PWA实战(3)—Manifest

Manifest是一个 JSON 文件,您(即开发者)可以利用它控制在用户想要看到应用的区域(例如移动设备主屏幕)中如何向用户显示网络应用或网站,指示用户可以启动哪些功能,以及定义其在启动时的外观。

Manifest提供了将网站书签保存到设备主屏幕的功能。当网站以这种方式启动时:

  • 它具有唯一的图标和名称,以便用户将其与其他网站区分开来。
  • 它会在下载资源或从缓存恢复资源时向用户显示某些信息。
  • 它会向浏览器提供默认显示特性,以避免网站资源可用时的过渡过于生硬。

它通过一个文本文件中的元数据这一简单机制完成所有这些工作。实现:

  • 创建清单并将其链接到您的页面,这是非常简单的过程。
  • 控制用户从主屏幕启动时看到的内容。
  • 这包括启动画面、主题颜色以及打开的网址等。

创建清单

在对网络应用清单做详细探究之前,让我们先创建一个基本清单,然后为其链接一个网页。

不管您要什么,都可以调用清单。大多数人使用manifest.json。下面是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"short_name": "AirHorner",
"name": "Kinlan's AirHorner of Infamy",
"icons": [
{
"src": "launcher-icon-1x.png",
"type": "image/png",
"sizes": "48x48"
},
{
"src": "launcher-icon-2x.png",
"type": "image/png",
"sizes": "96x96"
},
{
"src": "launcher-icon-4x.png",
"type": "image/png",
"sizes": "192x192"
}
],
"start_url": "index.html?launcher=true"
}

确保包括以下内容:

  • 在用户主屏幕上用作文本的short_name
  • 在网络应用安装横幅中使用的name

将清单的相关信息告知浏览器

在您创建清单且将清单添加到您的网站之后,将link标记添加到包含网络应用的所有页面上,如下所示:

1
<link rel="manifest" href="/manifest.json">

设置启动网址

如果您不提供start_url,则将使用当前页面,这不太可能是您的用户想要的内容。 但这并不是将它包括在内的唯一原因。 由于您现在可以定义应用的启动方式,因此可向start_url添加一个查询字符串参数来说明其启动方式。

1
"start_url": "/?utm_source=homescreen"

这可以是您希望的任何内容;我们要使用的值的优点是对网站统计十分有意义。

自定义图标

当用户将您的网站添加到其主屏幕时,您可以定义一组供浏览器使用的图标。您可以通过类型和大小定义它们,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"icons": [{
"src": "images/touch/icon-128x128.png",
"type": "image/png",
"sizes": "128x128"
}, {
"src": "images/touch/apple-touch-icon.png",
"type": "image/png",
"sizes": "152x152"
}, {
"src": "images/touch/ms-touch-icon-144x144-precomposed.png",
"type": "image/png",
"sizes": "144x144"
}, {
"src": "images/touch/chrome-touch-icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
}],

添加启动画面

当您从主屏幕启动网络应用时,幕后执行了若干操作:

  1. Chrome 启动。
  2. 显示页面的渲染器启动。
  3. 您的网站从网络(如果网站有服务工作线程,则从缓存)加载。

执行以上操作时,屏幕显示为白色并且看似已经停滞。如果您从网络加载网页时页面需要花费不止一两秒的时间才能让首页显现任何内容,这种情况将变得尤为明显。

为提供更优质的用户体验,您可以用标题、颜色和图像来替换白色屏幕。

设置图像和标题

如果您从未落下课程进度,您已应完成了图像和标题的设置。Chrome 会根据清单的特定成员推断图像和标题。此处的要点是了解详情。

启动画面图像提取自icons数组。Chrome 为设备选择最接近 128dp 的图像。标题是直接从name成员获取的。

设置背景颜色

利用适当命名的background_color属性指定背景颜色。 Chrome 在网络应用启动后会立即使用此颜色,这一颜色将保留在屏幕上,直至网络应用首次呈现为止。

要设置背景颜色,请在您的清单中设置下列内容:

1
"background_color": "#2196F3",

现在,从主屏幕启动您的网站时将不会呈现白色屏幕。

该属性的建议适用值是加载页面的背景颜色。使用与加载页面相同的颜色可实现从启动画面到首页的平稳过渡。

设置主题颜色

使用theme_color属性指定主题颜色。该属性设置工具栏的颜色。 对此,我们还建议复制某种现有颜色,具体地讲就是theme-color <meta>

设置启动样式

利用网络应用清单来控制显示类型和页面方向。

自定义显示类型

您可以通过将display类型设置为standalone,让您的网络应用隐藏浏览器的UI:

1
"display": "standalone"

如果您认为用户喜欢在浏览器中像正常网站一样查看您的网页,您可以将display类型设置为browser

1
"display": "browser"

指定页面的初始方向

您可以强制一个特定方向,这对于某些应用很有用,例如只能在一个方向上运行的游戏。 请有选择地使用。 用户更愿意能够自行选择方向。

1
"orientation": "landscape"

提供全站主题颜色

Chrome 在 2014 年为您的网站引入了主题颜色这一概念。主题颜色是来自您的网页的提示,用于告知浏览器使用什么颜色来为地址栏等 UI 元素着色。

如果没有清单,您需要在每个页面上定义主题颜色,并且如果您拥有的是大型网站或旧版网站,进行大量全站更改并不可行。
向您的清单添加theme_color属性后,从主屏幕启动网站时,网域中的每个页面都将自动获得主题颜色。

1
"theme_color": "#2196F3"

PWA实战(2)—Service Wroker

什么是Service Worker

一个Service Worker是一种类型的web worker。它本质上是一个JavaScript文件,它与主浏览器线程分开运行,拦截网络请求,缓存或从缓存中检索资源,以及传递推送消息。

