庞国明-博客

此心用度八千遍,不曾厌倦


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

微服务Spring cloud经验总结系列(初级),第三篇:服务注册与发现 Eureka

发表于 2020-07-26 | 分类于 系统架构

VuePress

发表于 2019-02-03

VuePress

这篇文章主要是记录自己在使用VuePress过程中所遇到的问题以及如何一步一步的解决问题。

安装vuepress前,请确保你的 Node.js 版本 >= 8

全局安装

# 安装
yarn global add vuepress 或者:npm install -g vuepress

<span class="hljs-comment"># 新建一个 markdown 文件
echo <span class="hljs-string">'# Hello VuePress!' > README.md

<span class="hljs-comment"># 开始写作
vuepress dev .

<span class="hljs-comment"># 构建静态文件
vuepress build .</span></span></span></span></span></span></span></code>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

注意 :`vuepress dev .`和`vuepress build .`后面的`.`。

## 在现有项目中安装

<pre><code class="hljs dockerfile"><span class="hljs-comment"># 将 vuepress 作为一个本地依赖安装
yarn <span class="hljs-keyword">add<span class="bash"> -D vuepress 或者:npm install -D vuepress

<span class="hljs-comment"># 新建一个 docs 文件夹
mkdir docs

<span class="hljs-comment"># 新建一个 markdown 文件
echo <span class="hljs-string">'# Hello VuePress!' > docs/README.md

<span class="hljs-comment"># 开始写作
npx vuepress dev docs</span></span></span></span></span></span></span></code>

接着,在 package.json 里加一些脚本:

<pre><code class="hljs json">{
  <span class="hljs-attr">"scripts": {
    <span class="hljs-attr">"docs:dev": <span class="hljs-string">"vuepress dev docs",
    <span class="hljs-attr">"docs:build": <span class="hljs-string">"vuepress build docs"
  }
}</span></span></span></span></span></code>
1
2
3
4

开始写作

<pre><code class="hljs less"><span class="hljs-selector-tag">yarn <span class="hljs-selector-tag">docs<span class="hljs-selector-pseudo">:dev 或者:<span class="hljs-selector-tag">npm <span class="hljs-selector-tag">run <span class="hljs-selector-tag">docs<span class="hljs-selector-pseudo">:dev</span></span></span></span></span></span></span></code>

第一个坑:我的项目就是依赖webpack 3.6.0同时也是用npm安装依赖,然后继续使用npm安装vuepress,然后执行npx vuepress dev docs的时候报错了,上网查了好久也没有解决问题,最后使用yarn安装vuepress成功了。

如果你的现有项目依赖了 webpack 3.x,推荐使用 yarn而不是 npm 来安装 vuepress。

要生成静态的 HTML 文件,运行:

<pre><code class="hljs less"><span class="hljs-selector-tag">yarn <span class="hljs-selector-tag">docs<span class="hljs-selector-pseudo">:build 或者:<span class="hljs-selector-tag">npm <span class="hljs-selector-tag">run <span class="hljs-selector-tag">docs<span class="hljs-selector-pseudo">:build</span></span></span></span></span></span></span></code>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

默认情况下,文件将会被生成在 `.vuepress/dist`,也可以通过 `.vuepress/config.js` 中的 `dest` 字段来修改.

以上步骤都成功以后,就可以在浏览器总看到页面了,接下来就是对页面进行布局

## 主题配置

本文是根据VuePress默认主题配置

### 1.首页

在docs文件夹下创建`.vuepress文件夹`和`README.md文件`。(如果以及有了就不要再新建)
根目录下的README.md文件可以当作首页,在文件中加入下面文字:

<pre><code class="hljs yaml"><span class="hljs-meta">---
<span class="hljs-attr">home: <span class="hljs-literal">true
<span class="hljs-attr">actionText: <span class="hljs-string">快速上手 <span class="hljs-string">→
<span class="hljs-attr">actionLink: <span class="hljs-string">/guide/install/install
<span class="hljs-meta">---</span></span></span></span></span></span></span></span></span></code>

可以根据自己的需要添加、删除、修改,这就完成了首页的布局
actionLink: /guide/install/install就是首页后要显示的下一个页面

接下来在docs文件夹中创建guide文件夹(根据自己的需要命名)。这个文件夹中放的是markdown文件,每一个markdown文件对应一个页面。至于页面之间的跳转和页面导航栏和侧边栏布局在config.js文件中设置。
VuePress 网站必要的配置文件是 .vuepress/config.js,它应该导出一个 JavaScript 对象:

<pre><code class="hljs java"><span class="hljs-keyword">module.<span class="hljs-keyword">exports = {
    title: <span class="hljs-string">'VuePress',
    description: <span class="hljs-string">'VuePress',
}</span></span></span></span></code>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

对于上述的配置,运行`yarn docs:dev`,你应该能看到一个页面,它包含一个页头,里面包含一个标题和一个搜索框。

### 2.导航栏

可以通过 `themeConfig.nav` 增加一些导航栏链接:

<pre><code class="hljs groovy"><span class="hljs-comment">// .vuepress/config.js
module.exports = {
<span class="hljs-symbol"> themeConfig: {
<span class="hljs-symbol"> nav: [
{<span class="hljs-string">text: <span class="hljs-string">'指南',<span class="hljs-string">link:<span class="hljs-string">'/guide/install/install'}
]
}
}</span></span></span></span></span></span></span></code>

当你提供了一个 items 数组而不是一个单一的 link 时,它将显示为一个 下拉列表 :

<pre><code class="hljs groovy">module.exports = {
<span class="hljs-symbol">  themeConfig: {
<span class="hljs-symbol">    nav: [
      {
<span class="hljs-symbol">        text: <span class="hljs-string">'Languages',
<span class="hljs-symbol">        items: [
          { <span class="hljs-string">text: <span class="hljs-string">'Chinese', <span class="hljs-string">link: <span class="hljs-string">'/language/chinese/' },
          { <span class="hljs-string">text: <span class="hljs-string">'Japanese', <span class="hljs-string">link: <span class="hljs-string">'/language/japanese/' }
        ]
      }
    ]
  }
}</span></span></span></span></span></span></span></span></span></span></span></span></span></code>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

### 3.侧边栏

想要使侧边栏(Sidebar)生效,需要配置 `themeConfig.sidebar`

