# Nginx
Java-nginx 分布式框架_免费高速下载 | 百度网盘 - 分享无限制 (baidu.com)
# nginx 目录结构
1 | /usr/local/nginx/ |
CGl (Common Gateway Interface) 通用网关【接口】,主要解决的问题是从客户端发送一个请求和数据,服务端获取到请求和数据后可以调用调用 CGI【程序】处理及相应结果给客户端的一种标准规范。
fastcgi,scgi,uwsgi 是 cgi 的升级版
koi-utf、koi-win、win-utf 这三个文件都是与编码转换映射相关的配置文件,用来将一种编码转换成另一种编码
mime.types: 记录的是 HTTP 协议中的 Content-Type 的值和文件后缀名的对应关系
mime.types.default:mime.types 的备份文件
nginx.conf: 这个是 Nginx 的核心配置文件,这个文件非常重要,也是我们即将要学习的重点
nginx.conf.default:nginx.conf 的备份文件
logs: 记录入门的文件,当 nginx 服务器启动后,这里面会有 access.log error.log 和 nginx.pid 三个文件出现。
sbin: 是存放执行程序文件 nginx
nginx 是用来控制 Nginx 的启动和停止等相关的命令。
# nginx 启停
ps -ef | grep nginx 查看 nginx 的 master 和 work process】
Nginx 后台进程中包含一个 master 进程和多个 worker 进程,master 进程主要用来管理 worker 进程,包含接收外界的信息,并将接收到的信号发送给各个 worker 进程,监控 worker 进程的状态,当 worker 进程出现异常退出后,会自动重新启动新的 worker 进程。而 worker 进程则是专门用来处理用户请求的,各个 worker 进程之间是平等的并且相互独立,处理请求的机会也是一样的。nginx 的进程模型,我们可以通过下图来说明下:
1 | [root@hecs-346515 ~]# ps -ef | grep nginx |
nginx 是多进程工作模式