由于工作者与主线程分开运行,因此Service Worker独立于与其关联的应用程序。这有几个后果:

  • 因为Service Worker没有阻塞(它被设计为完全异步)同步XHR并且localStorage不能在Service Worker中使用。

  • 当应用程序未处于活动状态时,Service Worker可以从服务器接收推送消息。这样,即使未在浏览器中打开,您的应用也会向用户显示推送通知。

  • Service Worker无法直接访问DOM。为了与页面通信,Service Worker使用postMessage()方法发送数据,并使用message事件监听器来接收数据。

关于Service Worker的注意事项:

  • Service Worker是一种可编程网络代理,可让您控制如何处理来自页面的网络请求。

  • Service Worker只能通过HTTPS运行。由于Service Worker可以拦截网络请求并修改响应,因此“中间人”攻击可能非常糟糕。

    注意:像Let's Encrypt这样的服务允许您免费获得SSL证书以便在服务器上安装。

  • Service Worker工作程序在不使用时变为空闲状态,并在下次需要时重新启动。您不能依赖事件之间持久存在的全局状态。如果存在需要在重新启动时保留和重用的信息,则可以使用IndexedDB数据库。

  • Service Worker广泛使用Promises

Service Worker能做什么

Service Worker使应用程序能够控制网络请求,缓存这些请求以提高性能,并提供对缓存内容的脱机访问。

Service Worker依赖于两个API来使应用程序脱机工作: Fetch(从网络检索内容的标准方法)和Cache(应用程序数据的持久内容存储)。这个Cache是持久的,独立于浏览器缓存或网络状态。

提高应用程序/站点的性能

缓存资源将使内容在大多数网络条件下加载更快。有关缓存策略的完整列表,请参阅 使用Caching files with the service workerThe Offline Cookbook

让您的应用“离线优先”

使用Service Worker内部的Fetch API,我们可以拦截网络请求,然后使用所请求资源以外的内容修改响应。当用户离线时,我们可以使用此技术从缓存中提供资源。请参阅 使用Service Worker缓存文件以获得此技术的实际操作经验。

充当高级功能的基础

Service Worker提供了使Web应用程序像本机应用程序一样工作的功能的起点。其中一些功能是:

  • Notifications API:使用操作系统的本机通知系统显示通知并与通信交互的方法。

  • Push API:一种API,可让您的应用订阅推送服务并接收推送消息。推送消息被传递给Service WorkerService Worker可以使用消息中的信息来更新本地状态或向用户显示通知。由于Service Worker独立于主应用程序运行,因此即使浏览器未运行,他们也可以接收和显示通知。

  • Background Sync API:允许您将操作推迟到用户具有稳定连接。这对于确保实际发送用户想要发送的内容非常有用。此API还允许服务器定期更新应用程序,以便应用程序可以在下次联机时进行更新

  • Channel Messaging API:允许Web工作者和Service Worker相互通信并与主机应用程序通信。此API的示例包括新内容通知和需要用户交互的更新。

Service Worker生命周期

Service Worker在其生命周期中经历三个步骤:

  • 注册
  • 安装
  • 激活

注册和作用域

要安装Service Worker,您需要在主JavaScript代码中注册它。注册会告诉浏览器您的Service Worker所在的位置,并开始在后台安装它。我们来看一个例子:

1
2
3
4
5
6
7
8
9
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(function(registration) {
console.log('Registration successful, scope is:', registration.scope);
})
.catch(function(error) {
console.log('Service worker registration failed, error:', error);
});
}

此代码首先检查浏览器支持navigator.serviceWorker。然后向Service Worker注册,navigator.serviceWorker.register返回在Service Worker成功注册时解析的promise,然后用记录registration.scope

scope是确定哪些Service Worker控制的,换句话说,从该路径的Service Worker将拦截请求。默认范围是Service Worker文件的位置,并扩展到下面的所有目录。因此,如果service-worker.js位于根目录中,则Service Worker将控制来自此域的所有文件的请求。

您还可以通过在注册时传入其他参数来设置任意范围。例如:

1
2
3
navigator.serviceWorker.register('/service-worker.js', {
scope: '/app/'
});

在这种情况下,我们设置Service Worker的作用域到/app/,这意味着Service Worker作用域包括/app//app/lower/以及/app/lower/lower等,但不包括/app或者/,以及其他上一级的路径。

如果已安装Service Worker,则navigator.serviceWorker.register返回当前Service Worker的注册对象。

安装

一旦浏览器注册了Service Worker,就可以尝试安装。如果浏览器认为Service Worker是新用户,则会安装Service Worker,原因是该站点当前没有已注册的Service Worker,或者因为新Service Worker与之前安装的Service Worker之间存在字节差异。

Service Worker安装会在安装过程中触发事件。我们可以在Service Worker安装过程中包含一个事件监听器,以便在安装Service Worker时执行某些任务。例如,在安装过程中,Service Worker可以预先缓存Web应用程序的某些部分,以便在用户下次打开它时立即加载。因此,在第一次加载之后,您将从即时重复加载中受益,并且在这些情况下,您的交互时间将变得更好。安装事件侦听器的示例如下所示:

1
2
3
4
// Listen for install event, set callback
self.addEventListener('install', function(event) {
// Perform some task
});

激活

一旦Service Worker成功安装,它就会转换到激活阶段。如果存在由前一个Service Worker控制的任何打开页面,则新Service Worker进入waiting状态。新Service Worker仅在不再加载仍在使用旧Service Worker的任何页面时激活。这可确保在任何给定时间只运行一个版本的Service Worker

注意:仅刷新页面不足以将控制权转移给新的Service Worker,因为在卸载当前页面之前将请求新页面,并且不会有旧Service Worker未使用的时间。
当新Service Worker激活时,将激活的Service Worker中触发事件activate。此事件侦听器是清理过时缓存的好地方