<pre><code class="hljs java"><span class="hljs-comment">// .vuepress/config.js
<span class="hljs-keyword">module.<span class="hljs-keyword">exports = {
themeConfig: {
sidebar: [
{
title: <span class="hljs-string">'开发指南',
collapsable: <span class="hljs-keyword">false, <span class="hljs-comment">//是否展开
},
[<span class="hljs-string">'./guide/install/install',<span class="hljs-string">'安装'],
[<span class="hljs-string">'./guide/started/started',<span class="hljs-string">'快速上手'],
{
title: <span class="hljs-string">'组件',
collapsable: <span class="hljs-keyword">false
},
[<span class="hljs-string">'./guide/icon/icon',<span class="hljs-string">'icon'],
]
}
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

可以省略 .md 拓展名,同时以 / 结尾的路径将会被视为 */README.md
如果想要显示地指定链接的文字,使用一个格式为 [link, text] 的数组。
具体配置可以根据官网配置:默认主题配置

这是浏览器显示效果:

1.png

现在页面基本也搭建完成,可以在页面之间进行切换。下一步是如何在markdown中使用vue组件,也就是在页面中展示自己的项目。

## 在markdown中使用Vue

在.vuepress中创建components文件夹。
所有在 .vuepress/components 中找到的 *.vue 文件将会自动地被注册为全局的异步组件。

如果需要引入静态文件,可以在.vuepress下新建public文件夹,里面可以放静态文件。

因为本文的案例是展示Icon图标,所有引入了svg.js,svg.js可以在http://www.iconfont.cn/中获取,本文使用## symbol引用具体方法请访问官网。放在public文件夹中,可以在components文件夹中的组件引入。

这是docs文件夹目录结构

2.png

<pre><code class="hljs css">.
└─ <span class="hljs-selector-class">.vuepress
   └─ <span class="hljs-selector-tag">components
      ├─ <span class="hljs-selector-tag">demo-1<span class="hljs-selector-class">.vue
      └─ <span class="hljs-selector-tag">Icon
         └─ <span class="hljs-selector-tag">vi-icon<span class="hljs-selector-class">.vue</span></span></span></span></span></span></span></code>
1
2
3
4
5

可以直接使用这些组件在任意的 Markdown 文件中(组件名是通过文件名取到的):

<pre><code class="hljs javascript"><demo<span class="hljs-number">-1/>
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">Icon-vi-icon/> <span class="hljs-comment">//文件名和组件名之间同`-`连接</span></span></span></span></span></code>

完成这一步以后就可以在页面中看到自己的组件在页面中展示了,但是在运行下面命令进行打包的时候会报错:
报错原因参考官网文档:浏览器的 API 访问限制

<pre><code class="hljs less"><span class="hljs-selector-tag">yarn <span class="hljs-selector-tag">docs<span class="hljs-selector-pseudo">:build 或者:<span class="hljs-selector-tag">npm <span class="hljs-selector-tag">run <span class="hljs-selector-tag">docs<span class="hljs-selector-pseudo">:build</span></span></span></span></span></span></span></code>
1
2
3
4
5
6

解决这个问题只需要在使用Vue组件的`markdown`文件中使用`<ClientOnly></ClientOnly>`将组件包裹起来。如:

<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">ClientOnly>
<span class="hljs-tag"><<span class="hljs-name">Icon-vi-icon/>
<span class="hljs-tag"></<span class="hljs-name">ClientOnly></span></span></span></span></span></span></code>

注意:在markdown文件中如果需要给组件名缩进,不要用tab键,会被当做markdown语法解析。

浏览器效果图

3.png

到这一步,基本上可以在页面中展示自己的组件。下一篇将继续写如何通过Vue组件实现跟:Element相似的效果。
通过VuePress管理项目文档(二)

Docker Compose安装以及入门

发表于 2019-02-01


Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用。

## Compose 简介

Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。Compose 定位是 「定义和运行多个 Docker 容器的应用(Defining and running multicontainer Docker applications)」,其前身是开源项目 Fig。

使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。

Compose 恰好满足了这样的需求。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。

Compose 中有两个重要的概念:

服务 ( service ):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例 项目 ( project ):由一组关联的应用容器组成的一个完整业务单元,在 dockercompose.yml 文件中定义。

Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。可见,一个项目可以由多个服务(容器)关联而成, Compose 面向项目进行管理

Compose 项目由 Python 编写,实现上调用了 Docker 服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理。

## 安装与卸载

Compose 可以通过 Python 的包管理工具 pip 进行安装,也可以直接下载编译好的二进制文件使用,甚至能够直接在 Docker 容器中运行。前两种方式是传统方式,适合本地环境下安装使用;最后一种方式则不破坏系统环境,更适合云计算场景。Docker for Mac 、 Docker for Windows 自带 docker-compose 二进制文件,安装 Docker 之后可以直接使用。Linux 系统请使用以下介绍的方法安装。

### 二进制包安装

在 Linux 上的也安装十分简单,从 官方 GitHub Release 处直接下载编译好的二进制文件即可。

例如,在 Linux 64 位系统上直接下载对应的二进制包。

sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-uname -s-uname -m > /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
1
2
3
4

对于卸载如果是二进制包方式安装的,删除二进制文件即可。

<pre><code class="hljs groovy">sudo rm <span class="hljs-regexp">/usr/local<span class="hljs-regexp">/bin/docker-compose</span></span></code>


### PIP 安装

这种方式是将 Compose 当作一个 Python 应用来从 pip 源中安装。执行安装命令:

sudo pip install -U docker-compose
1
2
3
4

使用PIP安装的时候,卸载可以使用如下命令:

<pre><code class="hljs nginx"><span class="hljs-attribute">sudo pip uninstall docker-compose</span></code>


## 简单入门

下面我们模拟一个网站,该网站的作用是能够记录页面的访问次数。我们使用Flask开发,缓存使用redis

### 编写wen应用

新建一个文件夹web,在该文件夹下创建app.py文件,内容如下:

from flask import Flask
from redis import Redis

app = Flask(name)
redis = Redis(host=“redis”,port=6379)

@app.route(“/“)
def hello():
count = redis.incr(‘hits’)
return ‘hello world! {}’.format(count)

if name == “main“:
app.run(host=“0.0.0.0”,debug=True)
1
2
3
4
5
6
7
8

### 编写Dockerfile文件

<pre><code class="hljs dockerfile"><span class="hljs-keyword">FROM python:<span class="hljs-number">3.6-alpine
<span class="hljs-keyword">ADD<span class="bash"> . /code
<span class="hljs-keyword">WORKDIR<span class="bash"> /code
<span class="hljs-keyword">RUN<span class="bash"> pip install redis flask
<span class="hljs-keyword">CMD<span class="bash"> [<span class="hljs-string">"python",<span class="hljs-string">"app.py"]</span></span></span></span></span></span></span></span></span></span></span></span></code>


### docker-compose.yml

编写 docker-compose.yml 文件,这个是 Compose 使用的主模板文件。

version: ‘3’
services:
web:
build: .
ports:
- “5000:5000”
redis:
images: “redis:alpine”
1
2
3
4

### 运行 compose 项目

<pre><code class="hljs">docker-compose up</code>


此时访问本地 5000 端口,每次刷新页面,计数就会加 1。

每天进步一点点

PDF.js实现个性化PDF渲染(文本复制)

发表于 2019-01-31

我肥来啦😁。看到Redux教程突破3w的浏览量,小窃喜,很高兴自己的文章能够帮助到大家。

这次重返,依然带给大家一个小指南,也是最近工作中遇到的一个小case。

前不久,产品经理提出要在界面上优雅地展示PDF文档,当即就有了两种实现方式:

实现方式一
使用embed标记来使用浏览器自带的pdf工具。

这种实现方式优缺点都很明显:
优点:自带“打印”,“搜索”,“翻页”等功能,强大且实现方便。
缺点:不同浏览器的pdf工具样式不一,且无法满足个性化需求,比如:禁止打印,下载等。

我们的产品经理是挑剔的😒,于是…

实现方式二
使用Mozilla的PDF.js,自定义展示PDF。

下面我们就细致讲述一下使用PDF.js过程中遇到的问题。主要包括:

  • 基础功能集成
  • 使用Text-Layers渲染

什么是PDF.JS

PDF.js是基于HTML5技术构建的,用于展示可移植文档格式的文件(PDF),它可以在现代浏览器中使用且无需安装任何第三方插件。

基础功能集成

1️⃣引用

首先,引用PDF.js就遇到了问题,官网中提到通过CDN引用或者下载源码至本地。
而我们并不想污染我们的index.html并且希望可以对每一个引用的框架有统一的版本管理。于是,我们搜寻到一个包:pdfjs-dist。

通过npm install pdfjs-dist,我们引入了PDF.js。

基础功能有两个必须引用的文件:

  • pdf.js
  • pdf.worker.js

如果使用CDN的方式,直接引用如下对应文件即可:

  • https://mozilla.github.io/pdf…
  • https://mozilla.github.io/pdf…

如果使用npm的方式,则在需要使用PDF.js的文件中如下引用:

import PDFJS from ‘pdfjs-dist’;

PDFJS.GlobalWorkerOptions.workerSrc = <span class="hljs-string">'pdfjs-dist/build/pdf.worker.js';</span></span></span></span></code>
1
2
3
4
5
6
7
8
9
10
11
12

这两个文件包含了获取、解析和展示PDF文档的方法,但是解析和渲染PDF需要较长的时间,可能会阻塞其它JS代码的运行。

为解决该问题,pdf.js依赖了HTML5引入的[Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers)——通过从主线程中移除大量CPU操作(如解析和渲染)来提升性能。

PDF.js的API都会返回一个Promise,使得我们可以优雅的处理异步操作。

2️⃣**使用**

首先,我们需要在HTML中添加`<canvas>`元素以渲染PDF:

<pre class="xml hljs"><code class="html"><span class="hljs-tag"><<span class="hljs-name">canvas <span class="hljs-attr">id=<span class="hljs-string">"pdf-canvas"><span class="hljs-tag"></<span class="hljs-name">canvas></span></span></span></span></span></span></code>

然后添加渲染PDF的js代码:

<pre class="javascript hljs"><code class="javascript"><span class="hljs-keyword">var url = <span class="hljs-string">'Helloworld.pdf';

PDFJS.getDocument(url).then(<span class="hljs-function">(<span class="hljs-params">pdf) => {
    <span class="hljs-keyword">return pdf.getPage(<span class="hljs-number">1);
}).then(<span class="hljs-function">(<span class="hljs-params">page) => {
    <span class="hljs-comment">// 设置展示比例
    <span class="hljs-keyword">var scale = <span class="hljs-number">1.5;
    <span class="hljs-comment">// 获取pdf尺寸
    <span class="hljs-keyword">var viewport = page.getViewport(scale);
    <span class="hljs-comment">// 获取需要渲染的元素
    <span class="hljs-keyword">var canvas = <span class="hljs-built_in">document.getElementById(<span class="hljs-string">'pdf-canvas');
    <span class="hljs-keyword">var context = canvas.getContext(<span class="hljs-string">'2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    <span class="hljs-keyword">var renderContext = {
        <span class="hljs-attr">canvasContext: context,
        <span class="hljs-attr">viewport: viewport
    };

    page.render(renderContext);
});</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

现在,PDF已经成功渲染在界面上了。我们来分析一下使用到的函数:

`getDocument()`:用于异步获取PDf文档,发送多个Ajax请求以块的形式下载文档。它返回一个Promise,该Promise的成功回调传递一个对象,该对象包含PDF文档的信息,该回调中的代码将在完成PDf文档获取时执行。

`getPage()`:用于获取PDF文档中的各个页面。

`getViewport()`:针对提供的展示比例,返回PDf文档的页面尺寸。

`render()`:渲染PDF。

到这里,基本功能告一段落了。
满心欢喜准备上线的时候,产品经理提出了另一个需求:文本复制。
然鹅。。。翻了好几遍官方文档,也没有找到文本复制的方法,并且stackoverflow上有很多类似的问题。
在不断的尝试下,我们发现了`Text-Layer`。

#### 使用Text-Layers渲染

PDF.js支持在使用Canvas渲染的PDF页面上渲染文本图层。然而,这个功能需要用到额外的两个文件:`text_layer_builder.js`和`text_layer_builder.css`。我们可以在GitHub的repo中获取到。

如果是使用npm,则需要做如下引用:

<pre class="javascript hljs"><code class="javascript"><span class="hljs-keyword">import { TextLayerBuilder } <span class="hljs-keyword">from <span class="hljs-string">'pdfjs-dist/web/pdf_viewer';
<span class="hljs-keyword">import <span class="hljs-string">'pdfjs-dist/web/pdf_viewer.css';</span></span></span></span></span></code>

现在,我们开始实现文本复制功能。

首先,创建渲染需要用到DOM节点:

<pre class="xml hljs"><code class="html"><span class="hljs-tag"><<span class="hljs-name">div <span class="hljs-attr">id=<span class="hljs-string">"container"><span class="hljs-tag"></<span class="hljs-name">div></span></span></span></span></span></span></code>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

`div#container`为最外层节点,在该div中,我们会为PDF的每个页面创建自己的`div`,在每个页面的`div`中,都会有`Canvas`元素。

接着,我们修改JS代码:

<pre class="javascript hljs"><code class="javascript"><span class="hljs-keyword">var container, pageDiv;

<span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">getPDF(<span class="hljs-params">url) {
PDFJS.getDocument(url).then(<span class="hljs-function">(<span class="hljs-params">pdf) => {
pdfDoc = pdf;
container = <span class="hljs-built_in">document.getElementById(<span class="hljs-string">'container');
<span class="hljs-keyword">for (<span class="hljs-keyword">var i = <span class="hljs-number">1; i<= pdf.numPages; i++) {
renderPDF(i);
}
})
}