| 信号 | 作用 |
|---|---|
| TERM/INT | 立即关闭整个服务 |
| QUIT | "优雅" 地关闭整个服务 |
| HUP | 重读配置文件并使用服务对新配置项生效 |
| USR1 | 重新打开日志文件,可以用来进行日志切割 |
| USR2 | 平滑升级到最新版的 nginx 会使用 |
| WINCH | 所有子进程不在接收处理新连接,相当于给 work 进程发送 QUIT 指令 |
1 | kill -TERM PID |
1 | [root@hecs-346515 sbin]# ./nginx -? |
1 | -s singal |
# nginx 平滑升级
升级 1:
1 | # 安装新版本 |
升级 2:
1 | # 备份旧的nginx |
1 | 加减模块可升级基本一样,只是不发送最后的信号 |
# nginx.conf
1 | # vim /usr/local/nginx/conf/nginx.conf |
nginx.conf 配置文件中默认有三大块:全局块、events 块、http 块
http 块中可以配置多个 server 块,每个 server 块又可以配置多个 location 块。
# 全局块
1 | | 语法 | user user [group] | |
综上所述,使用 user 指令可以指定启动运行工作进程的用户及用户组,这样对于系统的权限访问控制的更加精细,也更加安全。
master_process: 用来指定是否开启工作进程。
| 语法 | master_process on|off; |
|---|---|
| 默认值 | master_process on; |
| 位置 | 全局块 |
用于配置 Nginx 生成工作进程的数量,这个是 Nginx 服务器实现并发处理服务的关键所在。理论上来说 workder process 的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器 CPU 的内核数保存一致。
| 语法 | worker_processes num/auto; |
|---|---|
| 默认值 | 1 |
| 位置 | 全局块 |
设定 Nginx 是否以守护进程的方式启动。
| 语法 | daemon on|off; |
|---|---|
| 默认值 | daemon on; |
| 位置 | 全局块 |
1 | master_process on|off; # 是否开启工作进程,default on |
# events 块
1 | 默认值accept_mutex on; |
# http 块
1 | # mime-type Nginx作为web服务器,也需要能够识别前端请求的资源类型。 |
# 定义日志
1 | Nginx中日志的类型分access.log、error.log |
| 语法 | access_log path[format[buffer=size]] |
|---|---|
| 默认值 | access_log logs/access.log combined; |
| 位置 | http , server , location |
| 语法 | log_format name [escape=default|json|none] string…; |
| ------ | -------------------------------------------------------- |
| 默认值 | log_format combined “…”; |
| 位置 | http |
1 | access_log /usr/local/nginx/logs hahaha; # http,server,location块配置 |
1 | sendfile:用来设置Nginx服务器是否使用sendfile()传输文件,该属性可以大大提高Nginx处理静态资源的性能 |
# server、location
1 | server { |
http.server,location 中都有的,location 优先生效
# exercise
1 | (1)有如下访问: |
1 | # /home/www/conf.d/haha1.conf |
1 | worker_processes 1; |
# 配置 nginx 为系统服务
1 | vim /usr/lib/systemd/system/nginx.service |
1 | [Unit] |
1 | chmod 755 /usr/lib/systemd/system/nginx.service |
1 | 启动: systemctl start nginx |
# nginx 配置环境变量
1 | vim /etc/profile |
# nginx 虚拟主机
- 虚拟 Web 主机指的是在同一台物理服务器中发布多个 Web 站点或应用
- 独立的网站,独立的项目甚至独立的功能模块都可以使用虚拟主机进行发布
- Nginx 可以基于不同的 IP、不同的端口以及不同的域名实现不同的虚拟主机
- 虚拟主机内的资源收到虚拟主机配置文件内容约束,与其他虚拟主机相对独立
配置虚拟主机可以基于端口号也可以基于子域名
1 | server { |
# nginx 静态资源部署
我们所请 求的内容就分为两种类型,一类是静态资源、一类是动态资源。
静态资源即指在服务器端真实存在并且能直接拿来展示的一些文件,比如常见的 html 页面、css 文件、js 文件、图 片、视频等资源;
动态资源即指在服务器端真实存在但是要想获取需要经过一定的业务逻辑处理,根据不同的条件展示在页面不同这 一部分内容,比如说报表数据展示、根据当前登录用户展示相关具体数据等资源;
1 | (1)静态资源的配置指令 |
# (1)静态资源的配置指令
1 | 默认值listen *:80 | *:8000 |
1 | # location 用来设置请求的URI |
1 | # root path为Nginx服务器接收到请求以后查找资源的根目录路径。 |
1 | # 在`/usr/local/nginx/html`目录下创建一个 images目录,并在目录下放入一张图片mv.png图片 |
1 | # index |
1 | # error_page error_page:设置网站的错误页面 |
# 静态资源优化
1 | sendfile on; |
1 | tcp_nopush # sendfile 打开才生效 位置http,server,location 提升传输效率,即存满缓冲区再发,不要立即push |
在 linux2.5.9 以后的版本中两者是可以兼容的,三个指令都开启的好处是,sendfile 可以开启高效的文件传输模式,tcp_nopush 开启可以确保在发送到客户端之前数据包已经充分 “填满”, 这大大减少了网络开销,并加快了文件发送的速度。 然后,当它到达最后一个可能因为没有 “填满” 而暂停的数据包时,Nginx 会忽略 tcp_nopush 参数, 然后,tcp_nodelay 强制套接字发送数据。由此可知,TCP_NOPUSH 可以与 TCP_NODELAY 一起设置,它比单独配置 TCP_NODELAY 具有更强的性能。所以我们可以使用如下配置来优化 Nginx 静态资源的处理
1 | sendfile on; |
# nginx 静态资源压缩
在 Nginx 的配置文件中可以通过配置 gzip 来对静态资源进行压缩,相关的指令可以配置在 http 块、server 块和 location 块中,Nginx 可以通过
1 | ngx_http_gzip_module模块 |
对这些指令进行解析和处理
以下指令都可以在 http,server,location 中配置
1 | gzip on # 用于开启或者关闭gzip功能 http,server,location |
1 | gzip_proxied 取值 |
新建 nginx_gzip.conf
1 | gzip on; |
gzip 和 sendfile 冲突
gzip 压缩是在用户态完成的,使用 sendfile 之后就不在从内核态到用户态,因此无法同时使用
可以在存储压缩过的文件,直接发送压缩过的文件,客户端解压
可以使用 ngx_http_gzip_static_module 模块的 gzip_static 指令来解决。
1 | gzip_static off; # 检查与访问资源同名的.gz文件时,response中以gzip相关的header返回.gz文件的内容。 |
1 | nginx 编译时默认没有该模块 |
使用该模块后会在 header 中加入 content-Encoding: gzip Vary: Accept-Encoding
# brotil
需要 https 支持
br 和 gzip 可以共存,br 优先级更高
# 安装
- 官网
https://github.com/google/ngx_brotlihttps://codeload.github.com/google/brotli/tar.gz/refs/tags/v1.0.9
- 下载 两个项目
- 解压缩
把 brotli-1.0.9 下所有文件移走
mv ./* ../ngx_brotli-1.0.0rc/deps/brotli/
编译
1 | ./configure --with-compat --add-dynamic-module=/root/ngx_brotli-1.0.0rc --prefix=/usr/local/nginx/ |
- make
- 将
ngx_http_brotli_filter_module.songx_http_brotli_static_module.so拷贝到/usr/local/nginx/modules/ - 复制 nginx 主程序
- 配置文件中添加
1 | load_module "/usr/local/nginx/modules/ngx_http_brotli_filter_module.so"; |
1 | brotli on; |
1 | location / { |
# 静态资源缓存处理
缓存种类
客户端缓存
浏览器缓存
服务端缓存
Nginx / Redis / Memcached 等
浏览器缓存
是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览.
成本最低的一种缓存实现
减少网络带宽消耗
降低服务器压力
减少网络延迟,加快页面打开速度
header 和缓存相关字段
| header | 说明 |
|---|---|
| Expires | 缓存过期的日期和时间 |
| Cache-Control | 设置和缓存相关的配置信息 |
| Last-Modified | 请求资源最后修改时间 |
| ETag | 请求变量的实体标签的当前值,比如文件的 MD5 值 |

(1)用户首次通过浏览器发送请求到服务端获取数据,客户端是没有对应的缓存,所以需要发送 request 请求来获取数据;
(2)服务端接收到请求后,获取服务端的数据及服务端缓存的允许后,返回 200 的成功状态码并且在响应头上附上对应资源以及缓存信息;
(3)当用户再次访问相同资源的时候,客户端会在浏览器的缓存目录中查找是否存在响应的缓存文件
(4)如果没有找到对应的缓存文件,则走 (2) 步
(5)如果有缓存文件,接下来对缓存文件是否过期进行判断,过期的判断标准是 (Expires),
(6)如果没有过期,则直接从本地缓存中返回数据进行展示
(7)如果 Expires 过期,接下来需要判断缓存文件是否发生过变化
(8)判断的标准有两个,一个是 ETag (Entity Tag), 一个是 Last-Modified
(9)判断结果是未发生变化,则服务端返回 304,直接从缓存文件中获取数据
(10)如果判断是发生了变化,重新从服务端获取数据,并根据缓存协商 (服务端所设置的是否需要进行缓存数据的设置) 来进行数据缓存。
强缓存和弱缓存的区别在于是否还要向服务端请求
1 | expires off; # expires:该指令用来控制页面缓存的作用。可以通过该指令控制HTTP应答中的“Expires"和”Cache-Control" |

1 | # add_header指令是用来添加指定的响应头和响应值。 |
缓存响应指令:
1 | Cache-control: must-revalidate |
| 指令 | 说明 |
|---|---|
| must-revalidate | 可缓存但必须再向源服务器进行确认 |
| no-cache | 缓存前必须确认其有效性 |
| no-store | 不缓存请求或响应的任何内容 |
| no-transform | 代理不可更改媒体类型 |
| public | 可向任意方提供响应的缓存 |
| private | 仅向特定用户返回响应 |
| proxy-revalidate | 要求中间缓存服务器对缓存的响应有效性再进行确认 |
| max-age=<秒> | 响应最大 Age 值 |
| s-maxage=<秒> | 公共缓存服务器响应的最大 Age 值 |
max-age=[秒]:
# nginx 解决跨域问题
同源:协议、域名 (IP)、端口相同即为同源
有两台服务器分别为 A,B, 如果从服务器 A 的页面发送异步请求到服务器 B 获取数据,如果服务器 A 和服务器 B 不满足同源策略,则就会出现跨域问题。
Access-Control-Allow-Origin: 直译过来是允许跨域访问的源地址信息,可以配置多个 (多个用逗号分隔),也可以使用 * 代表所有源
Access-Control-Allow-Methods: 直译过来是允许跨域访问的请求方式,值可以为 GET POST PUT DELETE…, 可以全部设置,也可以根据需要设置,多个用逗号分隔
1 | # 解决跨域问题 |
# 防盗链
资源盗链指的是此内容不在自己服务器上,而是通过技术手段,绕过别人的限制将别人的内容放到自己页面上最终展示给用户。以此来盗取大网站的空间和流量。

Referer, 当浏览器向 web 服务器发送请求的时候,一般都会带上 Referer, 来告诉浏览器该网页是从哪个页面链接过来的。
在二次请求时会在请求头中加入 referer,第一次访问时是没有的
后台服务器可以根据获取到的这个 Referer 信息来判断是否为自己信任的网站地址,如果是则放行继续访问,如果不是则可以返回 403 (服务端拒绝访问) 的状态信息。
valid_referers:nginx 会通就过查看 referer 自动和 valid_referers 后面的内容进行匹配,如果匹配到了就将 $invalid_referer 变量置 0,如果没有匹配到,则将 $invalid_referer 变量置为 1,匹配的过程中不区分大小写。
| 语法 | valid_referers none|blocked|server_names|string… |
|---|---|
| 默认值 | — |
| 位置 | server、location |
1 | # 防盗链测试 |
1 | none: 如果Header中的Referer为空,允许访问 |
1 | # 检测到盗链时返回403错误码 |
1 | # 检测到盗链时返回指定页面 |
1 | # 检测到盗链时返回指定图片 |
Referer 的限制比较粗,比如随意加一个 Referer,上面的方式是无法进行限制的
此处我们需要用到 Nginx 的第三方模块 ngx_http_accesskey_module ,第三方模块如何实现盗链
# rewrite
主要的作用是用来实现 URL 的重写。
Nginx 服务器的 Rewrite 功能的实现依赖于 PCRE 的支持,因此在编译安装 Nginx 服务器之前,需要安装 PCRE 库。Nginx 使用的是 ngx_http_rewrite_module 模块来解析和处理 Rewrite 功能的相关配置。
重写和转发的区别:
1 | 地址重写浏览器地址会发生变化而地址转发则不变 |
Module ngx_http_rewrite_module (nginx.org)
1 | # set 该指令用来设置一个新的变量。 |
rewrite 常用全局变量
| 变量 | 说明 |
|---|---|
| $args | 变量中存放了请求 URL 中的请求指令。比如 http://192.168.200.133:8080?arg1=value1&args2=value2 中的 "arg1=value1&arg2=value2",功能和 $query_string 一样 |
| $http_user_agent | 变量存储的是用户访问服务的代理信息 (如果通过浏览器访问,记录的是浏览器的相关版本信息) |
| $host | 变量存储的是访问服务器的 server_name 值 |
| $document_uri | 变量存储的是当前访问地址的 URI。比如 http://192.168.200.133/server?id=10&name=zhangsan 中的 "/server",功能和 $uri 一样 |
| $document_root | 变量存储的是当前请求对应 location 的 root 值,如果未设置,默认指向 Nginx 自带 html 目录所在位置 |
| $content_length | 变量存储的是请求头中的 Content-Length 的值 |
| $content_type | 变量存储的是请求头中的 Content-Type 的值 |
| $http_cookie | 变量存储的是客户端的 cookie 信息,可以通过 add_header Set-Cookie 'cookieName=cookieValue’来添加 cookie 数据 |
| $limit_rate | 变量中存储的是 Nginx 服务器对网络连接速率的限制,也就是 Nginx 配置中对 limit_rate 指令设置的值,默认是 0,不限制。 |
| $remote_addr | 变量中存储的是客户端的 IP 地址 |
| $remote_port | 变量中存储了客户端与服务端建立连接的端口号 |
| $remote_user | 变量中存储了客户端的用户名,需要有认证模块才能获取 |
| $scheme | 变量中存储了访问协议 |
| $server_addr | 变量中存储了服务端的地址 |
| $server_name | 变量中存储了客户端请求到达的服务器的名称 |
| $server_port | 变量中存储了客户端请求到达服务器的端口号 |
| $server_protocol | 变量中存储了客户端请求协议的版本,比如 "HTTP/1.1" |
| $request_body_file | 变量中存储了发给后端服务器的本地文件资源的名称 |
| $request_method | 变量中存储了客户端的请求方式,比如 "GET","POST" 等 |
| $request_filename | 变量中存储了当前请求的资源文件的路径名 |
| $request_uri | 变量中存储了当前请求的 URI,并且携带请求参数,比如 http://192.168.200.133/server?id=10&name=zhangsan 中的 "/server?id=10&name=zhangsan" |
# if
使用正则表达式对变量进行匹配,匹配成功返回 true,否则返回 false。变量与正则表达式之间使用 "","*","!","!*" 来连接。
"~" 代表匹配正则表达式过程中区分大小写,
"~*" 代表匹配正则表达式过程中不区分大小写
"!“和”!*" 刚好和上面取相反值,如果匹配上返回 false, 匹配不上返回 true
判断请求的文件是否存在使用 "-f" 和 "!-f",
当使用 "-f" 时,如果请求的文件存在返回 true,不存在返回 false。
当使用 "!f" 时,如果请求文件不存在,但该文件所在目录存在返回 true, 文件和目录都不存在返回 false, 如果文件存在返回 false
1 | # if (condition){...} |
-
判断请求的目录是否存在使用 "-d" 和 "!-d",
当使用 "-d" 时,如果请求的目录存在,if 返回 true,如果目录不存在则返回 false
当使用 "!-d" 时,如果请求的目录不存在但该目录的上级目录存在则返回 true,该目录和它上级目录都不存在则返回 false, 如果请求目录存在也返回 false.
-
判断请求的目录或者文件是否存在使用 "-e" 和 "!-e"
当使用 "-e", 如果请求的目录或者文件存在时,if 返回 true, 否则返回 false.
当使用 "!-e", 如果请求的文件和文件所在路径上的目录都不存在返回 true, 否则返回 false
-
判断请求的文件是否可执行使用 "-x" 和 "!-x"
当使用 "-x", 如果请求的文件可执行,if 返回 true, 否则返回 false
当使用 "!-x", 如果请求文件不可执行,返回 true, 否则返回 false
# break
该指令用于中断当前相同作用域中的其他 Nginx 配置。与该指令处于同一作用域的 Nginx 配置中,位于它前面的指令配置生效,位于后面的指令配置无效。
1 | location /testbreak { |
# return
该指令用于完成对请求的处理,直接向客户端返回响应状态代码。在 return 后的所有 Nginx 配置都是无效的。
1 | return code [text]; |
code: 为返回给客户端的 HTTP 状态代理。可以返回的状态代码为 0~999 的任意 HTTP 状态代理
text: 为返回给客户端的响应体内容,支持变量的使用
URL: 为返回给客户端的 URL 地址
1 | server /ret { |
# rewrite
该指令通过正则表达式的使用来改变 URI。可以同时存在一个或者多个指令,按照顺序依次对 URL 进行匹配和处理。
1 | # rewrite regex replacement [flag]; |
regex: 用来匹配 URI 的正则表达式
replacement: 匹配成功后,用于替换 URI 中被截取内容的字符串。如果该字符串是以 "http://" 或者 "https://" 开头的,则不会继续向下对 URI 进行其他处理,而是直接返回重写后的 URI 给客户端。
flag: 用来设置 rewrite 对 URI 的处理行为,可选值有如下:
last: 终止继续在本 location 块中处理接收到的 URI,并将此处重写的 URI 作为一个新的 URI,使用各 location 块进行处理。该标志将重写后的 URI 重写在 server 块中执行,为重写后的 URI 提供了转入到其他 location 块的机会。即本条规则匹配完成后,继续向下匹配新的 1ocation URI 规则
break: 将此处重写的 URI 作为一个新的 URI, 在本块中继续进行处理。该标志将重写后的地址在当前的 location 块中执行,不会将新的 URI 转向其他的 location 块。
redirect: 将重写后的 URl 返回给客户端,状态码为 302,指明是临时重定向 URl, 主要用在 replacement 变量不是以 "http:/“或者"https:/”" 开头的情况。浏览器地址会显示跳转后的 URL 地址
permanent: 将重写后的 URI 返回给客户端,状态码为 301,指明是重定向 URl, 主要用在 replacement 变量不是以 "http://“或者"https://”" 开头的情况。浏览器地址栏会显示跳转后的 URL 地址
# rewrite_log
该指令配置是否开启 URL 重写日志的输出功能。
1 | rewrite_log off; |
# rewrite 实现伪静态
1 | # 假设pageNum为前端接收数据,后端根据对应的pageNum展示对应的页面 |
1 | server { |
可以实现访问 http://www.a.com/haha?pageNum=13 时客户端显示 http://www.a.com/13.html
# 域名跳转
1 | # 1.修改hosts |
# 域名镜像
镜像网站指定是将一个完全相同的网站分别放置到几台服务器上,并分别使用独立的 URL 进行访问。其中一台服务器上的网站叫主站,其他的为镜像网站。镜像网站和主站没有太大的区别,可以把镜像网站理解为主站的一个备份节点。
然如果我们不想把整个网站做镜像,只想为其中某一个子目录下的资源做镜像,我们可以在 location 块中配置 rewrite 功能,比如:
提高可用性
加快响应速度
流量负载
1 | # 只对user子目录做镜像 |
# 独立域名
为每个模块设置独立域名
1 | http://search.hm.com 访问商品搜索模块 |
1 | server{ |
# 自动加 /
重定向的地址会有一个指令叫 server_name_in_redirect on|off; 来决定重定向的地址:
1 | 如果该指令为on |
server_name_in_redirect on 时,如果访问 192.168.13.155/shabi 会跳转到 localhost/shabi/ 导致无法访问
自动加 / 可以避免自动跳转
注意 server_name_in_redirect 指令在 Nginx 的 0.8.48 版本之前默认都是 on,之后改成了 off, 所以现在我们这个版本不需要考虑这个问题
1 | server { |
127.0.0.1/shbi 与 127.0.0.1/shabi/ 的区别
127.0.0.1/shabi 不加 / 会 301 重定向到 /shabi/
127.0.0.1/shabi/ 不做重定向
# 目录合并
URL 的目录层级一般不要超过三层,否则的话不利于搜索引擎的搜索也给客户端的输入带来了负担,但是将所有的文件放在一个目录下又会导致文件资源管理混乱并且访问文件的速度也会随着文件增多而慢下来
1 | server { |
# 防盗链
1 | # 检测到盗链时返回指定图片 |
# Nginx 代理
正向代理

1 | # 访问192.168.13.155 82 代理到服务器,服务器认为是155访问的 |
修稿客户端的代理
# 反向代理
Nginx 反向代理模块的指令是由 ngx_http_proxy_module 模块进行解析,该模块在安装 Nginx 的时候已经自己加装到 Nginx 中了
1 | proxy_pass # 设置被代理服务器的地址 |
1 | proxy_set_header |
1 | # proxy_redirect |
当后端三台服务器上内容不一样时的案例:
1 | # 如果后端服务器每台上内容不一样 |
# nginx 安全控制
http 请求转变成 https 请求
nginx 添加 ssl 支持
–with-http_ssl_module
ssl 模块下所有的配置都可以在 http,server 块中配置,下面就省略配置位置了
1 | ssl on; # 开启ssl支持 |
生成证书
阿里云生成
openssl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 mkdir /root/cert
cd /root/cert
openssl genrsa -des3 -out server.key 2048
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
[root@localhost cert]# ls -al
total 20
drwxr-xr-x 2 root root 82 Apr 12 19:48 .
dr-xr-x---. 20 root root 4096 Apr 12 19:42 ..
-rw-r--r-- 1 root root 867 Apr 12 19:48 server.crt
-rw-r--r-- 1 root root 708 Apr 12 19:46 server.csr
-rw------- 1 root root 916 Apr 12 19:47 server.key
-rw------- 1 root root 1062 Apr 12 19:47 server.key.org
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 server {
listen 443 ssl;
server_name localhost;
ssl_certificate /root/cert/server.crt;
ssl_certificate_key /root/cert/server.key
ssl_session_cache shared:SSL:1m; # 工作进程共享缓存 名称 大小
ssl_session_timeout 5m; # 超时时间
ssl_ciphers HIGH:!aNULL:!MD5; # 密码格式
ssl_prefer_server_ciphers on; # 是否服务端密码优先于客户端密码
location / {
root html;
index index.html index.htm;
}
}
1
2
3
4
5
6
7
8 # httprewrite到https,因为浏览器www.baidu.com 默认是http
server {
listen 80;
server_name www,baidu.com;
location / {
rewrite ^(.*) https://baidu.com$1;
}
}
# 反向代理系统优化
Buffer 和 cache
1 | 相同点: |
下面所有的参数都可以在 http,server,location 中配置
1 | proxy_buffering on :该指令用来开启或者关闭代理服务器的缓冲区; |
通用配置
1 | proxy_buffering on; |
# 代理 https 请求
需要第三方模块
https://github.com/chobits/ngx_http_proxy_connect_module
配置
1 | server { |
# 负载均衡
系统的扩展分为纵向扩展和横向扩展
纵向扩展是从单机的角度出发,通过增加系统的硬件处理能力来提升服务器的处理能力
云服务资源增加
・整机:IBM、浪潮、DELL、HP 等
・CPU / 主板:更新到主流
・网卡:10G/40G 网卡
・磁盘:SAS (SCSI) HDD(机械)、HHD(混合)、SATA SSD、PCI-e SSD、
MVMe SSD
• SSD
・多副本机制
・系统盘 / 热点数据 / 数据库存储
• HDD
・冷数据存储
横向扩展是通过添加机器来满足大型网站服务的处理能力。
会话管理
・Nginx 高级负载均衡
• ip_hash
・其他 Hash
• hash $cookie_jsessionid;
• hash $request_uri;
・使用 lua 逻辑定向分发
• Redis + SpringSession

应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理并返回响应的数据。
负载均衡器:将用户访问的请求根据对应的负载均衡算法,分发到集群中的一台服务器进行处理。
负载均衡作用:
1、解决服务器的高并发压力,提高应用程序的处理性能。
2、提供故障转移,实现高可用。
3、通过添加或减少服务器数量,增强网站的可扩展性。
4、在负载均衡器上进行过滤,可以提高系统的安全性。
负载均衡常用方式:
用户手动选择,比如下载时选择电信、联通
DNS 轮询 :对同一个主机名添加多条 A 记录,这就是 DNS 轮询,DNS 服务器将解析请求按照 A 记录的顺序,随机分配到不同的 IP 上,这样就能完成简单的负载均衡。DNS 轮询的成本非常低,在一些不重要的服务器,被经常使用。
1. 可靠性低
假设一个域名 DNS 轮询多台服务器,如果其中的一台服务器发生故障,那么所有的访问该服务器的请求将不会有所回应,即使你将该服务器的 IP 从 DNS 中去掉,但是由于各大宽带接入商将众多的 DNS 存放在缓存中,以节省访问时间,导致 DNS 不会实时更新。所以 DNS 轮流上一定程度上解决了负载均衡问题,但是却存在可靠性不高的缺点。
2. 负载均衡不均衡
DNS 负载均衡采用的是简单的轮询负载算法,不能区分服务器的差异,不能反映服务器的当前运行状态,不能做到为性能好的服务器多分配请求,另外本地计算机也会缓存已经解析的域名到 IP 地址的映射,这也会导致使用该 DNS 服务器的用户在一定时间内访问的是同一台 Web 服务器,从而引发 Web 服务器减的负载不均衡。
负载不均衡则会导致某几台服务器负荷很低,而另外几台服务器负荷确很高,处理请求的速度慢,配置高的服务器分配到的请求少,而配置低的服务器分配到的请求多。
四层 / 七层负载均衡
# 四层负载均衡 / 七层负载均衡
所谓四层负载均衡指的是 OSI 七层模型中的传输层,主要是基于 IP+PORT 的负载均衡
1 | 实现四层负载均衡的方式: |
所谓的七层负载均衡指的是在应用层,主要是基于虚拟的 URL 或主机 IP 的负载均衡
1 | 实现七层负载均衡的方式: |
四层和七层负载均衡的区别
1 | 四层负载均衡数据包是在底层就进行了分发,而七层负载均衡数据包则在最顶端进行分发,所以四层负载均衡的效率比七层负载均衡的要高。 |
其实还有二层、三层负载均衡,二层是在数据链路层基于 mac 地址来实现负载均衡,三层是在网络层一般采用虚拟 IP 地址的方式实现负载均衡。
实际会采用: 四层负载 (LVS)+ 七层负载 (Nginx)
七层负载均衡
Nginx 的负载均衡是在 Nginx 的反向代理基础上把用户的请求根据指定的算法分发到一组【upstream 虚拟服务池】。
1 | upstream 该指令是用来定义一组服务器,它们可以是监听不同端口的服务器,并且也可以是同时监听TCP和Unix socket的服务器。服务器可以指定不同的权重,默认为1。 |

该指令用来指定后端服务器的名称和一些参数,可以使用域名、IP、端口或者 unix socket
1 | upstream backend{ |
代理服务器在负责均衡调度中的状态有以下几个:
| 状态 | 概述 |
|---|---|
| down | 当前的 server 暂时不参与负载均衡,该状态一般会对需要停机维护的服务器进行设置。 |
| backup | 预留的备份服务器,当主服务器不可用时,将用来传递请求。 |
| max_fails | 允许请求失败的次数,默认为 1 |
| fail_timeout | 经过 max_fails 失败后,服务暂停时间,默认是 10 秒 |
| max_conns | 限制最大的接收连接数,默认为 0,表示不限制,使用该配置可以根据后端服务器处理请求的并发量来进行设置,防止后端服务器被压垮。 |
负载均衡策略
Nginx 的 upstream 支持如下六种方式的分配算法,分别是:
| 算法名称 | 说明 |
|---|---|
| 轮询 | 默认方式 |
| weight | 权重方式,权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的,所有此策略比较适合服务器的硬件配置差别比较大的情况 |
| ip_hash | 先 hash,再和后端服务器的数量取余,得到的值就是需要转发到后端的服务器。不适用于局域网项目,即多用户共享 IP 的场景。容易造成流量倾斜。后端服务器宕机导致 session 丢失。适用于中小型项目,快速扩容。 依据 ip 分配方式。能够将某个客户端 IP 的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某一个 IP 的用户在后端 Web 服务器 A 上登录后,在访问该站点的其他 URL,能保证其访问的还是后端 web 服务器 A。ip_hash 指令无法保证后端服务器的负载均衡,可能导致有些后端服务器接收到的请求多,有些后端服务器接收的请求少,而且设置后端服务器权重等方法将不起作用。 |
| least_conn | 依据最少连接方式。有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn 这种方式就可以达到更好的负载均衡效果。 |
| url_hash | 依据 URL 分配方式。url_hash 按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用 url_hash,可以使得同一个 url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。 |
| fair | 依据响应时间方式。可以根据页面大小、加载时间长短智能的进行负载均衡。 |
| $request_uri | 适用于不支持 cookie 的情况下。资源不平均分配:只需要算出 hash 将资源放到对应的服务器 |
| $cookie_jsessionid | sessionid 只有 tomcat 才有,并且 hash 的是 value |
1 | upstream backend{ |
fair
fair 采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小、加载时间长短智能的进行负载均衡。那么如何使用第三方模块的 fair 负载均衡策略。
1 | upstream backend { |
1 | 在Nginx的源码中 src/http/ngx_http_upstream.h,找到ngx_http_upstream_srv_conf_s,在模块中添加添加default_port属性 |
1 | # 实现带有URL重写的负载均衡 |
# stick 实现 cookie 负载均衡
Sticky 是 nginx 的一个模块,它是基于 cookie 的一种 nginx 的负载均衡解决方案,通过分发和识别 cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为 route
客户端首次发起访问请求,nginx 接收后,发现请求头没有 cookie,则以轮询方式将请求分发给后端服务器。
后端服务器处理完请求,将响应数据返回给 nginx。
此时 nginx 生成带 route 的 cookie,返回给客户端。route 的值与后端服务器对应,可能是明文,也可能是 md5、sha1 等 Hash 值
客户端接收请求,并保存带 route 的 cookie。
当客户端下一次发送请求时,会带上 route,nginx 根据接收到的 cookie 中的 route 值,转发给对应的后端服务器。
https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/src/master/
依赖 openssl-devel
1 | ./configure --prefix=/usr/local/nginx --add-module=/root/nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d |
打开 ngx_http_sticky_misc.c 文件
在 12 行添加
1 |
备份之前的程序
1 | mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old |
把编译好的 Nginx 程序替换到原来的目录里
1 | cp objs/nginx /usr/local/nginx/sbin/ |
升级检测
1 | make upgrade |
检查程序中是否包含新模块
1 | nginx -V |
1 | upstream httpds { |
浏览器多标签会共享 cookie,且名字不好和 JESEEIONID 重复
原理是在 cookie 中加入一个字段,从会话保持,也能维持静态会话
# 四层负载均衡
Nginx 在 1.9 之后,增加了一个 stream 模块,用来实现四层协议的转发、代理、负载均衡等。stream 模块的用法跟 http 的用法类似,允许我们配置一组 TCP 或者 UDP 等协议的监听,然后通过 proxy_pass 来转发我们的请求,通过 upstream 添加多个后端服务,实现负载均衡。

1 | --with-stream |
四层和七层都有,四层优先
# 缓存
缓存就是数据交换的缓冲区 (称作:Cache), 当用户要获取数据的时候,会先从缓存中去查询获取数据,如果缓存中有就会直接返回给用户,如果缓存中没有,则会发请求从服务器重新查询数据,将数据返回给用户的同时将数据放入缓存,下次用户就会直接从缓存中获取数据。
| 场景 | 作用 |
|---|---|
| 操作系统磁盘缓存 | 减少磁盘机械操作 |
| 数据库缓存 | 减少文件系统的 IO 操作 |
| 应用程序缓存 | 减少对数据库的查询 |
| Web 服务器缓存 | 减少对应用服务器请求次数 |
| 浏览器缓存 | 减少与后台的交互次数 |
缓存的优点
1. 减少数据传输,节省网络流量,加快响应速度,提升用户体验;
2. 减轻服务器压力;
3. 提供服务端的高可用性;
缓存的缺点
1. 数据的不一致
2. 增加成本
# 浏览器缓存
# 什么时候可以用缓存?
- 不常改变的内容
- 过期时间
- 针对 post/get 请求都可以
- 存储位置
- 磁盘使用空间限制
- deskcache
字面理解是从内存中,其实也是字面的含义,这个资源是直接从内存中拿到的,不会请求服务器一般已经加载过该资源且缓存在了内存当中,当关闭该页面时,此资源就被内存释放掉了,再次重新打开相同页面时不会出现 from memory cache 的情况
- memorycache
是从磁盘当中取出的,也是在已经在之前的某个时间加载过该资源,不会请求服务器但是此资源不会随着该页面的关闭而释放掉,因为是存在硬盘当中的,下次打开仍会 from disk cache
# Age
是 CDN 添加的属性表示在 CDN 中缓存了多少秒
# via
用来标识 CDN 缓存经历了哪些服务器,缓存是否命中,使用的协议
# 强制缓存与协商缓存
强制缓存:直接从本机读取,不请求服务器
协商缓存:发送请求 header 中携带 Last-Modified,服务器可能会返回 304 Not Modified
# 浏览器强制缓存
# cache-control
http1.1 的规范,使用 max-age 表示文件可以在浏览器中缓存的时间以秒为单位
| 标记 | 类型 | 功能 |
|---|---|---|
| public | 响应头 | 响应的数据可以被缓存,客户端和代理层都可以缓存 |
| private | 响应头 | 可私有缓存,客户端可以缓存,代理层不能缓存(CDN,proxy_pass) |
| no-cache | 请求头 | 可以使用本地缓存,但是必须发送请求到服务器回源验证 |
| no-store | 请求和响应 | 应禁用缓存 |
| max-age | 请求和响应 | 文件可以在浏览器中缓存的时间以秒为单位 |
| s-maxage | 请求和响应 | 用户代理层缓存,CDN 下发,当客户端数据过期时会重新校验 |
| max-stale | 请求和响应 | 缓存最大使用时间,如果缓存过期,但还在这个时间范围内则可以使用缓存数据 |
| min-fresh | 请求和响应 | 缓存最小使用时间, |
| must-revalidate | 请求和响应 | 当缓存过期后,必须回源重新请求资源。比 no-cache 更严格。因为 HTTP 规范是允许客户端在某些特殊情况下直接使用过期缓存的,比如校验请求发送失败的时候。那么带有 must-revalidate 的缓存必须校验,其他条件全部失效。 |
| proxy-revalidate | 请求和响应 | 和 must-revalidate 类似,只对 CDN 这种代理服务器有效,客户端遇到此头,需要回源验证 |
| stale-while-revalidate | 响应 | 表示在指定时间内可以先使用本地缓存,后台进行异步校验 |
| stale-if-error | 响应 | 在指定时间内,重新验证时返回状态码为 5XX 的时候,可以用本地缓存 |
| only-if-cached | 响应 | 那么只使用缓存内容,如果没有缓存 则 504 getway timeout |
在浏览器和服务器端验证文件是否过期的时候,浏览器在二次请求的时候会携带 IF-Modified-Since 属性
# Expires
过期时间
1 | expires 30s; #缓存30秒 |
# 协商缓存
# last-modified
# etag
http1.1 支持
在 HTTP 协议中 If-Modified-Since 和 If-None-Match 分别对应 Last-Modified 和 ETag
Entity Tag 的缩写,中文译过来就是实体标签的意思.
HTTP 中并没有指定如何生成 ETag,哈希是比较理想的选择。
在计算 Etag 的时候,会产生 CPU 的耗费,所以也可以用时间戳,但这样直接使用 Last-Modified 即可。
ETag 用来校验用户请求的资源是否有变化,作用和 lastmodified 很像,区别是 lastmodified 精确到秒,ETag 可以用 hash 算法来生成更精确的比对内容。
当用户首次请求资源的时候返回给用户数据和 200 状态码并生成 ETag,再次请求的时候服务器比对 ETag,没有发生变化的话返回 304
Cache-Control 直接是通过不请求来实现,而 ETag 是会发请求的,只不过服务器根据请求的东西的内容有无变化来判断是否返回请求的资源
# cache-control expires 强制缓存
页面首次打开,直接读取缓存数据,刷新,会向服务器发起请求
# etag lastmodify 协商缓存
没发生变化 返回 304 不发送数据
# 浏览器缓存原则
-
多级集群负载时 last-modified 必须保持一致
-
还有一些场景下我们希望禁用浏览器缓存。比如轮训 api 上报数据数据
-
浏览器缓存很难彻底禁用,大家的做法是加版本号,随机数等方法。
-
只缓存 200 响应头的数据,像 3XX 这类跳转的页面不需要缓存。
-
对于 js,css 这类可以缓存很久的数据,可以通过加版本号的方式更新内容
-
不需要强一致性的数据,可以缓存几秒
-
异步加载的接口数据,可以使用 ETag 来校验。
-
在服务器添加 Server 头,有利于排查错误
-
分为手机 APP 和 Client 以及是否遵循 http 协议
-
在没有联网的状态下可以展示数据
-
流量消耗过多
-
提前下发 避免秒杀时同时下发数据造成流量短时间暴增
-
兜底数据 在服务器崩溃和网络不可用的时候展示
-
临时缓存 退出即清理
-
固定缓存 展示框架这种,可能很长时间不会更新,可用随客户端下发
- 首页有的时候可以看做是框架 应该禁用缓存,以保证加载的资源都是最新的
-
父子连接 页面跳转时有一部分内容不需要重新加载,可用从父菜单带过来
-
预加载 某些逻辑可用判定用户接下来的操作,那么可用异步加载那些资源
-
漂亮的加载过程 异步加载 先展示框架,然后异步加载内容,避免主线程阻塞
Nginx 是从 0.7.48 版开始提供缓存功能。Nginx 是基于 Proxy Store 来实现的,其原理是把 URL 及相关组合当做 Key, 在使用 MD5 算法对 Key 进行哈希,得到硬盘上对应的哈希目录路径,从而将缓存内容保存在该目录中。它可以支持任意 URL 连接,同时也支持 404/301/302 这样的非 200 状态码。Nginx 即可以支持对指定 URL 或者状态码设置过期时间,也可以使用 purge 命令来手动清除指定 URL 的缓存。
Nginx 的 web 缓存服务主要是使用 ngx_http_proxy_module 模块相关指令集来完成
1 | # proxy_cache_path 该指定用于设置缓存文件的存放路径 |

1 | http{ |
# 删除缓存
1 | 1.rm -rf /usr/local/proxy_cache/...... |
# 设置资源不缓存
比如说对于一些经常发生变化的数据。如果进行缓存的话,就很容易出现用户访问到的数据不是服务器真实的数据。所以对于这些资源我们在缓存的过程中就需要进行过滤,不进行缓存。
1 | # 配置位置http,server,location |
上述两个指令都有一个指定的条件,这个条件可以是多个,并且多个条件中至少有一个不为空且不等于 "0", 则条件满足成立。里面使用到了三个变量,分别是 $cookie_nocache、$arg_nocache、$arg_comment
1 | $cookie_nocache |
1 | server{ |
或者通过 url 指定后面两个参数
/jquery.js?nocache=1
/jquery.js?comment=1
都不会缓存或者使用 set cookie 中的 nocache
上面三个变量只要不是 0 就行
推荐两个都用 proxy_no_cache proxy_cache_bypass
# 动静分离
动:后台应用程序的业务处理
静:网站的静态资源 (html,javaScript,css,images 等文件)
分离:将两者进行分开部署访问,提供用户进行访问。举例说明就是以后所有和静态资源相关的内容都交给 Nginx 来部署访问,非静态内容则交个类似于 Tomcat 的服务器来部署访问。
Nginx 在处理静态资源的时候,效率是非常高的,而且 Nginx 的并发访问量也是名列前茅,而 Tomcat 则相对比较弱一些,所以把静态资源交个 Nginx 后,可以减轻 Tomcat 服务器的访问压力并提高静态资源的访问速度。
动静分离以后,降低了动态资源和静态资源的耦合度。如动态资源宕机了也不影响静态资源的展示。
实现动静分离的方式很多,比如静态资源可以部署到 CDN、Nginx 等服务器上,动态资源可以部署到 Tomcat,weblogic 或者 websphere 上。
1 | # 将后端服务器上的静态资源删除 |
# keepalived
Keepalived 软件由 C 编写的,最初是专为 LVS 负载均衡软件设计的,Keepalived 软件主要是通过 VRRP 协议实现高可用功能。
1. 选择协议
1 | VRRP可以把一个虚拟路由器的责任动态分配到局域网上的 VRRP 路由器中的一台。其中的虚拟路由即Virtual路由是由VRRP路由群组创建的一个不真实存在的路由,这个虚拟路由也是有对应的IP地址。而且VRRP路由1和VRRP路由2之间会有竞争选择,通过选择会产生一个Master路由和一个Backup路由。 |
2. 路由容错协议
1 | Master路由和Backup路由之间会有一个心跳检测,Master会定时告知Backup自己的状态,如果在指定的时间内,Backup没有接收到这个通知内容,Backup就会替代Master成为新的Master。Master路由有一个特权就是虚拟路由和后端服务器都是通过Master进行数据传递交互的,而备份节点则会直接丢弃这些请求和数据,不做处理,只是去监听Master的状态 |

1 | 步骤1:从官方网站下载keepalived,官网地址https://keepalived.org/ |
打开 keepalived.conf 配置文件
这里面会分三部,第一部分是 global 全局配置、第二部分是 vrrp 相关配置、第三部分是 LVS 相关配置。
1 | global全局部分: |
1 | VRRP部分,该部分可以包含以下四个子模块 |
1 | global_defs { |
1 | keepalived只能做到对网络故障和keepalived本身的监控,即当出现网络故障或者keepalived本身出现问题时,进行切换。但是这些还不够,我们还需要监控keepalived所在服务器上的其他业务,比如Nginx,如果Nginx出现异常了,仅仅keepalived保持正常,是无法完成系统的正常工作的,因此需要根据业务进程的运行状态决定是否需要进行主备切换,这个时候,我们可以通过编写脚本对业务进程进行检测监控。 |

要想让 vip 进行切换,就必须要把服务器上的 keepalived 进行关闭,而什么时候关闭 keepalived 呢?应该是在 keepalived 所在服务器的 nginx 出现问题后,把 keepalived 关闭掉,就可以让 VIP 执行另外一台服务器,但是现在这所有的操作都是通过手动来完成的,我们如何能让系统自动判断当前服务器的 nginx 是否正确启动,如果没有,要能让 VIP 自动进行 "漂移"
keepalived 只能做到对网络故障和 keepalived 本身的监控,即当出现网络故障或者 keepalived 本身出现问题时,进行切换。但是这些还不够,我们还需要监控 keepalived 所在服务器上的其他业务,比如 Nginx, 如果 Nginx 出现异常了,仅仅 keepalived 保持正常,是无法完成系统的正常工作的,因此需要根据业务进程的运行状态决定是否需要进行主备切换,这个时候,我们可以通过编写脚本对业务进程进行检测监控。
实现步骤:
- 在 keepalived 配置文件中添加对应的配置像
1 | vrrp_script 脚本名称 |
- 编写脚本
ck_nginx.sh
1 | #!/bin/bash |
1 | chmod 755 ck_nginx.sh |
1 | vrrp_script ck_nginx { |
通常如果 master 服务死掉后 backup 会变成 master,但是当 master 服务又好了的时候 master 此时会抢占 VIP,这样就会发生两次切换对业务繁忙的网站来说是不好的。所以我们要在配置文件加入 nopreempt 非抢占,但是这个参数只能用于 state 为 backup,故我们在用 HA 的时候最好 master 和 backup 的 state 都设置成 backup 让其通过 priority 来竞争。
# 制作下载站点
nginx 使用的是模块 ngx_http_autoindex_module 来实现的,该模块处理以斜杠 ("/") 结尾的请求,并生成目录列表。
nginx 编译的时候会自动加载该模块,但是该模块默认是关闭的,我们需要使用下来指令来完成对应的配置
1 | # 以下都可以在http,server,location 配置 |
1 | location /download{ |
# 用户认证模块
对应系统资源的访问,我们往往需要限制谁能访问,谁不能访问。这块就是我们通常所说的认证部分,认证需要做的就是根据用户输入的用户名和密码来判定用户是否为合法用户,如果是则放行访问,如果不是则拒绝访问。
Nginx 对应用户认证这块是通过 ngx_http_auth_basic_module 模块来实现的,它允许通过使用 "HTTP 基本身份验证" 协议验证用户名和密码来限制对资源的访问。默认情况下 nginx 是已经安装了该模块,如果不需要则使用–without-http_auth_basic_module。
1 | (1)auth_basic:使用“ HTTP基本认证”协议启用用户名和密码的验证 |
1 | location /download{ |
yum install -y httpd-tools
1 | htpasswd -c /usr/local/nginx/conf/htpasswd username //创建一个新文件记录用户名和密码 |
13-Nginx 用户认证模块的使用_哔哩哔哩_bilibili
# keepalive
需要持续获取请求,通过 http 连接,则开启 keepalive
1 | keepalive_timeout 65; |

如果一个 connections 中有多个 transactions,那么说明这些 transactions 是复用了这个 connections
对于 keepalive 链接,服务端通过 content-length 区分每一个请求
# 什么时候使用?
明显的预知用户会在当前连接上有下一步操作
复用连接,有效减少握手次数,尤其是 https 建立一次连接开销会更大
# 什么时候不用?
访问内联资源一般用缓存,不需要 keepalive
长时间的 tcp 连接容易导致系统资源无效占用
1 | # http块的keepalive |
1 | # upstream 块的长连接 |
1 | 出现大量TIME_WAIT的情况 |
1 | http { |
# 对客户端限制
client_body_buffer_size
对客户端请求中的 body 缓冲区大小
默认 32 位 8k 64 位 16k
如果请求体大于配置,则写入临时文件
client_header_buffer_size
设置读取客户端请求体的缓冲区大小。 如果请求体大于缓冲区,则将整个请求体或仅将其部分写入临时文件。 默认 32 位 8K。 64 位平台 16K。
client_max_body_size 1000M;
默认 1m,如果一个请求的大小超过配置的值,会返回 413 (request Entity Too Large) 错误给客户端
将 size 设置为 0 将禁用对客户端请求正文大小的检查。
client_body_timeout
指定客户端与服务端建立连接后发送 request body 的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx 返回 HTTP 408(Request Timed Out)
client_header_timeout
客户端向服务端发送一个完整的 request header 的超时时间。如果客户端在指定时间内没有发送一个完整的 request header,Nginx 返回 HTTP 408(Request Timed Out)。
client_body_temp_path path
[level1[level2[level3`]]]在磁盘上客户端的 body 临时缓冲区位置
client_body_in_file_only on;
把 body 写入磁盘文件,请求结束也不会删除
client_body_in_single_buffer
尽量缓冲 body 的时候在内存中使用连续单一缓冲区,在二次开发时使用
$request_body读取数据时性能会有所提高client_header_buffer_size
设置读取客户端请求头的缓冲区大小
如果一个请求行或者一个请求头字段不能放入这个缓冲区,那么就会使用 large_client_header_buffers
large_client_header_buffers
默认 8k
# 获取客户端 IP
X-Forwarded-for:将上一层的 remoteaddr 写入到 x-forwarded-for
remote_addr 建立 tcp 连接的时候的 IP,反向代理时一定是 nginx 的 ip,无法伪造
1 | location / { |
如果存在多级代理,除了第一级代理以外直接转发即可,无需在设置 x-forwarded-for
或者在加一个 ip X-Forwarded-For: ip1,ip2
# concat 压缩请求个数
concat 模块压缩请求数,减少并发请求个数
淘宝网即,?? 代表这是一个合并请求

https://www.nginx.com/nginx-wiki/build/dirhtml/modules/concat/
./configure --prefix=/usr/local/nginx --add-module=/root/Downloads/nginx-http-concat/
1 | location /static/css/ { |
1 | <link href="??font.css,bg.css" rel="stylesheet"> |
png 的可以一张图片包含多张图,在用切割展示不同的部分

其实就是把 css 文件拼接

# 根据 IP 判断用户位置
云厂商在 DNS 中有实现,也可以在 GEOIP 中自己实现
GEOIP 判断 IP 所属区域,实现 IP 阻断或限制
# 1 下载数据库
官网需注册登录
下载数据库
maxmind.com
# 2 安装依赖
# 官方 git
https://github.com/maxmind/libmaxminddb
下载后执行编译安装之后
1 | $ echo /usr/local/lib >> /etc/ld.so.conf.d/local.conf |
# Nginx 模块
https://github.com/leev/ngx_http_geoip2_module
1 | geoip2 /root/GeoLite2-ASN_20220524/GeoLite2-ASN.mmdb { |
# 健康检查
主动检查模式
Nginx 服务端会按照设定的间隔时间主动向后端的 upstream_server 发出检查请求来验证后端的各个 upstream_server 的状态。 如果得到某个服务器失败的返回超过一定次数,比如 3 次就会标记该服务器为异常,就不会将请求转发至该服务器。
一般情况下后端服务器需要为这种健康检查专门提供一个低消耗的接口。
被动检查模式
Nginx 在代理请求过程中会自动的监测每个后端服务器对请求的响应状态,如果某个后端服务器对请求的响应状态在短时间内累计一定失败次数时,Nginx 将会标记该服务器异常。就不会转发流量给该服务器。 不过每间隔一段时间 Nginx 还是会转发少量的一些请求给该后端服务器来探测它的返回状态。 以便识别该服务器是否恢复。
后端服务器不需要专门提供健康检查接口,不过这种方式会造成一些用户请求的响应失败,因为 Nginx 需要用一些少量的请求去试探后端的服务是否恢复正常。
重试机制
1 | upstream { |
主动状态检查
tengine 版
https://github.com/yaoweibin/nginx_upstream_check_module
nginx 商业版
http://nginx.org/en/docs/http/ngx_http_upstream_hc_module.html
1 | 1.下载安装nginx 1.20.2 |
1 | upstream backend { |
./nginx -c /usr/local/nginx20/conf/nginx.conf

# 资源静态化
将原本需要计算的请求缓存成文件放在 nginx 里
并发最高的:列表,详情页
前端合并和后端合并
前端合并:节约服务器资源,消耗请求数
后端合并:ssi
# ssi
通常称为服务器端嵌入,是一种类似于 ASP 的基于服务器的网页制作技术。
一个静态化的页面中,需要嵌入一小块实时变化的内容,。例如首页,大部分的页面内容需要缓存但是用户登录后的个人信息是动态信息,不能缓存。那么如何解决这个” 页面部分缓存” 问题,利用 SSI 就可以解决,在首页的静态页面中嵌入个人信息的动态页,由于是服务器端的嵌入,所以用户浏览的时候都是一个嵌入后的页面。
http://nginx.org/en/docs/http/ngx_http_ssi_module.html
1 | # http, server, location |
1 | <!--#include file="header.html"--> |

# rsync
https://www.samba.org/ftp/rsync/rsync.html
remote synchronize 是一个远程数据同步工具,可通过 LAN/WAN 快速同步多台主机之间的文件。也可以使用 rsync 同步本地硬盘中的不同目录。
rsync 是用于替代 rcp 的一个工具,rsync 使用所谓的 rsync 算法 进行数据同步,这种算法只传送两个文件的不同部分,而不是每次都整份传送,因此速度相当快。
rsync 基于 inotify 开发
Rsync 有三种模式:
- 本地模式(类似于 cp 命令)
- 远程模式(类似于 scp 命令)
- 守护进程(socket 进程:是 rsync 的重要功能)
# 安装
两端安装
1 | yum install -y rsync |
#
# 密码文件
创建文件 /etc/rsync.password
内容
1 | hello:123 |
修改权限
1 | chmod 600 /etc/rsync.password |
修改配置
1 | auth users = sgg |
# 开机启动
在 /etc/rc.local 文件中添加
1 | rsync --daemon |
- 修改权限
echo “sgg:111” >> /etc/rsyncd.passwd
# 查看远程目录
rsync --list-only 192.168.44.104::www/
# 拉取数据到指定目录
rsync -avz rsync://192.168.44.104:873/www
rsync -avz 192.168.44.104::www/ /root/w
# 使用 SSH 方式
rsync -avzP /usr/local/nginx/html/ root@192.168.44.105:/www/
# 推送
修改配置
1 | rsync -avz --password-file=/etc/rsyncd.passwd.client /usr/local/nginx/html/ rsync://sgg@192.168.44.105:/www |
--delete 删除目标目录比源目录多余文件
# 实时推送
推送端安装 inotify
依赖
1 | yum install -y automake |
1 | wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz |
监控目录
1 | /usr/local/inotify/bin/inotifywait -mrq --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %w%f %e' -e close_write,modify,delete,create,attrib,move //usr/local/nginx/html/ |
# 简单自动化脚本
1 | !/bin/bash |
# nginx + php
1 | # 这里新加的 |
1、nginx 的 worker进程 直接管理每一个请求到 nginx 的网络请求。
2、php-fpm 程序也如同 nginx 一样,需要监听端口,并且有 master 和 worker 进程。worker 进程直接管理每一个 php 进程。
3、关于 fastcgi:fastcgi 是一种进程管理器,管理 cgi 进程。市面上有多种实现了 fastcgi 功能的进程管理器,php-fpm 就是其中的一种。再提一点,php-fpm 作为一种 fast-cgi 进程管理服务,会监听端口, 一般默认监听9000端口,并且是监听本机 ,也就是只接收来自本机的端口请求,所以我们通常输入命令 netstat -nlpt|grep php-fpm 会得到:
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1057/php-fpm
这里的 127.0.0.1:9000 就是监听本机 9000 端口的意思。
4、关于 fastcgi 的配置文件,目前 fastcgi 的配置文件一般放在 nginx.conf 同级目录下,配置文件形式,一般有两种:fastcgi.conf 和 fastcgi_params。不同的 nginx 版本会有不同的配置文件,这两个配置文件有一个非常重要的区别:fastcgi_parames 文件中缺少下列配置:
fastcgi_param SCRIPT_FILENAME fastcgi_script_name;
我们可以打开 fastcgi_parames 文件加上上述行,也可以在要使用配置的地方动态添加。使得该配置生效。
5、 当需要处理php请求时,nginx的worker进程会将请求移交给php-fpm的worker进程进行处理,也就是最开头所说的nginx调用了php,其实严格得讲是nginx间接调用php
Nginx 和 PHP 的配置 - 知乎 (zhihu.com)
php 环境搭建(正确配置 nginx 和 php) - 知乎 (zhihu.com)