1
2
3
self.addEventListener('activate', function(event) {
// Perform some task
});

激活后,Service Worker将控制在其作用域内加载的所有页面,并开始侦听来自这些页面的事件。但是,在Service Worker激活之前加载的页面不在Service Worker控制之下。新Service Worker只会在您关闭并重新打开应用程序或执行 clients.claim()时接管。在此之前,新Service Worker不会截获此页面的请求。这是有意识的,以确保您的网站的一致性。

PWA实战(1)—概述

什么是PWA

PWA(Progressive Web Apps)是渐进式web应用程序,它是2016年,Google I/O 大会上提出的一个概念。这并不是描述一个技术,而是一些技术的合集。PWA是专门应对手机Web开发而提出的,通过新技术的成熟,实现最好的Web + 手机APP。

PWA特点

  • 可发现:能被识别为应用程序,通过搜索引擎能容易找到。

  • 可安装:可用于的移动设备,用户的主屏幕上 - 没有应用程序商店的麻烦。

  • 可连接:通过URL轻松共享,无需复杂的安装。

  • 网络独立:可工作在离线或低速的网络环境下。

  • 渐进增强:适用于所有用户,无论选择什么种类的浏览器。

  • 再参与:使用提醒注意让用户更容易的参与,即使用户没有使用他们的设备。

  • 响应式:适合任何形式的因素:台式机,手机,平板电脑,或任何随之而来的新设备。

  • 安全:传递机制可以防止监听,并保证内容不被篡改。

主要技术

  • Https
  • Service Worker
  • Web App Manifest
  • Push Notification

成功案例

PWA 资源大全: Outweb, PWA Directory

PWA资料: Google Developers

网站使用https,免费方便的Let's Encrypt证书

现在越来越多的网站升级到https了,并且Chrome和Firefox开始对HTTP网站显示不安全警告,那么如何方便快捷,最好是免费的升级https呢。没错,Let’s Encrypt证书完全能够满足你的所有需求。

Let’s Encrypt介绍

Let’s Encrypt是一个免费、开放,自动化的证书颁发机构,由 ISRG(Internet Security Research Group)运作。Let’s Encrypt网址:https://letsencrypt.org/

ISRG是一个关注网络安全的公益组织,其赞助商从非商业组织到财富100强公司都有,包括Mozilla、Akamai、Cisco、Facebook,密歇根大学等等。ISRG以消除资金,技术领域的障碍,全面推进加密连接成为互联网标配为自己的使命。

Let’s Encrypt项目于2012年由 Mozilla 的两个员工发起,2014年11年对外宣布公开,2015年12月3日开启公测。

Let’s Encrypt优势

Let’s Encrypt有众多互联网顶级公司的参与,保证了其自身的可信度和可持续性,加上免费这一大杀器,本应该大杀四方,哪里还有那些收费ssl证书的活路。但是,Let’s Encrypt证书的有效期只有90天,到期后需要提交更新,在初期,Let’s Encrypt 的安全证书配置起来比较麻烦,需要手动获取及部署。存在一定的门槛,没有一些技术底子可能比较难搞定。虽然有一些网友就自己做了一些脚本来优化和简化部署过程,但还是有些麻烦不是,并且个人制作的脚本存在一定的使用风险和安全隐患。

但是,现在Let’s Encrypt官方推出了Certbot工具,简单敲几行命令就能完成所有配置,并且能够自动续期,妈妈咱已不用惦记90天的问题了。

Certbot使用

Certbot网址:https://certbot.eff.org/,打开网站后看到:

Imgur

可以根据操作系统和使用的软件来选择相应的命令,以centos7上的nginx为例:

  • 安装Certbot

    1
    $ sudo certbot --nginx
  • 执行配置命令

    Certbot有一个Nginx插件,它在许多平台上都受支持,并且安装了证书。

    1
    $ sudo certbot --nginx

    运行此命令将为您获得证书,并让Certbot自动编辑您的Nginx配置以便为其提供服务。如果您感觉更保守,并且想手动更改Nginx配置,则可以使用certonly 子命令:

    1
    $ sudo certbot --nginx certonly
  • 自动更新

    Certbot可以配置为在证书过期之前自动续订您的证书。自从让我们将证书最后加密90天后,最好利用此功能。您可以通过运行以下命令来测试证书的自动续订:

    1
    $ sudo certbot renew --dry-run

    如果工作正常,您可以通过添加运行以下命令的cron job或systemd timer来安排自动续订:

    1
    certbot renew

    执行cron命令

    1
    $ sudo crontab -e

    一个cron的例子可能是这样的,它会在每天的中午和午夜运行:

    1
    0 0,12 * * * certbot renew 
  • certbot追加域名

    列出由Certbot管理的所有证书信息

    1
    $ sudo certbot certificates

    追加域名

    1
    $ sudo certbot --expand -d existing.com -d example.com -d newdomain.com

nginx缓存和Gzip压缩设置

nginx 是一个高性能的 Web 服务器,为了提高响应速度,可以从设置 nginx 的 gzip 和缓存这2方面入手。开启 gzip 和缓存能大大减少带宽的消耗。

开启gzip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 开启gzip
gzip on;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;

# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 2;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";

开启缓存

1
2
3
4
5
6
7
8
9
10
11
12
location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ { 
access_log off;
expires 30d;
}

location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
access_log off;
expires 24h;
}
location ~* ^.+\.(html|htm)$ {
expires 1h;
}

通过Git Hooks实现自动部署

在没有接触到Git Hook之前,我一直都是在本地将代码push到远程仓库,然后再ssh到服务器上git pull,想起来都心酸。这样手工操作不仅繁琐,还非常容易出错。好在Git为我们提供了hook这种好东西,能够在特定的事件触发时执行我们写好的脚本,实现自动化部署。