<span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">renderPDF(<span class="hljs-params">num) {
pdf.getPage(num).then(<span class="hljs-function">(<span class="hljs-params">page) => {
<span class="hljs-keyword">var scale = <span class="hljs-number">1.5;
<span class="hljs-keyword">var viewport = page.getViewport(scale);
pageDiv = <span class="hljs-built_in">document.createElement(<span class="hljs-string">'div');
pageDiv.setAttribute(<span class="hljs-string">'id', <span class="hljs-string">'page-' + (page.pageIndex + <span class="hljs-number">1));
pageDiv.setAttribute(<span class="hljs-string">'style', <span class="hljs-string">'position: relative');
container.appendChild(pageDiv);
<span class="hljs-keyword">var canvas = <span class="hljs-built_in">document.createElement(<span class="hljs-string">'canvas');
pageDiv.appendChild(canvas);
<span class="hljs-keyword">var context = canvas.getContext(<span class="hljs-string">'2d');
canvas.height = viewport.height;
canvas.width = view.width;

<span class="hljs-keyword">var renderContext = {
<span class="hljs-attr">canvasContext: context,
<span class="hljs-attr">viewport: viewport
};

page.render(renderContext);
});
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

以上代码只是实现了多页渲染,接下来,开始渲染文本图层。我们需要将page.render(renderContext)修改为以下代码:

<pre class="javascript hljs"><code class="javascript">page.render(renderContext).then(<span class="hljs-function"><span class="hljs-params">() => {
    <span class="hljs-keyword">return page.getTextContent();
}).then(<span class="hljs-function">(<span class="hljs-params">textContent) => {
    <span class="hljs-comment">// 创建文本图层div
    <span class="hljs-keyword">const textLayerDiv = <span class="hljs-built_in">document.createElement(<span class="hljs-string">'div');
    textLayerDiv.setAttribute(<span class="hljs-string">'class', <span class="hljs-string">'textLayer');
    <span class="hljs-comment">// 将文本图层div添加至每页pdf的div中
    pageDiv.appendChild(textLayerDiv);

    <span class="hljs-comment">// 创建新的TextLayerBuilder实例
    <span class="hljs-keyword">var textLayer = <span class="hljs-keyword">new TextLayerBuilder({
        <span class="hljs-attr">textLayerDiv: textLayerDiv,
        <span class="hljs-attr">pageIndex: page.pageIndex,
        <span class="hljs-attr">viewport: viewport
    });

    textLayer.setTextContent(textContent);

    textLayer.render();
});</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>```

我们依旧来讲解以下用到的几个关键函数:

page.render():该函数返回一个当PDF页面成功渲染到界面上时解析的promise,我们可以使用成功回调来渲染文本图层。

page.getTextContent():该函数的成功回调会返回PDF页面上的文本片段。

TextLayerBuilder:该类的实例有两个重要的方法。setTextContent()用于设置page.getTextContent()函数返回的文本片段;render()用于渲染文本图层。

Bingo😎!通过以上改造,文本复制功能就实现了。官方文档上可没有这个小技巧哦。

PDF.js是一个很棒的工具,但无奈文档写的较为精简,需要开发人员不断探索PDF.js的强大功能。

如果这篇文章有帮助到您,记得点赞咯👍!

超详细动手搭建一个Vuepress站点及开启PWA与自动部署

发表于 2019-01-29




# 超详细动手搭建一个Vuepress站点及开启PWA与自动部署

> 五一之前就想写一篇关于Vuepress的文章,结果朋友结婚就不了了之了。
>
> 记得最后一定要看注意事项!

## Vuepress介绍

官网:https://vuepress.vuejs.org/

类似hexo一个极简的静态网站生成器,用来写技术文档不能在爽。当然搭建成博客也不成问题。

## Vuepress特点

响应式,也可以自定义主题与hexo类似 内置markdown(还增加了一些扩展),并且可以在其使用Vue组件
Google Analytics 集成 PWA 自动生成Service Worker

## 快速上手

### 安装

初始化项目

yarn init -y
# 或者 npm init -y
1
2
3
4
5
6

安装vuepress

<pre class="hljs shell"><code class="shell">yarn add -D vuepress
<span class="hljs-meta">#<span class="bash"> 或者 npm install -D vuepress
</span></span></code>


全局安装vuepress

yarn global add vuepress
# 或者 npm install -g vuepress
1
2
3
4
5

新建一个docs文件夹

<pre class="hljs shell"><code class="shell">mkdir docs
</code>


设置下package.json

{
“scripts”: {
“docs:dev”: “vuepress dev docs”,
“docs:build”: “vuepress build docs”
}
}
1
2
3
4
5

### 写作

<pre class="hljs shell"><code class="shell">yarn docs:dev # 或者:npm run docs:dev
</code>


也就是运行开发环境,直接去docs文件下书写文章就可以,打开http://localhost:8080/可以预览






image

### 构建

build生成静态的HTML文件,默认会在 .vuepress/dist 文件夹下

yarn docs:build # 或者:npm run docs:build
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

## 基本配置

在 `.vuepress`目录下新建一个`config.js`,他导出一个对象

一些配置可以参考[官方文档](https://link.jianshu.com?t=https%3A%2F%2Fvuepress.vuejs.org%2Fconfig%2F%23base),这里我配置常用及必须配置的

### 网站信息

<pre class="hljs javascript"><code class="javascript"><span class="hljs-built_in">module.exports = {
<span class="hljs-attr">title: <span class="hljs-string">'游魂的文档',
<span class="hljs-attr">description: <span class="hljs-string">'Document library',
<span class="hljs-attr">head: [
[<span class="hljs-string">'link', { <span class="hljs-attr">rel: <span class="hljs-string">'icon', <span class="hljs-attr">href: <span class="hljs-string">`/favicon.ico` }],
],
}
</span></span></span></span></span></span></span></span></span></span></span></code>


### 导航栏配置

module.exports = {
themeConfig: {
nav: [
{ text: ‘主页’, link: ‘/‘ },
{ text: ‘前端规范’, link: ‘/frontEnd/‘ },
{ text: ‘开发环境’, link: ‘/development/‘ },
{ text: ‘学习文档’, link: ‘/notes/‘ },
{ text: ‘游魂博客’, link: ‘https://www.iyouhun.com' },
// 下拉列表的配置
{
text: ‘Languages’,
items: [
{ text: ‘Chinese’, link: ‘/language/chinese’ },
{ text: ‘English’, link: ‘/language/English’ }
]
}
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

如图:

<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> 
<div class="image-view" data-width="556" data-height="83">![](http://pangguoming.com/blog/images/d0397c5a-09c6-4d33-bdd8-fd95ecb6d468.jpg)

<div class="image-caption">image

### 侧边栏配置

可以省略`.md`扩展名,同时以 `/` 结尾的路径将会被视为 `*/README.md`

<pre class="hljs javascript"><code class="javascript"><span class="hljs-built_in">module.exports = {
<span class="hljs-attr">themeConfig: {
<span class="hljs-attr">sidebar: {
<span class="hljs-string">'/frontEnd/': genSidebarConfig(<span class="hljs-string">'前端开发规范'),
}
}
}
</span></span></span></span></span></code>


上面封装的genSidebarConfig函数

function genSidebarConfig(title) {
return [{
title,
collapsable: false,
children: [
‘’,
‘html-standard’,
‘css-standard’,
‘js-standard’,
‘git-standard’
]
}]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

支持侧边栏分组(可以用来做博客文章分类) collapsable是当前分组是否展开

<pre class="hljs javascript"><code class="javascript"><span class="hljs-built_in">module.exports = {
<span class="hljs-attr">themeConfig: {
<span class="hljs-attr">sidebar: {
<span class="hljs-string">'/note': [
{
<span class="hljs-attr">title:<span class="hljs-string">'前端',
<span class="hljs-attr">collapsable: <span class="hljs-literal">true,
<span class="hljs-attr">children:[
<span class="hljs-string">'/notes/frontEnd/VueJS组件编码规范',
<span class="hljs-string">'/notes/frontEnd/vue-cli脚手架快速搭建项目',
<span class="hljs-string">'/notes/frontEnd/深入理解vue中的slot与slot-scope',
<span class="hljs-string">'/notes/frontEnd/webpack入门',
<span class="hljs-string">'/notes/frontEnd/PWA介绍及快速上手搭建一个PWA应用',
]
},
{
<span class="hljs-attr">title:<span class="hljs-string">'后端',
<span class="hljs-attr">collapsable: <span class="hljs-literal">true,
<span class="hljs-attr">children:[
<span class="hljs-string">'notes/backEnd/nginx入门',
<span class="hljs-string">'notes/backEnd/CentOS如何挂载磁盘',
]
},
]
}
}
}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>


如图:






成品图

## 默认主题修改

### 主题色修改

在.vuepress目录下的创建一个override.styl文件

$accentColor = #3eaf7c // 主题色
$textColor = #2c3e50 // 文字颜色
$borderColor = #eaecef // 边框颜色
$codeBgColor = #282c34 // 代码背景颜色
1
2
3
4
5
6
7
8
9

### 自定义页面类

有时需要在不同的页面应用不同的css,可以先在该页面中声明

<pre class="hljs yaml"><code class="yaml"><span class="hljs-meta">---
<span class="hljs-attr">pageClass: <span class="hljs-string">custom-page-class
<span class="hljs-meta">---
</span></span></span></span></code>


然后在override.styl中书写

.theme-container.custom-page-class {
/ 特定页面的 CSS /
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

## PWA设置

设置serviceWorker为true,然后提供Manifest 和 icons,可以参考我之前的《[PWA介绍及快速上手搭建一个PWA应用](https://www.jianshu.com/p/fad8aa9e277f)》

<pre class="hljs javascript"><code class="javascript"><span class="hljs-built_in">module.exports = {
<span class="hljs-attr">head: [
[<span class="hljs-string">'link', { <span class="hljs-attr">rel: <span class="hljs-string">'icon', <span class="hljs-attr">href: <span class="hljs-string">`/favicon.ico` }],
<span class="hljs-comment">//增加manifest.json
[<span class="hljs-string">'link', { <span class="hljs-attr">rel: <span class="hljs-string">'manifest', <span class="hljs-attr">href: <span class="hljs-string">'/manifest.json' }],
],
<span class="hljs-attr">serviceWorker: <span class="hljs-literal">true,
}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>


## 部署上线

### 设置基础路径

在config.js设置base
例如:你想要部署在https://foo.github.io 那么设置base为/,base默认就为/,所以可以不用设置
想要部署在https://foo.github.io/bar/,那么 base 应该被设置成 "/bar/"

module.exports = {
base: ‘/documents/‘,
}
1
2
3
4
5
6
7
8
9
10

`base` 将会自动地作为前缀插入到所有以 `/` 开始的其他选项的链接中,所以你只需要指定一次。

### 构建与自动部署

用[gitHub](https://link.jianshu.com?t=https%3A%2F%2Fgithub.com)的pages或者[coding](https://link.jianshu.com?t=https%3A%2F%2Fcoding.net%2Fr%2FO5YOFA)的pages都可以,也可以搭建在自己的服务器上。
将`dist`文件夹中的内容提交到git上或者上传到服务器就好

<pre class="hljs shell"><code class="shell">yarn docs:build # 或者:npm run docs:build
</code>


> 另外可以弄一个脚本,设置持续集成,在每次 push 代码时自动运行脚本

deploy.sh

#!/usr/bin/env sh

# 确保脚本抛出遇到的错误
set -e

# 生成静态文件
npm run docs:build

# 进入生成的文件夹
cd docs/.vuepress/dist

# 如果是发布到自定义域名
# echo ‘www.example.com' > CNAME

git init
git add -A
git commit -m ‘deploy’

# 如果发布到 https://.github.io
# git push -f git@github.com:/.github.io.git master

# 如果发布到 https://.github.io/
git push -f git@github.com:/.git master:gh-pages

cd -
`

## 注意事项(坑)

把你想引用的资源都放在.vuepress目录下的public文件夹 给git仓库绑定了独立域名后,记得修改base路径
设置侧边栏分组后默认会自动生成 上/下一篇链接 设置了自动生成侧边栏会把侧边栏分组覆盖掉
* 设置PWA记得开启SSL




PPTP服务端与客户端 修改默认PPTP默认端口1723

发表于 2019-01-26

linux pptp服务端:
我们在Linux下建立的pptpd端口号默认是1723,有时候这个端口并不是那么的好用,不是麽?
所以服务端修改端口号比较简单

修改 /etc/services 文件
查找 1723,然后将其修改为你想修改的数值,重启 pptpd即可.

Windows PPTP客户端:

1、找到 C:\WINDOWS\system32\drivers\etc,修改services文件,修改里面的VPN(PPTP)端口1723为你设定的端口

2、系统自带的东西,修改配置参数当然就得进注册表了。进入HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE- BFC1-08002bE10318}项,其中有类似0000、0001、0002……这样的子项,每个子项都对应一个网适配器的配置。逐一打开这些子项,找到其中字段DriverDesc值为WAN Miniport (PPTP)的子项,例如我找到的是0003。在这个子项里的TcpPortNumber的值就是pptp vpn所使用的端口,双击修改其值,选择基数为十进制,修改成所需要的值确认即可。重启机器后,修改生效。