为什么需要自动化部署?

  • 当在本地计算机完成服务器应用程序开发之后,需要把程序安装到服务器上,这样的安装过程一般称之为部署。
  • 部署一般分为文件复制、启动服务、安装依赖等。
  • 每次开发完成一个版本都需要部署一次。手动部署属于多次重复劳动。
  • 身为合格的程序员,应该把一切能够自动化的劳动自动化。

通过Git Hooks实现的自动化部署,将实现敲入git push命令后,自动完成整个部署过程。

认识Hooks

Git Hooks提供了多种形式的Hook,以pre-commit为例,该Hook将拦截git commit操作,运行名叫pre-commit的脚本,且仅当脚本返回值为0时进行真正的commit操作。

那么自动部署所需使用的Hook名为post-receive. 该Hook将在服务器端的bare repository接收到push信息并完成push操作后,进行执行;无法中断客户端(Client)的push过程。

可能浏览完上面的介绍,还是不太明白Hook是什么。简单地说,Hook是一种特殊的脚本(代码),仅在满足特定条件时执行。Git Hooks分别有对应各种操作的Hook,可以在git repository的.git/hooks目录下看到。

1
2
3
4
applypatch-msg.sample     pre-commit.sample         prepare-commit-msg.sample
commit-msg.sample pre-push.sample update.sample
post-update.sample pre-rebase.sample
pre-applypatch.sample pre-receive.sample

以上的脚本文件就是Hook了。可以看到脚本文件的后缀名都是sample,也就是说,这些都是Git自带的Hook示例,并不会真正地被执行。要想真正地被执行,只需要去掉sample后缀名即可。例如要启用pre-push的Hook(在push操作前执行脚本,脚本返回值为0时执行push操作),在hooks目录下新建一个pre-push的文件(没有后缀名)。

在脚本中,你可以写Bash、Python、JavaScript等代码,Git通过Shebang来选择执行代码的解释器。如果要写Bash,Shebang可以是这样:

1
#!/usr/bin/bash

使用Windows的读者请注意,如果脚本文件含有BOM(字节序标识符),可能会导致一些问题。

当完成脚本编写后,Git Hooks便完成了。

Git Hooks与自动部署

要保证不是git服务端和要部署的网站目录在同一台服务器,并且最好都属于git用户,这样不需要考虑操作权限问题了。

  • git hooks部署

裸仓库接收push之后怎么自动去执行pull操作,git仓库中有个.git文件夹,里面有个hooks文件夹,git 钩子就藏在这。里面有很多文件,其中有个post-receive.sample文件(没有的话也没有关系,新建一个post-receive文件,注意不带sample后缀,带上这个后缀默认是不触发执行的),我们要做的脚本代码就在这里个文件里面完成。

下面的示例是使用nodejs生成的静态网站,先执行git pull获取最新代码,然后检查node_modules文件夹是否存在,如果不存在,执行npm install命令。然后检查package.json文件,如果变动,执行npm install命令,最后执行npm run build命令生成静态网站文件。

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
#!/bin/bash
WORKTREE=/var/www/xxxweb
CONFIG=package.json

while read oldrev newrev ref # post-receive 将读取这三个变量
do
if [[ $ref =~ .*/master$ ]]; # 仅允许master分支进行部署
then
echo "Pull to worktree..."
#echo "$oldrev $newrev"
cd $WORKTREE
unset GIT_DIR
git pull &> /dev/null

if [ ! -d "/node_modules" ] # 如果node_modules文件夹不存在
then
echo "install packages..."
npm install
fi

git diff --quiet $oldrev $newrev -- $CONFIG
if [ "$?" -eq "1" ] # 当package.json被修改时,安装依赖
then
echo "package.json changed"
export LC_ALL=C # 去除所有本地化的设置
echo "install packages..."
npm install
else
echo "package.json does not changed"
fi

#如果是需要PM2启动服务
pm2 show api &> /dev/null #查看PM2是否启动
if [ "$?" -eq "1" ]
then
pm2 start app.js -n 'api'
else
pm2 restart api
fi

#如果是生成网页
npm run build # 生成dist
echo "build complete"
else
echo "This is not master branch, and it will not be deployed"
fi
done

对了,编辑完post-receive文件,要赋予其执行权限,chmod +x post-receive,并且改变文件所有者chown git:git post-receive

  • 权限处理
    在上述代码示例中,我部署了的网站工作目录是/var/www/xxxweb,所属用户是git,如果不是,执行
    1
    chown -R git:git xxxweb
    因为所属用户是git,钩子脚本的所有者也是git,所以权限是没有问题的(如果不是同属于git用户,命令需要sudo,同时需要配置权限,比较麻烦,不建议)。可能有些时候需要在git用户下执行ssh -T git@127.0.0.1添加known_hosts。

Web API文档生成工具apidoc

在项目开发过程中,总会牵扯到接口文档的设计与编写,如果使用office工具,写一个文档,总也是不够漂亮和直观。好在git上的开源大神提供了生成文档的工具,so来介绍一下apidoc!

apidoc可以根据代码注释生成web api文档,支持大部分主流语言java javascript php coffeescript erlang perl python ruby go…,相对而言,web接口的注释维护起来更加方便,不需要额外再维护一份文档。

apidoc从注释生成静态html网页文档,不仅支持项目版本号,还支持api版本号。

安装

主页: http://apidocjs.com
github: https://github.com/apidoc/apidoc
可以使用npm install apidoc -g进行安装。
如果不想使用全局命令,可以使用下面的构建工具:

应用

在命令行窗口执行apidoc -h命令,可以查看帮助。
下面讲讲常用的方法