centos7防火墙iptables开放常用端口

发表于 2019-01-26
  1. 清除所有规则:

iptables -F

1
2
3
4

2. 开放常用tcp端口:
<pre><code class="hljs css"><span class="hljs-selector-tag">iptables <span class="hljs-selector-tag">-I <span class="hljs-selector-tag">INPUT <span class="hljs-selector-tag">-p <span class="hljs-selector-tag">tcp <span class="hljs-selector-tag">-m <span class="hljs-selector-tag">multiport <span class="hljs-selector-tag">--dports 20,21,22,3690,80,443,4443,8023,8888,25,110,30000<span class="hljs-selector-pseudo">:30999 <span class="hljs-selector-tag">-j <span class="hljs-selector-tag">ACCEPT
<span class="hljs-selector-tag">iptables <span class="hljs-selector-tag">-I <span class="hljs-selector-tag">OUTPUT <span class="hljs-selector-tag">-p <span class="hljs-selector-tag">tcp <span class="hljs-selector-tag">-m <span class="hljs-selector-tag">multiport <span class="hljs-selector-tag">--sports 20,21,22,3690,80,443,4443,8023,8888,25,110,30000<span class="hljs-selector-pseudo">:30999 <span class="hljs-selector-tag">-j <span class="hljs-selector-tag">ACCEPT</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

3.  开放常用udp端口:
<pre><code class="hljs sql">iptables  -I  INPUT  -p  udp  -m  multiport  <span class="hljs-comment">--dports  53,123,8571,8888  -j  ACCEPT
iptables  -I  OUTPUT  -p  udp  -m  multiport  <span class="hljs-comment">--sports  53,123,8571,8888  -j  ACCEPT</span></span></code>
1
2
3
4

4. 开放特殊udp端口(如:dns):
<pre><code class="hljs sql">iptables -I INPUT -p udp <span class="hljs-comment">--sport 53 -j ACCEPT
iptables -I OUTPUT -p udp <span class="hljs-comment">--dport 53 -j ACCEPT</span></span></code>
5. 开放vrrp协议: <pre><code class="hljs nginx"><span class="hljs-attribute">iptables -I INPUT -p vrrp -j ACCEPT</span></code>
1
2
3
4

6. 允许服务器互ping:
<pre><code class="hljs nginx"><span class="hljs-attribute">iptables -A OUTPUT -p icmp -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT</span></code>
7. 允许握手成功的数据通过: <pre><code class="hljs perl">iptables -I INPUT -p tcp -<span class="hljs-keyword">m <span class="hljs-keyword">state --<span class="hljs-keyword">state RELATED,ESTABLISHED -j ACCEPT iptables -I OUTPUT -p tcp -<span class="hljs-keyword">m <span class="hljs-keyword">state --<span class="hljs-keyword">state RELATED,ESTABLISHED -j ACCEPT</span></span></span></span></span></span></code>
1
2
3
4
5

8. 设置默认关闭所有端口:
<pre><code class="hljs sql">iptables -P FORWARD <span class="hljs-keyword">DROP
iptables -P <span class="hljs-keyword">OUTPUT <span class="hljs-keyword">ACCEPT
iptables -P <span class="hljs-keyword">INPUT <span class="hljs-keyword">DROP</span></span></span></span></span></code>
9. 防syn***: <pre><code class="hljs sql">iptables -N syn-flood iptables -A INPUT -p tcp <span class="hljs-comment">--syn -j syn-flood iptables -I syn-flood -p tcp -m limit <span class="hljs-comment">--limit 3/s --limit-burst 6 -j RETURN iptables -A syn-flood -j REJECT</span></span></code>
1
2
3
4
5
6

10. 防ddos***:
<pre><code class="hljs sql">iptables -A INPUT -i eth0 -p tcp <span class="hljs-comment">--syn -m connlimit --connlimit-above 15 -j DROP
iptables -A INPUT -p tcp -m state <span class="hljs-comment">--state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp <span class="hljs-comment">--syn -m limit --limit 12/s --limit-burst 24 -j ACCEPT
iptables -A FORWARD -p tcp <span class="hljs-comment">--syn -m limit --limit 1/s -j ACCEPT</span></span></span></span></code>
11. 防cc***: <pre><code class="hljs cs">iptables -I INPUT -p tcp --dport <span class="hljs-number">80 -m connlimit --connlimit-above <span class="hljs-number">50 -j REJECT <span class="hljs-meta"># 允许单个IP的最大连接数为30 iptables -A INPUT -p tcp --dport <span class="hljs-number">80 -m recent --name BAD_HTTP_ACCESS --update --seconds <span class="hljs-number">60 --hitcount <span class="hljs-number">30 -j REJECT iptables -A INPUT -p tcp --dport <span class="hljs-number">80 -m recent --name BAD_HTTP_ACCESS --<span class="hljs-keyword">set -j ACCEPT <span class="hljs-meta">#单个IP在60秒内只允许最多新建30个连接</span></span></span></span></span></span></span></span></span></code>
1
2
3

12. 保存:
<pre><code class="hljs javascript">iptables-save > <span class="hljs-regexp">/etc/sysconfig/iptables</span></code>
</pre></pre></pre></pre></pre></pre></pre></pre></pre></pre></pre>

PDF.js 分片下载的介绍2:分片下载demo

发表于 2019-01-25

上一个章节,简要说了以下分片下载的几个特性。今天主要用示例说明一下pdf.js分片下载。

服务器环境:
php7.2
nginx 1.14
ubuntu 18.04
测试浏览器:谷歌浏览器 70.0.3538.110(

第一个场景,直接使用pdf 文件
1.1 代码如下:注意路径使用的是pdf 文件的物理路径

$filePath = ‘…/doc/big.pdf’;
这里是举例,这样作有一个明显的缺点,就是容易被盗链
getDocument 方法中的 rangeChunkSize 参数,就是设置分块大小,默认是64k,可以修改这个数字,来改变
这个例子使用的 1664k ,1m 左右来分片,方便测试。您可以根据具体情况,来调整
PDFJS.getDocument({url:url,rangeChunkSize:6553616,disableAutoFetch:0}).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

<html>
<head><title>pdf.js展示1,上一页,下一页</title></head>
<h1>PDF.js Previous/Next example</h1>
<div>
<button id="prev">Previous</button>
<button id="next">Next</button>     <span>Page: <span id="page_num"></span> / <span
id="page_count"></span></span></div>
<canvas id="the-canvas"></canvas>
<script src="../js/pdfjs/pdf.js"></script>
<script src="../js/pdfjs/pdf.worker.js"></script>
<script>
var url = '../doc/big.pdf';

var pdfDoc = null,
pageNum = 1,
pageRendering = false,
pageNumPending = null,
scale = 0.8,
canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');

/**
* Get page info from document, resize canvas accordingly, and render page.
* @param num Page number.
*/
function renderPage(num) {
pageRendering = true;
// Using promise to fetch the page
pdfDoc.getPage(num).then(function (page) {
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;

// Render PDF page into canvas context
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
var renderTask = page.render(renderContext);

// Wait for rendering to finish
renderTask.promise.then(function () {
pageRendering = false;
if (pageNumPending !== null) {
// New page rendering is pending
renderPage(pageNumPending);
pageNumPending = null;
}
});
});

// Update page counters
document.getElementById('page_num').textContent = num;
}

/**
* If another page rendering in progress, waits until the rendering is
* finised. Otherwise, executes rendering immediately.
*/
function queueRenderPage(num) {
if (pageRendering) {
pageNumPending = num;
} else {
renderPage(num);
}
}

/**
* Displays previous page.
*/
function onPrevPage() {
if (pageNum <= 1) {
return;
}
pageNum--;
queueRenderPage(pageNum);
}

document.getElementById('prev').addEventListener('click', onPrevPage);

/**
* Displays next page.
*/
function onNextPage() {
if (pageNum >= pdfDoc.numPages) {
return;
}
pageNum++;
queueRenderPage(pageNum);
}

document.getElementById('next').addEventListener('click', onNextPage);

/**
* Asynchronously downloads PDF.
*/
PDFJS.getDocument({url:url,rangeChunkSize:65536*16,disableAutoFetch:0}).then(function(pdfDoc_) {
pdfDoc = pdfDoc_;
document.getElementById('page_count').textContent = pdfDoc.numPages;

// Initial/first page rendering
renderPage(pageNum);
});
</script>
</html>

1.2今天第一加载:发现没有出现分片效果。如果您也遇到这种情况,不要着急,很大程度是因为浏览器缓存
在这里插入图片描述
1.3 在浏览器中,安Ctrl+alt+delte 键,清除缓存

在这里插入图片描述
1.4 清除缓存后,再次刷新页面,发现分片下载功能出现了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<pre class="brush:html;gutter:true;">后台代码

<?php
$filePath = '../doc/big.pdf';

//普通的方式处理包装pdf文件
download_file($filePath);

function download_file($file, $fname = 'chunk.pdf')
{
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment;filename=$fname");

echo(file_get_contents($file));
}

前台js 调用代码

1
2
3
4
5
6
7
8
9
10
11
12
<pre class="brush:html;gutter:true;">  。。。。。
var url = 'download.php';

var pdfDoc = null,
pageNum = 1,
pageRendering = false,
pageNumPending = null,
scale = 0.8,
canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');

。。。。

2.2 经过清理缓存,发现无法达到分片的效果。
在这里插入图片描述

初步总结如下,常规的附件处理方式,会影响分片下载的效果

## 场景3:使用php 结合httprange,实现分片的效果

3.1 这里是从网上搜集到的分片下载php 函数

代码的核心是,增加head 头,开启分片 Header(“Accept-Ranges: bytes”); 至于 Http range 如何计算,就比较繁琐了,这里就不详细介绍了。有兴趣的可以去百度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<pre class="brush:html;gutter:true;"><?php
$filePath = '../doc/big.pdf';

//分片下载
chunk_download_file($filePath);

/**
* 分篇下载的汉书
*
* @param $file
* @param $fname
*/
function chunk_download_file($file, $fname = 'chunk.pdf')
{
$fhandle = fopen($file, 'rb');//文件句柄
$fsize = filesize($file);//文件大小

//断点续传和整个文件下载的判断,支持多段下载
if (!empty($_SERVER['HTTP_RANGE'])) {
$range = str_replace("=", "-", $_SERVER['HTTP_RANGE']);
$match = explode("-", $range);
$start = $match[1];
$end = !empty($match[2]) ? $match[2] : $fsize - 1;
} else {
$start = 0;
$end = $fsize - 1;
}

if (($end - $start) < ($fsize - 1)) {
fseek($fhandle, $start);
header("HTTP/1.1 206 Partial Content");
header("Content-Length: " . ($end - $start + 1));
header("Content-Range: bytes " . $start . "-" . $end . "/" . $fsize);
} else {
header("HTTP/1.1 200 OK");
header("Content-Length: $fsize");
Header("Accept-Ranges: bytes");
header("Content-Range: bytes " . $start . "-" . $end . "/" . $fsize);
}

header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment;filename=$fname");

if (!feof($fhandle)) {
set_time_limit(0);
$buffer = fread($fhandle, $end - $start + 1);
echo $buffer;
flush();
ob_flush();
}
}

demo 下载路径:
https://download.csdn.net/download/niedewang/10804164

3.2 清理调浏览器缓存,发现这种方式可以达到分片下载的效果

经过测试,谷歌浏览器支持的很好,如上图所示,截图就是使用的谷歌浏览器。
但是firefox 在这种场景下,分片效果不理想。具体原因未知

简要的总结
1:前期承诺的demo 放出来了,blog貌似会清理连接地址,不知道是否会删除
2:使用pdf 真实文件路径,分片兼容性最好。但是地址容易泄漏
3:如果使用php 处理,一般的处理程序,不能达到分片效果。需要结合http range特性,但是不知道什么原因,firefox测试下来,效果不好。谷歌浏览器支持的较好,好消息是谷歌浏览器现在占用量是最大的。

4:后面有时间了,会介绍以下使用 x-sendfile 的方式处理附件,无论性能还是兼容性都比php 处理要好

作者:只看远方
来源:CSDN
原文:https://blog.csdn.net/niedewang/article/details/84576969
版权声明:本文为博主原创文章,转载请附上博文链接!

使用 JMeter 进行压力测试

发表于 2019-01-21

一.前言

压力测试是每一个Web应用程序上线之前都需要做的一个测试,他可以帮助我们发现系统中的瓶颈问题,减少发布到生产环境后出问题的几率;预估系统的承载能力,使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步骤,下面我带大家来使用一款压力测试工具JMeter。

二.关于JMeter

Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器, 等等。JMeter 可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序返回了你期望的结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。
Apache jmeter 可以用于对静态的和动态的资源(文件,Servlet,Perl脚本,java 对象,数据库和查询,FTP服务器等等)的性能进行测试。它可以用于对服务器、网络或对象模拟繁重的负载来测试它们的强度或分析不同压力类型下的整体性能。你可以使用它做性能的图形分析或在大并发负载测试你的服务器/脚本/对象。

官网:http://jmeter.apache.org/download_jmeter.cgi

这里我选用了 4.0 版本的二进制包:http://mirror.bit.edu.cn/apache//jmeter/binaries/apache-jmeter-4.0.zip

更多内容介绍 https://baike.baidu.com/item/Jmeter/3104456

三.准备工作

因为JMeter是使用JAVA写的,所以使用JMeter之前,先安装JAVA环境,本文就不讲不如安装JAVA环境了。.

JAVA环境变量配置:https://jingyan.baidu.com/article/fd8044fa2c22f15031137a2a.html

解压下载的二进制包,进入bin目录,使用jmeter.bat启动程序。

启动之后会有两个窗口,一个cmd窗口,一个JMeter的 GUI。前面不要忽略CMD窗口的提示信息:

JMeter:

CMD窗口的提示信息

================================================================================
Don’t use GUI mode for load testing !, only for Test creation and Test debugging.
For load testing, use NON GUI Mode:
jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
& increase Java Heap to meet your test requirements:
Modify current env variable HEAP=”-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m” in the jmeter batch file
Check : https://jmeter.apache.org/usermanual/best-practices.html
================================================================================

1
2
3
4

上面的意思就是:不要使用GUI运行压力测试,GUI仅用于压力测试的创建和调试;执行压力测试请不要使用GUI。使用下面的命令来执行测试:

<pre class="shell"><code class="hljs"> jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]</code>