1
2
3
4
5
6
7
8
// 典型用法
apidoc -i api/ -o doc/api [-c ./] -f ".*\.js$"

-i 表示输入,后面是文件夹路径
-o 表示输出,后面是文件夹路径
默认会带上-c,在当前路径下寻找配置文件(apidoc.json),如果找不到则会在package.json中寻找 "apidoc": { }
-f 为文件过滤,后面是正则表达式,示例为只选着js文件
与-f类似,还有一个 -e 的选项,表示要排除的文件/文件夹,也是使用正则表达式

配置文件(apidoc.json)

apidoc.json示例:

1
2
3
4
5
6
7
{
"name": "example",
"version": "0.1.0",
"description": "apiDoc basic example",
"title": "Custom apiDoc browser title",
"url" : "https://api.github.com/v1"
}

如果放入package.json中,相同的字段可以直接使用package.json的定义,额外的字段放入apidoc下

1
2
3
4
5
6
7
8
9
{
"name": "example",
"version": "0.1.0",
"description": "apiDoc basic example",
"apidoc": {
"title": "Custom apiDoc browser title",
"url" : "https://api.github.com/v1"
}
}

注释写法

常用关键字

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
@api {method} path [title]
只有使用@api标注的注释块才会在解析之后生成文档,title会被解析为导航菜单(@apiGroup)下的小菜单
method可以有空格,如{POST GET}
@apiGroup name
分组名称,被解析为导航栏菜单
@apiName name
接口名称,在同一个@apiGroup下,名称相同的@api通过@apiVersion区分,否者后面@api会覆盖前面定义的@api
@apiDescription text
接口描述,支持html语法
@apiVersion verison
接口版本,major.minor.patch的形式

@apiIgnore [hint]
apidoc会忽略使用@apiIgnore标注的接口,hint为描述
@apiSampleRequest url
接口测试地址以供测试,发送请求时,@api method必须为POST/GET等其中一种

@apiDefine name [title] [description]
定义一个注释块(不包含@api),配合@apiUse使用可以引入注释块
@apiDefine内部不可以使用@apiUse
@apiUse name
引入一个@apiDefine的注释块

@apiParam [(group)] [{type}] [field=defaultValue] [description]
@apiHeader [(group)] [{type}] [field=defaultValue] [description]
@apiError [(group)] [{type}] field [description]
@apiSuccess [(group)] [{type}] field [description]
用法基本类似,分别描述请求参数、头部,响应错误和成功
group表示参数的分组,type表示类型(不能有空格),入参可以定义默认值(不能有空格)
@apiParamExample [{type}] [title] example
@apiHeaderExample [{type}] [title] example
@apiErrorExample [{type}] [title] example
@apiSuccessExample [{type}] [title] example
用法完全一致,但是type表示的是example的语言类型
example书写成什么样就会解析成什么样,所以最好是书写的时候注意格式化,(许多编辑器都有列模式,可以使用列模式快速对代码添加*号)

@apiPermission name
name必须独一无二,描述@api的访问权限,如admin/anyone

文档生成后的结果是这样的:
http://apidocjs.com/example/

koa2开发的api服务及jwt应用

koa2开发的api服务示例,使用用jwt验证。

github代码:https://github.com/yunzaifei/koa2-jwt-demo

安装及部署

  • 执行命令npm install
  • 执行命令npm start启动服务
  • 可以通过postman等工具对服务进行测试,或者通过npm run test命令使用网页页查看

涉及知识点

  • koa2框架
  • jwt原理及应用
  • mongoose应用
  • async/await的简单使用

知识点讲解

koa2框架

koa就是一种简单好用的Web框架。它的特点是优雅、简洁、表达力强、自由度高。本身代码只有1000多行,所有功能都通过插件实现,很符合Unix哲学。

koa官网 http://koajs.com/

koa中文文档 https://github.com/guo-yu/koa-guide

koa2进阶学习笔记 https://chenshenhai.github.io/koa2-note/

本示例中涉及的中间件

中间件 功能说明 链接 备注
bcrypt 加密 NPM version 用于用户密码存入数据库时
jsonwebtoken jwt实现 NPM version
kcors koa跨域 NPM version
koa koa框架 NPM version
koa-bodyparser 数据解析到ctx.request.body中 NPM version 详细
koa-json response转换位json格式 NPM version
koa-jwt jwt自动校验 NPM version 使用后不用在每个路由下手写校验方法
koa-logger 日志 NPM version
koa-router 路由 NPM version 详细
mongoose 操作mongodb数据库 NPM version 文档

代码结构说明

本示例代码实现api服务,因为没有页面展示功能,所以没有使用koa-static加载静态资源和创建views视图结构。

启动文件是app.js。

route文件夹是路由服务。

config.js文件记录所有配置信息方便统一管理。

jwt原理及应用

jwt原理

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。注意,在JWT中,不应该在载荷里面加入任何敏感的数据。查看jwt信息:https://jwt.io/

jwt原理

基于Token的WEB后台认证机制

jwt应用

对于jwt的应用,本示例中主要用到jsonwebtokenNPM version和koa-jwtNPM version两个中间件。koa-jwt是对jsonwebtoken功能的封装,如果想更灵活的实现并且不怕麻烦,可以只使用jsonwebtoken中间件。

jsonwebtoken用法

1
2
3
4
5
6
7
8
9
10
11
12
//jsonwebtoken在服务端生成token返回给客户端
const jwt = require('jsonwebtoken')
const token = jwt.sign({
id: user._id,
secret: user.app_secret
}, config.jwt_secret, {expiresIn: 3600})

ctx.body = {
code: 200,
message: '登录成功!',
token: token
}

koa-jwt用法