并且修改JMeter批处理文件的环境变量:HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"

### 更改语言为中文

官方默认为我们提供了简体中文。通过 【Options】->【Choose Language】变更为简体中文

## 四.创建测试

### 1.创建线程组

在“测试计划”上右键 【添加】–>【Threads(Users)】–>【线程组】。

设置线程数和循环次数。我这里设置线程数为500,循环一次。

### 2.配置元件

在我们刚刚创建的线程组上右键 【添加】–>【配置元件】–>【HTTP请求默认值】。

配置我们需要进行测试的程序协议、地址和端口

当所有的接口测试的访问域名和端口都一样时,可以使用该元件,一旦服务器地址变更,只需要修改请求默认值即可。

### 3.构造HTTP请求

在“线程组”右键 【添加-】->【samlper】–>【HTTP 请求】设置我们需要测试的API的请求路径和数据。我这里是用的json

### 4.添加HTTP请求头

在我们刚刚创建的线程组上右键 【添加】–>【配置元件】–>【HTTP信息头管理器】。

因为我要传输的数据为json,所以设置一个 Content-Type:application/json

### 5.添加断言

在我们刚刚创建的线程组上右键 【添加】–>【断言】–>【响应断言】。

根据响应的数据来判断请求是否正常。我在这里只判断的响应代码是否为200。还可以配置错误信息

### 6.添加察看结果树

在我们刚刚创建的线程组上右键 【添加】–>【监听器】–>【察看结果树】。

直接添加,然后点击运行按钮就可以看到结果了。

### 7.添加Summary Report

在我们刚刚创建的线程组上右键 【添加】–>【监听器】–>【Summary Report】。

直接添加,然后点击运行按钮就可以看到结果了。

为了不引起不必要的争论,隐藏了TPS。此数据不具备任何价值,仅仅为文章演示。

### 8.测试计划创建完成

记得点保存。

## 五.执行测试计划

前面我们说过,执行测试计划不能用GUI,需要用命令行来执行。

我这里执行的命令为:

<pre class="shell"><code class="hljs">jmeter -n -t testplan/RedisLock.jmx -l testplan/result/result.txt -e -o testplan/webreport</code>```

说明:

testplan/RedisLock.jmx 为测试计划文件路径
testplan/result/result.txt 为测试结果文件路径
testplan/webreport 为web报告保存路径。

Web报告如下:

## 六.写在最后

线程数量和循环次数将会影响最终的测试报告,请大家多多测试。

Centos7 设置、查看、添加、删除服务的开机启动项

发表于 2019-01-18

查看开机启动项

systemctl list-unit-files | grep enable

为服务添加开机启动项

systemctl enable zabbix-server.service

移除开机启动项的服务

[root@localhost bin]# systemctl disable zabbix-server.service
Removed symlink /etc/systemd/system/multi-user.target.wants/zabbix-server.service.

减价修改自定义开机启动的脚本

修改 /etc/rc.d/rc.local 这个文件

例如将 apache、mysql、samba、svn 等这些服务的开机自启动问题一起搞定:

1
2
3
4
5
6
7
8
9
10
11
12

[root@localhost ~]# vim /etc/rc.d/rc.local

#添加以下命令

/usr/sbin/apachectl start

/etc/rc.d/init.d/mysqld start

/etc/rc.d/init.d/smb start

/usr/local/subversion/bin/svnserve -d
12…42
庞国明

庞国明

Software make the information world run, and programer make the softeware run.

420 日志
3 分类
267 标签
GitHub E-Mail Twitter StackOverflow Instagram
© 2021 庞国明
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4