1
2
3
4
5
6
7
8
9
10
11
12
//koa-jwt在服务端校验从客户端提交的token值
const app = new Koa()
const jwt = require('koa-jwt')
app.use(jwt({secret: config.jwt_secret}).unless({path:[/^\/api\/login/, /^\/api\/register/]})) //usless排除进行jwt校验的路由

//在路由中处理
const router = require('koa-router')()
router.post('/xxx', async ctx => {
const token = ctx.state.user
console.log('user_id:', token.id)
console.log('user.app_secret:', token.secret)
}

mongoose应用

mongoose文档:http://mongoosejs.com/docs/guide.html

mongoose中文文档:https://mongoose.shujuwajue.com/

async/await的简单使用

async 函数

深入理解ES7的async/await

Callback、Promise、Generator、async/await对比

搭建自己的Git服务器

Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Git与常用的版本控制工具CVS, SVN等不同,它采用了分布式版本库的方式,不必服务器端软件支持。Github是一个基于git的代码托管平台,Github公开的项目是免费的,但是如果你不想让其他人看到你的项目就需要收费。这时我们就需要自己搭建一台Git服务器作为私有仓库使用。接下来我们将以Centos 7为例搭建Git服务器,其中Centos 7作为服务端,windows系统作为客户端。

sever

  1. 安装git
    1
    yum install git
  2. 新建一个linux用户,起名为git(当然也可以叫其他名字)
    1
    useradd git
  3. 在git用户目录中新建目录.ssh
    1
    2
    $ mkdir .ssh
    $ chmod 700 .ssh
  4. 在/home/git/.ssh/目录中新建authorized_keys文件,并将客户端提供的公钥(id_rsa.pub)黏贴到该文件中
    1
    2
    $ touch .ssh/authorized_keys
    $ chmod 600 .ssh/authorized_keys
  5. 创建一个git裸仓库,假如当前项目目录为/home/git/xxx.git
    1
    git init --bare xxx.git
  6. 将项目目录和git用户目录下的.ssh目录的所有者和所属组都设置成git
    1
    2
    chown -R git.git xxx.git  
    chown -R git.git /home/git/.ssh/
  7. 为了安全考虑,禁用git用户的shell登录
    1
    2
    3
    vi /etc/passwd
    注释 ##git:x:000:000::/home/git:/bin/bash (git:x:000:000中数字不要改动,文件中是多少就是多少)
    改为 git:x:000:000:git version control:/home/git:/usr/bin/git-shell
  8. git服务器打开RSA认证
    1
    2
    3
    4
    5
    vi /etc/ssh/sshd_config
    下面3个打开
    1.RSAAuthentication yes
    2.PubkeyAuthentication yes
    3.AuthorizedKeysFile .ssh/authorized_keys

client

  1. 生成公钥,并复制到服务端authorized_keys文件
    1
    2
    ssh-keygen -t rsa -C "标识名"
    ssh-add -L
  2. 在C:/Users/用户名/.ssh下新建config文件,config文件内容
    1
    2
    3
    4
    5
    6
    #注释名称
    Host xxxx(自定义host名称)
    HostName xxx.xxx.xxx.xxx(服务端ip地址)
    user git(服务端作为git仓库的用户名)
    Port 22(服务端ssh端口号)
    IdentityFile ~/.ssh/id_rsa(默认值为id_rsa,如果个性化名称,请填写个性化的名称)
  3. 新建一个文件夹,克隆仓库
    1
    git clone git@xxxx(config文件中自定义host名称):/home/git/xxx.git

常用个git命令

  1. 新建代码库
    1
    2
    3
    4
    5
    6
    7
    8
    #在当前目录新建一个Git代码库
    $ git init

    # 新建一个目录,将其初始化为Git代码库
    $ git init [project-name]

    # 下载一个项目和它的整个代码历史
    $ git clone [url]
  2. 配置
    Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 显示当前的Git配置
    $ git config --list

    # 编辑Git配置文件
    $ git config -e [--global]

    # 设置提交代码时的用户信息
    $ git config [--global] user.name "[name]"
    $ git config [--global] user.email "[email address]"
  3. 增加/删除文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 添加指定文件到暂存区
    $ git add [file1] [file2] ...

    # 添加指定目录到暂存区,包括子目录
    $ git add [dir]

    # 添加当前目录的所有文件到暂存区
    $ git add .

    # 添加每个变化前,都会要求确认
    # 对于同一个文件的多处变化,可以实现分次提交
    $ git add -p

    # 删除工作区文件,并且将这次删除放入暂存区
    $ git rm [file1] [file2] ...

    # 停止追踪指定文件,但该文件会保留在工作区
    $ git rm --cached [file]

    # 改名文件,并且将这个改名放入暂存区
    $ git mv [file-original] [file-renamed]
  4. 代码提交
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 提交暂存区到仓库区
    $ git commit -m [message]

    # 提交暂存区的指定文件到仓库区
    $ git commit [file1] [file2] ... -m [message]

    # 提交工作区自上次commit之后的变化,直接到仓库区
    $ git commit -a

    # 提交时显示所有diff信息
    $ git commit -v

    # 使用一次新的commit,替代上一次提交
    # 如果代码没有任何新变化,则用来改写上一次commit的提交信息
    $ git commit --amend -m [message]

    # 重做上一次commit,并包括指定文件的新变化
    $ git commit --amend [file1] [file2] ...
  5. 分支
    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
    # 列出所有本地分支
    $ git branch

    # 列出所有远程分支
    $ git branch -r

    # 列出所有本地分支和远程分支
    $ git branch -a

    # 新建一个分支,但依然停留在当前分支
    $ git branch [branch-name]

    # 新建一个分支,并切换到该分支
    $ git checkout -b [branch]

    # 新建一个分支,指向指定commit
    $ git branch [branch] [commit]

    # 新建一个分支,与指定的远程分支建立追踪关系
    $ git branch --track [branch] [remote-branch]

    # 切换到指定分支,并更新工作区
    $ git checkout [branch-name]

    # 切换到上一个分支
    $ git checkout -

    # 建立追踪关系,在现有分支与指定的远程分支之间
    $ git branch --set-upstream [branch] [remote-branch]

    # 合并指定分支到当前分支
    $ git merge [branch]

    # 选择一个commit,合并进当前分支
    $ git cherry-pick [commit]

    # 删除分支
    $ git branch -d [branch-name]

    # 删除远程分支
    $ git push origin --delete [branch-name]
    $ git branch -dr [remote/branch]
  6. 标签
    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
    # 列出所有tag
    $ git tag

    # 新建一个tag在当前commit
    $ git tag [tag]

    # 新建一个tag在指定commit
    $ git tag [tag] [commit]

    # 删除本地tag
    $ git tag -d [tag]

    # 删除远程tag
    $ git push origin :refs/tags/[tagName]

    # 查看tag信息
    $ git show [tag]

    # 提交指定tag
    $ git push [remote] [tag]

    # 提交所有tag
    $ git push [remote] --tags

    # 新建一个分支,指向某个tag
    $ git checkout -b [branch] [tag]
  7. 查看信息
    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
    # 显示有变更的文件
    $ git status

    # 显示当前分支的版本历史
    $ git log

    # 显示commit历史,以及每次commit发生变更的文件
    $ git log --stat

    # 搜索提交历史,根据关键词
    $ git log -S [keyword]

    # 显示某个commit之后的所有变动,每个commit占据一行
    $ git log [tag] HEAD --pretty=format:%s

    # 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
    $ git log [tag] HEAD --grep feature

    # 显示某个文件的版本历史,包括文件改名
    $ git log --follow [file]
    $ git whatchanged [file]

    # 显示指定文件相关的每一次diff
    $ git log -p [file]

    # 显示过去5次提交
    $ git log -5 --pretty --oneline

    # 显示所有提交过的用户,按提交次数排序
    $ git shortlog -sn

    # 显示指定文件是什么人在什么时间修改过
    $ git blame [file]

    # 显示暂存区和工作区的差异
    $ git diff

    # 显示暂存区和上一个commit的差异
    $ git diff --cached [file]

    # 显示工作区与当前分支最新commit之间的差异
    $ git diff HEAD

    # 显示两次提交之间的差异
    $ git diff [first-branch]...[second-branch]

    # 显示今天你写了多少行代码
    $ git diff --shortstat "@{0 day ago}"

    # 显示某次提交的元数据和内容变化
    $ git show [commit]

    # 显示某次提交发生变化的文件
    $ git show --name-only [commit]

    # 显示某次提交时,某个文件的内容
    $ git show [commit]:[filename]

    # 显示当前分支的最近几次提交
    $ git reflog
  8. 远程同步
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 下载远程仓库的所有变动
    $ git fetch [remote]

    # 显示所有远程仓库
    $ git remote -v

    # 显示某个远程仓库的信息
    $ git remote show [remote]

    # 增加一个新的远程仓库,并命名
    $ git remote add [shortname] [url]

    # 取回远程仓库的变化,并与本地分支合并
    $ git pull [remote] [branch]

    # 上传本地指定分支到远程仓库
    $ git push [remote] [branch]

    # 强行推送当前分支到远程仓库,即使有冲突
    $ git push [remote] --force

    # 推送所有分支到远程仓库
    $ git push [remote] --all
  9. 撤销
    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
    # 恢复暂存区的指定文件到工作区
    $ git checkout [file]

    # 恢复某个commit的指定文件到暂存区和工作区
    $ git checkout [commit] [file]

    # 恢复暂存区的所有文件到工作区
    $ git checkout .

    # 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
    $ git reset [file]

    # 重置暂存区与工作区,与上一次commit保持一致
    $ git reset --hard

    # 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
    $ git reset [commit]

    # 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
    $ git reset --hard [commit]

    # 重置当前HEAD为指定commit,但保持暂存区和工作区不变
    $ git reset --keep [commit]

    # 新建一个commit,用来撤销指定commit
    # 后者的所有变化都将被前者抵消,并且应用到当前分支
    $ git revert [commit]

    # 暂时将未提交的变化移除,稍后再移入
    $ git stash
    $ git stash pop
  10. 其他
    1
    2
    3
    4
    # 生成一个可供发布的压缩包
    $ git archive
    # 忽略更新(适用于配置信息等)
    $ git update-index --assume-unchanged <file-path>

nginx简单用法和介绍

Nginx(发音同engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由Igor Sysoev为俄罗斯访问量第二的Rambler.ru站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名,其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

Nginx官网:http://nginx.org/  
https://www.nginx.com/

安装

  • 编译安装
    下载对应的安装包进行编译安装
    1
    2
    ./configure --user=www --group=www --prefix=/usr/local/nginx/ --with-http_stub_status_module --with-openssl=/usr/local/openssl
    make && make install
  • yum安装(以centos7为例)
    官方示例:https://www.nginx.com/resources/wiki/start/topics/tutorials/install/
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #新建repo文件
    vi /etc/yum.repos.d/nginx.repo

    #复制以下内容
    [nginx]
    name=nginx repo
    baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
    gpgcheck=0
    enabled=1

    #保存退出后,生成源数据缓存
    yum makecache

    #之后就可以yum命令安装
    yum install nginx

    #yum命令更新
    yum update nginx

Nginx反向代理

  1. proxy_pass
    语法:proxy_pass URL;
    配置块:location、if
    此配置项将当前请求反向代理到URL参数指定的服务器上,URL可以是主机名或IP地址加端口的形式,例如:

    1
    proxy_pass http://localhost:8000/uri/;

    也可以是UNIX句柄:

    1
    proxy_pass http://unix:/path/to/backend.socket:/uri/;

    还可以如上节负载均衡中所示,直接使用upstream块,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    upstream backend {

    }

    server {
    location / {
    proxy_pass http://backend;
    }
    }

    用户可以把HTTP转换成更安全的HTTPS,例如:

    1
    proxy_pass https://192.168.0.1;

    默认情况下反向代理是不会转发请求中的Host头部的。如果需要转发,那么必须加上配置:

    1
    proxy_set_header Host $host;
  2. proxy_method
    语法:proxy_method method;
    配置块:http、server、location
    此配置项表示转发时的协议方法名。例如设置为

    1
    proxy_method POST;

    那么客户端发来的GET请求在转发时方法名也会改为POST。

  3. proxy_hide_header
    语法:proxy_hide_header the_header;
    配置块:http、server、location
    Nginx会将上游服务器的响应转发给客户端,但默认不会转发以下HTTP头部字段:Date、Server、X-Pad和X-Accel-*。使用proxy_hide_header后可以任意地指定哪些HTTP头部字段不能被转发。例如:

    1
    2
    proxy_hide_header Cache-Control;
    proxy_hide_header MicrosoftOfficeWebServer;
  4. proxy_pass_header
    语法:proxy_pass_header the_header;
    配置块:http、server、location与proxy_hide_header功能相反,proxy_pass_header会将原来禁止转发的header设置为允许转发。例如:

    1
    proxy_pass_header X-Accel-Redirect;
  5. proxy_pass_request_body
    语法:proxy_pass_request_body on | off;
    默认:proxy_pass_request_body on;
    配置块:http、server、location
    作用为确定是否向上游服务器发送HTTP包体部分。

  6. proxy_pass_request_headers
    语法:proxy_pass_request_headers on | off;
    默认:proxy_pass_request_headers on;
    配置块:http、server、location
    作用为确定是否转发HTTP头部。

  7. proxy_redirect
    语法:proxy_redirect [ default|off|redirect replacement ];
    默认:proxy_redirect default;
    配置块:http、server、location
    当上游服务器返回的响应是重定向或刷新请求(如HTTP响应码是301或者302)时,proxy_redirect可以重设HTTP头部的location或refresh字段。
    例如,如果上游服务器发出的响应是302重定向请求,location字段的URL是:http://localhost:8000/two/some/uri/,
    那么在下面的配置情况下,实际转发给客户端的location是http://frontend/one/some/uri/。

    1
    proxy_redirect http://localhost:8000/two/ http://frontend/one/;

    这里还可以使用ngx-http-core-module提供的变量来设置新的location字段。例如

    1
    proxy_redirect   http://localhost:8000/ http://$host:$server_port/;

    也可以省略replacement参数中的主机名部分,这时会用虚拟主机名称来填充。例如:

    1
    proxy_redirect http://localhost:8000/two/ /one/;

    使用off参数时,将使location或者refresh字段维持不变。例如:

    1
    proxy_redirect off;

    使用默认的default参数时,会按照proxy_pass配置项和所属的location配置项重组发往客户端的location头部。例如,下面两种配置效果是一样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    location /one/ {  
    proxy_pass http://upstream:port/two/;
    proxy_redirect default;
    }

    location /one/ {
    proxy_pass http://upstream:port/two/;
    proxy_redirect http://upstream:port/two/ /one/;
    }
  8. proxy_next_upstream
    语法:proxy_next_upstream [error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_404 | off ];
    默认:proxy_next_upstream error timeout;
    配置块:http、server、location
    此配置项表示当向一台上游服务器转发请求出现错误时,继续换一台上游服务器处理这个请求。前面已经说过,上游服务器一旦开始发送应答,Nginx反向代理服务器会立刻把应答包转发给客户端。因此,一旦Nginx开始向客户端发送响应包,之后的过程中若出现错误也是不允许换下一台上游服务器继续处理的。这很好理解,这样才可以更好地保证客户端只收到来自一个上游服务器的应答。proxy_next_upstream的参数用来说明在哪些情况下会继续选择下一台上游服务器转发请求。
    error:当向上游服务器发起连接、发送请求、读取响应时出错。
    timeout:发送请求或读取响应时发生超时。
    invalid_header:上游服务器发送的响应是不合法的。
    http_500:上游服务器返回的HTTP响应码是500。
    http_502:上游服务器返回的HTTP响应码是502。
    http_503:上游服务器返回的HTTP响应码是503。
    http_504:上游服务器返回的HTTP响应码是504。
    http_404:上游服务器返回的HTTP响应码是404。
    off:关闭proxy_next_upstream功能—出错就选择另一台上游服务器再次转发。

  9. 简单示例(以centos7为例)

  • 反向代理网站
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #新增配置文件
    vi /etc/nginx/conf.d/fxdl.conf
    #复制以下内容
    server{
    listen 80;
    server_name gl.yunzaifei.com;
    location / {
    proxy_pass https://www.google.com;
    }
    }
    #保存退出后重启nginx
    nginx -s reload
  • 反向代理北地端口
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #新增配置文件
    vi /etc/nginx/conf.d/fxdl.conf
    #复制以下内容
    server {
    listen 80;
    server_name api.xxx.com;

    location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://127.0.0.1:8000/;
    proxy_redirect off;
    }
    }

    #保存退出后重启nginx
    nginx -s reload
    Nginx的反向代理模块还提供了很多种配置,如设置连接的超时时间、临时文件如何存储,以及最重要的如何缓存上游服务器响应等功能。这些配置可以通过阅读ngx_http_proxy_module模块的说明了解,只有深入地理解,才能实现一个高性能的反向代理服务器。