一、nginx介绍
Nginx(“engine x”)是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。和apache一样,都是web服务器软件,因为其性能优异,所以被广大运维喜欢。又因为nginx是一个轻量级的web服务器,相比apache来说资源消耗更低。
nginx官网:http://nginx.org/
nginx与apache的比较,Nginx适合处理静态页面,apache处理动态页面
Web服务器 | Nginx | Apache |
反向代理 | 非常好 |
|
Rewrite规则 | 非常好 | 好 |
系统压力比较 | 很小 | 小 |
内存消耗 | 非常小 | 很大 |
静态文件处理 | 非常好 | 一般 |
稳定性 | 非常好 | 好 |
安全性 | 一般 | 好 |
技术资料 | 很少 | 非常多 |
虚拟主机 | 支持 | 支持 |
热部署 | 支持 | 不支持 |
FastCGI | 好 | 差 |
二、nginx部署
安装部署
下载nginx源码包
wget http://nginx.org/download/nginx-1.19.3.tar.gz -P /usr/src
安装依赖包
yum -y install gcc pcre-devel zlib-devel openssl-dev
- gcc: 源码编译工具
- pcre-devel: nginx url_rewrite 功能提供包,支持nginx的正则表达
- zlib-devel: nginx 压缩功能提供包
- openssl-dev:安全网络功能
解压nginx源码包
tar xf nginx-1.19.3.tar.gz
cd nginx-1.19.3/
配置nginx源码
./configure --prefix=/usr/local/nginx
配置目的:
(1)检查环境是否满足安装条件,依赖解决
(2)指定安装方式,配置文件、命令文、各种文件放哪里
(3)开启模块功能【内置模块 三方模块】
(4)指定软件安装在那里
编绎源码
make
安装
make install
相关目录
—安装目录:/usr/local/nginx/
—主配置文件:conf/nginx.conf
—网页目录:html
—日志文件:logs
—启动脚本:sbin/nginx
—模块目录:modules
—进程目录:pid
nginx启动管理
配置文件测试:/usr/local/nginx/sbin/nginx -t
启动:/usr/local/nginx/sbin/nginx
停止:/usr/local/nginx/sbin/nginx -s stop
关闭:/usr/local/nginx/sbin/nginx -s quit 【优雅关闭,在退出前完成已经接受的连接请求】
关闭:killall -s QUIT nginx
加载:/usr/local/nginx/sbin/nginx -s reload 【重新加载配置文件】
2.启动测试
nginx安装完毕,接下来就可以启动nginx了,nginx启动后如何测试nginx的启动状态呢?可以通过以下三种方式去测试,这个可以根据自己的习惯选择一种测试就行了。
使用netstat命令查看启动端口
netstat -ntpl
使用losf命令查看启动端口
lsof -i :80
使用文本浏览器访问nignx默认网站
elinks http://192.168.65.21
3.编辑服务脚本
vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx - web server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
ExecQuit=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
重新加载系统服务
systemctl daemon-reload
启动服务
systemctl start nginx
开机自启
systemctl enable nginx.service
三、nginx配置
最基本配置
worker_processes 1; # 默认为1,表示开户一个业务进程
events { # 事件驱动模块
worker_connections 1024; # 单个业务进程可接受连接数
}
http {
include mime.types; # 引入http mime类型
default_type application/octet-stream;# 如果mime类型没匹配上,默认使用二进制流的方式传输
sendfile on; # 使用linux的sendfile(socket,file,len)高效网络传输,也就是数据0拷贝。未开户senfile
keepalive_timeout 65; # 保持连接配置
server { # 虚拟主机
listen 80; # 监听的端口号
server_name localhost; # 主机名、域名
location / { # location是匹配用户输入的路径,url
root html; # 默认存放网页的目录路径
index index.html index.htm; # 默认网页
}
error_page 500 502 503 504 /50x.html; # 发生错误展示的页面
location = /50x.html {
root html;
}
}
}
nginx默认配置文件大概分为几个区域:
没有被 {} 包裹的部分为全局配置:
—如worker_processes 1; 设置工作进程(子进程)数为 1
events {} 为 nginx 连接配置的模块:
—如worker_connections 1024; 设置每一个子进程最大允许连 接 1024 个连接
http {} 为 nginxhttp 核心配置模块
—而 http {} 中还有 server {},以及 server {} 中的 location {}
server {} 为虚拟主机配置模块,包括监听端口、监听域名、IP等内容
—在一个 Nginx 的配置文件里面,我们是可以指定多个 Sever 区块的配置的。
location {} URI 匹配
—细分到针对不同的路径和请求而进行的配置。一个站点中 URI 通常会很多,在 Location 区块设置,可以写多个 Location 的配置的。
虚拟主机
原本一台服务器只能对应一个站点,通过虚拟主机技术可以虚拟化成多个站点同时对外提供服务。
2.1、域名解析、端口监听
基于域名的虚拟主机,实现两个基于域名的虚拟主机,可以在server_name匹配多个域名
基于端口的虚拟主机,实现两个基于端口的虚拟主机,可以listen监听多个端口
http框架是定义与nginx网站相关的配置
server:虚拟主机
listen:端口
server_name:主机,可以填IP或域名
location:网页地址
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server { # 第一个虚拟主机
listen 80; # 端口
server_name www.s.com; # 主机、域名
location / {
root /www/www;
index index.html index.htm;
}
}
server { # 第二个虚拟主机
listen 88; # 端口
server_name vod.s.com; # 主机、域名
location / {
root /www/vod;
index index.html index.htm;
}
}
ServerName匹配规则
ServerName匹配是从上往下的顺序,前面匹配成功了,就不会向下匹配了。
完整匹配:可以在同一个servername中匹配多个域名
server_name vod.s.com vod1.s.com;
通配符匹配
server_name *.s.com; # *通配符匹配,*.s.com域名匹配同一个网页
通配符结束匹配
server_name vod.*; # *通配符匹配,不管vod.*域名访问都是同一个网页
正则匹配:比较适用于二级域名系统,符合哪些规则就进入到对应的server里面进行转发。
server_name ~^[0-9]+\.s\.com$;
2.2、location
相同类型的表达式,字符串长的会优先匹配
按优先级排列
① = 类型
② ^~类型表达式
③ 正则表达式 (~和 ~*) 类型
④常规字符串匹配类型,按前缀匹配
⑤ 通用匹配(/),如果没有其他匹配,任何请求都会匹配到
location优先级规则
①匹配某个具体文件:(location=完整路径) >(location ~ 完整路径) > (location ~ *完整路径) >(location~完整路径) > (location完整路径) > (location /)
②用目录做匹配访问某个文件:(location=目录) >(location ^ ~ 目录/) > (location ~ 目录 ) > (location~*目录) > (location目录) > (location /)
反向代理
正向代理:搭建一个属于自己的代理服务器
①用户发送请求到自己的代理服务器
②自己的代理服务器发送请求到服务器
③服务器将数据返回到自己的代理服务器
④自己的代理服务器再将数据返回给用户
反向代理:七层代理,调度作用,该功能可以通过组建后台集群提高网站性能
①用户发送请求到服务器(访问的其实是 反向代理 服务器,但用户不知道)
②反向代理服务器发送请求到真正的服务器
③真正的服务器将数据返回给反向代理服务器
④反向代理服务器再将数据返回给用户
3.1、代理服务器
proxy_pass:location模块内配置,和网页目录同级别,定义的服务器列表,可以填写域名、IP。不支持代理https服务器
location / {
proxy_pass http://www.baidu.com; # 请求转向baidu,proxy_pass和root目录二选一
}
集群代理
upstream:http模块内配置,模块内的server是服务器列表,和server模块同级别。
proxy_pass:调用集群,在location模块内配置,和upstream集群名保持一致。
upstream jiangying { # 创建集群,定义代理的服务器列表
server 192.168.65.22:80; # 是IP、端口、状态的配置
server 192.168.65.10:80;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://jiangying; # 请求转向到jiangying定义的服务器列表
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
3.2、UpStream
3.2.1、上游服务器
UpStream工作流程:proxy_pass 向上游服务器请求数据共有6个阶段
- 初始化
- 与上游服务器建立连接
- 向上游服务器发送请求
- 处理响应头
- 处理响应体
- 结束
配置说明
参 数 | 作 用 | 案 例 |
set_header | 设置header | |
proxy_connect_timeout | 与上游服务器连接超时时间、快速失败 | |
proxy_send_timeout | 定义nginx向后端服务发送请求的间隔时间(不是耗时)。默认60秒,超过这个时间会关闭连接 | |
proxy_read_timeout | 后端服务给nginx响应的时间,规定时间内后端服务没有给nginx响应,连接会被关闭,nginx返回504 Gateway Time-out。默认60秒 | |
proxy_requset_buffering | 缓冲区,是否完全读到请求体之后再向上游服务器发送请求,on打开,off关闭 | |
proxy_buffering | 是否缓冲上游服务器数据,on打开,off关闭 | |
proxy_buffers | 缓冲区大小 32个128k大小内存缓冲块 | proxy_buffers 32 128k; |
proxy_buffer_size | header缓冲区大小 | proxy_buffer_size 64k; |
proxy_busy_buffers_size | ||
proxy_max_temp_file_size | 临时文件最大值 | proxy_max_temp_file_size 1024m; |
proxy_temp_file_write_size | 当启用从代理服务器到临时文件的响应的缓冲时,一次限制写入临时文件的数据的大小。默认情况下,大小由proxy_buffer_size和proxy_buffers指令设置的两个缓冲区限制。临时文件的最大大小由proxy_max_temp_file_size指令设置。 |
3.2.1.1、获取客户端真实IP
X-Real-IP额外模块,不推荐使用
setHeader,配置在location模块,$remote_addr获取真实的客户地址,通过proxy_set_header将地址写入到X-Forwarded-For。
proxy_set_header X-Forwarded-For $remote_addr;
3.2.2、客户端
对客户端的限制,可配置位置:- http、- server、- location
配置说明
参 数 | 作 用 | 案 例 |
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 EntityToo Large)错误给客户端,将size设置为0将禁用对客户端请求正文大小的检查。 | |
client_body_timeout | 指定客户端与服务端建立连接后发送 request body 的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx返回 HTTP 408(Request Timed Out) | |
client_header_timeout | 客户端向服务端发送一个完整的 request header 的超时时间。如果客户端在指定时间内没有发送一个完整的request header,Nginx 返回 HTTP408(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 |
反向代理中的容错机制
参考文档:
https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/
http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_bind
3.2.1、负载均衡策略
轮询
最基本的配置方法,它是upstream模块默认的负载均衡默认策略。每个请求会按时间顺序逐一分配到不同的后端服务器。在轮询中,如果服务器down掉了,会自动剔除该服务器。此策略适合服务器配置相当,无状态且短平快的服务使用。
weight:权重方式,在轮询策略的基础上指定轮询的几率。权重越高分配到需要处理的请求越多,此策略可以与least_conn和ip_hash结合使用,适合服务器的硬件配置差别比较大的情况。
upstream jiangying {
server 192.168.65.22:80 weight=8;
server 192.168.65.10:80 weight=2;
}
down:标记服务器永久停机了。
upstream jiangying {
server 192.168.65.22:80 down;
server 192.168.65.10:80;
}
backup:标记该服务器为备用服务器。当主服务器停止时,请求会被发送到它这里。
upstream jiangying {
server 192.168.65.22:80;
server 192.168.65.10:80 backup;
}
健康检查
max_fails:允许失败的次数
fail_timeout:与max_fails结合使用。检查失败后,需要等30s,再重新连接
fail_time:失败后,暂停服务的时间,服务器会被认为停机的时间长度,默认为10s。
upstream jiangying {
server 192.168.65.22:80;
server 192.168.65.10:80 max_fails=2 fail_timeout=30;
}
3.2.3、least_conn
最少连接访问。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。
upstream jiangying {
least_conn;
server 192.168.65.22:80;
server 192.168.65.10:80;
}
3.2.4、第三方策略
第三方的负载均衡策略的实现需要安装第三方插件。
fair:根据后端服务器响应时间来分配请求,响应时间短的优先分配。
url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。
总结:以上便是6种负载均衡策略的实现方式,其中除了轮询和轮询权重外,都是Nginx根据不同的算法实现的。在实际运用中,需要根据不同的场景选择性运用,大都是多种策略结合使用以达到实际需求。
3.4、四层代理
其他业务集群:nginx四层代理(TCP/UDP高度),nginx从1.9版本才开始支持该功能
模块查询
./configure --help
配置四层代理模块--with-stream
./configure --with-stream
make && make install
http之外配置集群
stream { # 四层代理模块
upstream backend { # 创建集群
server 192.168.65.22:22;
server 192.168.65.10:22;
}
server {
listen 12345;
proxy_pass backend; # 调用集群
}
}
验证:远程业务,可以轮询登录到后方集群的服务器
ssh 192.168.65.21 -p 12345
动静分离
因nginx的静态处理能力很强,但动态处理能力不足,所以在企业中常采用动静分离技术,针对PHP,将静态页面交给nginx处理,动态页面交给PHP-FPM模块或Apache处理。在nginx的配置文件中,是通过location配置段配合正则匹配来实现静态与动态页面的不同处理方式。在企业信息化应用环境中,服务器的安全性和响应速度需要根据实际情况进行相应参数配置,以达到最优的用户体验。默认的nginx安装参数只能供最基本的服务,还需要调整如网页缓存时间,连接超时,网页压缩等相应参数,餐能发挥出服务器的最大作用。
4.1、动静分离原理
Nginx动静分离概述
Nginx的静态处理能力很强,但是动态处理能力不足,因此,在企业中常用动静分离技术
针对PHP的动静分离
静态页面交给 Nginx处理
动态页面交给 PHP-FPM模块或 Apache处理
在 Nginx的配置中,是通过 ocation配置段配合正则匹配实现静态与动态页面的不同处理方式
Nginx实现动静分离配置
我们根据需要,将配置Nginx实现动静分离,对php页面的请求转发给LAMP或LNMP处理,而静态页面交给Nginx处理,从而实现动静分离。
部署 LNMP环境任务要求
— 安装Linux(操作系统)、Nginx(网站服务)、Mysql(数据库)、PhP( 编写动态网站的语言工具,pythen也可以)环— 境启动Nginx、MySQL、PHP服务
— 测试Nginx及MySQL、PHP是否工作正常
LNMP常见问题
Nginx的默认访问日志文件为/usr/local/nginx/logs/access.log
Nginx的默认错误日志文件为/usr/local/nginx/logs/error.log
PHP默认错误日志文件为/var/log/php-fpm/www-error.log
4.2、动静分离部署(LNMP)
4.2.1、环境配置
安装相关软件,软件仓库没有mysql,安装mariadb
yum -y install mariadb mariadb-server mariadb-devel php php-mysql php-fpm
动态网站创建需要安装的软件
mariadb:数据库包
mariadb-server:客户端数据库包
mariadb-devel:数据库的依赖包,开发环境软件包
php(FastCGI):开发语言解释器
php-fpm:关联nginx与php的服务
php-mysql:关联php与数据库的服务
启动服务
systemctl start php-fpm
systemctl start mariadb
修改Nginx配置文件并启动服务
vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name localhost;
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
}
注:
~ \.php$:~是开启正则表达式,\转义作用,匹配.php结尾的文件,动态网页设置
fastCGI:快速公共网关接口,可以连接网站程序(nginx)到网站的语言解释器(如php),php-fpm为fastCGI的管理者。fastcgi.conf:fastcgi_params改成fastcgi.conf,更改扩展名称,安装php-fpm生成的文件,要比原有文件可靠。
4.2.2、案例1:php网页配置
查看php-fpm配置文件
vim /etc/php-fpm.d/www.conf
[www]
listen = 127.0.0.1:9000 # PHP端口号
listen.allowed_clients = 127.0.0.1
group = apache
pm = dynamic
pm.max_children = 50 # 最大进程数量
pm.start_servers = 5 # 最小进程数量
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
创建PHP页面
vim /usr/local/nginx/html/test.php
<html>
<body>
This is HTML message
</br>
<?php
$c = 12;
$d = 2;
if($c > $d){echo "c is bigger";}
else{ echo "d is bigger";}
?>
</body>
</html>
浏览器验证php网页:IP/test.php
4.2.3、案例2:动态网站调用数据库
创建PHP测试页面,连接并查询MariaDB数据库。
vim /usr/local/nginx/html/mysql.php
<?php
$mysqli = new mysqli('localhost','root','','mysql');
#注意:root为mysql数据库的账户名称,密码需要修改为实际mysql密码,无密码则留空即可
#localhost是数据库的域名或IP,mysql是数据库的名称
if (mysqli_connect_errno()){
die('Unable to connect!'). mysqli_connect_error();
}
$sql = "select * from user";
$result = $mysqli->query($sql);
while($row = $result->fetch_array()){
printf("Host:%s",$row[0]);
printf("</br>");
printf("Name:%s",$row[1]);
printf("</br>");
}
?>
进入数据库,创建新的用户‘jy’
systemctl restart mariadb.service
mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.68-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> create user jy@localhost identified by '123';
Query OK, 0 rows affected (0.00 sec)
验证:浏览器访问IP/mysql.php,会看到Name:jy
安全配置
5.1、登录认证
在HTTP中,HttpAuthBasic模块可以使用用户名和密码基于 HTTP 基本认证(Basic access authentication),这是一种用来允许网页浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。
默认值: auth_basic off 作用域: http, server, location, limit_except 该指令包含用于 HTTP 基本认证 的测试名和密码
在server模块中添加以下配置信息,开启认证提示
vim /usr/local/nginx/conf/nginx.conf
auth_basic "password"; # 自定义提示语句,开启认证提示
auth_basic_user_file "/usr/local/nginx/pass"; # 密码文件存放位置在pass文件中
注:
auth_basic 可设置为off或其它字符串,为off时表示不开启密码验证,或者#注释效果一样
auth_basic_user_file 为包含用户名和密码的文件,具体位置就是htpasswd生成账号及密码的存放路径
安装创建加密文件软件
yum -y install httpd-tools
首次创建加密文件、用户,增加用户不用-c
htpasswd -c /usr/local/nginx/pass tom # pass是加密文件,tom是用户,提示输入密码
验证:浏览器登录网页,输入用户和密码
5.2、https证书配置
--with-http_ssl_module是安全网站模块,源码安装Nginx时必须使用–with-http_ssl_module参数,启用加密模块,对于需要进行SSL加密处理的站点添加ssl相关指令(设置网站需要的私钥和证书)。
openssl:包含SSL协议库、应用程序以及密码处法库,自签名openssl系统内置
加密算法
对称算法:AES、DES,使用相同的字符串加密和解密,主要应用在单机数据加密。应用案例 :RAR、ZIP压缩加密
非对称算法:RSA、DSA,利用公钥(锁)加密,私钥(钥匙)解密,主要应用在网络数据加密。应用案例:https、ssh
信息摘要:MD5、sha256、sha512,数据校验,主要应用在数据完整性校验。
5.2.1、加密网站设置
更改配置文件
vim /usr/local/nginx/conf/nginx.conf
server {
listen 443 ssl;
server_name localhost; # IP或域名
ssl_certificate cert.pem; # 公钥
ssl_certificate_key cert.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;
}
}
创建私钥,用来解密的
openssl genrsa > /usr/local/nginx/conf/cert.key # genrsa使用rsa非对称算法
创建证书(正式的证书需要花费,证明https是合规的),里面包含公钥
openssl req -x509 -key /usr/local/nginx/conf/cert.key > /usr/local/nginx/conf/cert.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JY # 国家
State or Province Name (full name) []:JY # 省份
Locality Name (eg, city) [Default City]:JY # 城市
Organization Name (eg, company) [Default Company Ltd]:JY # 公司
Organizational Unit Name (eg, section) []:JY # 部门
Common Name (eg, your name or your server's hostname) []:JY # 服务器
Email Address []:JY@163.com # 邮箱
注:
req -x509:请求创建-x509格式的证书,-x509证书是国际通用标准。
-key /usr/local/nginx/conf/cert.key:指定私钥创建公钥
重新加载文件
systemctl reload nginx.service
验证
mkdir /usr/local/nginx/html_c
echo "nginx-c~~~~" > /usr/local/nginx/html_c/index.html
curl -k https://www.jiangying.com # -k忽略风险提示
地址重写
6.1、URL重写介绍
和apache等web服务软件一样,rewrite的主要功能是实现URL地址的重定向。Nginx的rewrite功能需要PCRE软件的支持,即通过perl兼容正则表达式语句进行规则匹配的。默认参数编译nginx就会支持rewrite的模块,但是也必须要PCRE的支持。
Rewrite功功能是Nginx服务器提供的一个重要功能。几乎是所有的web产品必备技能,用于实现URL重写。URL重写是非常有用的功能,比如它可以在我们在改变网站结构后,不需要客户端修改原来的书签,也不需要其他网站修改对我们网站的友情链接,还可以在一定程度上提高网站的安全性,能够让我们的网站显得更专业。
6.2、应用场景
域名变更(京东)
用户跳转 (从某个连接跳到另一个连接)
伪静态场景 (便于CDN缓存动态页面数据)
rewrite地址重写
可以定义用户的访问路径可以看到的实际内容。相同网站间的调转,获得一个来访的URL请求,然后改写成服务器可以的另一个URL的过程。地址重写可以是网页、域名、浏览器。
重写优点:缩短URL,隐藏实际路径提高安全性,易于用户记录和键入,易于被搜索引擎收录
正则表达式:区分大小写匹配~;不区分大小写匹配~*;区分大小写不区配!~;不区分大小写不匹配~!*。
语法格式:
— 宽松匹配:rewrite 匹配路径(A) 实际页面(B) 选项 # 浏览器输入路径A,看到页面B,网页名前后可以加东西
— 精确匹配:rewrite ^匹配路径$(A) 实际页面(B) 选项 # 网页名前后不可以加东西
— 条件判断:if(条件){任务} # 满足什么条件,就执行重定向到哪个地址
—选项有:
last:本条规则匹配完成后,继续向下匹配新的location url规则
Break:本条规则匹配完成既终止,不再匹配后面的任何规则
redirect:临时重定向,状态码302,爬虫不敢兴趣
permanent:永久重定向,状态码301,爬虫感兴趣
6.2.1、相同网站不同页面
rewrite ^/a.html$ /b.html redirect; # 临时,打开a网站转到b网站,加上^和$符号严格匹配,否则可以在前后加字符符号。
rewrite ^/a.html$ /b.html permanent; # 永久,但是redirect为临时重定向,permanent为永久重定向
6.2.2、不同网站之间的跳转
rewrite /(.*) 新网站网址/$1 ; # 将旧网站调转到新网站,()保留/理解为复制,(.*)保留/复制任意值,$1相当于将前面保留的内容粘贴/复制到新网站之后
6.2.3、不同浏览器或访问端之间的调转
if ($http_user_agent ~* firefox){
rewrite /(.*) /firefox/$1;
}
注:条件判断,如果用户使用了火狐浏览器,就进行地址重写操作,让用户看到火狐专属页面。
if:判断语句
():放条件
$http_user_agent:是nginx的内置变量,存储了用户的信息,比如用的什么浏览器
~* firefox:~匹配正则,*忽略大小写,包含有firefox字样;
{}:放的任务
6.2.4、针对同一个范围
同一个范围有多个rewrite之后,系统会整体分析跳转最终位置,需要在语句结尾添加last,同一个范围的rewrite不发生混淆。
rewrite ^/a.html$ /b.html last;
rewrite ^/b.html$ /c.html ;
6.2.5、针对不同范围
在不同的location下面有多个rewrite之后,地址重写Break:不再读其他的语句结束请求,不同范围的rewrite不发生混淆。
rewrite ^/a.html$ /b.html break;
错误页面
HTTP常见错误代码列表
200:一切正常
301:表示网址的重定向,临时重定向
302:临时重定向
400:请求语法错误,客户端方面的问题
401:访问被拒绝(账户或密码错误)
403:资源不可用,通常由于服务器上文件或目录的权限设置导致,禁止访问(客户端额IP地址被拒绝)
404:无法找到指定位置的资源(Not Found),服务端不知道客户端请求的资源有哪个
410:服务端知道客户端请求的资源曾经存在但是现在不存在了
414:请示UIR头部太长
500:服务器内部错误
502:web服务器没有回应,没有接受到有效信息。服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应
更改nginx404报错的页面显示
error_page 404 /test.jpg; # 配置错误页面,然后存储一个test.jpg图片到/usr/local/nginx/html/目录下。
状态页面
status模块,可以查看网站后台数据,如Nginx连接数等信息,--with-http_stub_status_module开启模块功能。
安装模块--with-http_stub_status_module
./configure --with-http_stub_status_module
make && make install
状态页面设置
location /status {
stub_status on; # 显示后台数据
allow 192.168.65.21; # 允许查看的数据的服务器
deny all; # 禁止其他服务器查看
}
访问状态status页面:curl http://IP/status
Activeconnections:当前活动的连接数量(当前有多少用户访问该网站)。
Accepts:已经接受客户端的连接总数量。
Handled:已经处理客户端的连接总数量。
Requests:客户端发送的请求数量。
Reading:当前服务器正在读取客户端请求头的数量。
Writing:当前服务器正在写响应信息的数量。
Waiting:当前多少客户端在等待服务器的响应。
优化配置
参考文档:
https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/
http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_bind
9.1、缓存优化
解决客户端访问头部信息过长的问题,还要以缓存文件到客户,缓存服务器,还可以通过varnish,squid缓存文件,搭建缓存服务器。增加用户访问速度 。当客户端在访问服务器时,由服务器决定将生么文件缓存在客户端。
缓存优化配置
location ~* \.(jpg|html|txt)$ { # 缓存文件类型
expires 30d; # 缓存时长
}
访问网站,通过浏览器缓存(Expires)过期时间是一个月,说明缓存成功。
9.2、超长地址
nginx是一个强大的http服务器,但是在使用过程中发现,当遇到超长的post请求或者get请求时,nginx会返回413、400、414等状态码,这是因为请求串长度超过了nginx默认的缓存大小或者请求串大小。
超长地址访问设置,在主配置文件中server之外,http之内。
client_header_buffer_size 200k; # 改为200K
large_client_header_buffers 4 200k; # 如果200k不够用,再添加4个200k
注:
client_header_buffer_size:可以定义将识别的头部信息(包含地址栏)的大小
large_client_header_buffers:定义个数
9.2、并发优化
9.2.1、开发和并行的区别
「并发」强调的是可以一起「出『发』」,「并行」强调的是可以一起「执『行』」。
并发:与可以一起出发的并发(concurrent)相对的是不可以一起出发的顺序(sequential)
顺序:上一个开始执行的任务完成后,当前任务才能开始执行
并发:无论上一个开始执行的任务是否完成,当前任务都可以开始执行
(也就是说,A B 顺序执行的话,A 一定会比 B 先完成,而并发执行则不一定。)
并行:与可以一起执行的并行(parallel)相对的是不可以一起执行的串行(serial)
串行:有一个任务执行单元,从物理上就只能一个任务、一个任务地执行
并行:有多个任务执行单元,从物理上就可以多个任务一起执行
(也就是说,在任意时间点上,串行执行时必然只有一个任务在执行,而并行则不一定。)
总结
综上,并发与并行并不是互斥的概念,只是前者关注的是任务的抽象调度、后者关注的是任务的实际执行。而它们又是相关的,比如并行一定会允许并发。
单核 CPU 多任务:并发(不必等上一个任务完成才开始下一个任务)、串行(只有一个实际执执行任务的 CPU 核)
多线程:并发、串行(所有线程都在同一个核上执行);并发、并行(不同线程在不同的核上执行)
9.2.2、优化nginx并发
worker_processes 2;
events {
worker_connections 500000;
}
注:
worker_processes:定义后台开启nginx的进程数量,与CPU数量一致
worker_connections:限制访问用户,一个nginx可以允许访问的用户数
9.2.3、文件访问
Linux系统默认打开文件的个数最大不得超过1024,客户端访问一个页面,相当于打开了一个文件,需要改动linux的配置文件。
临时配置
ulimit -n # 查看同时打开文件的数量
ulimit -n 100000 # 配置同时打开文件的数量
永久配置
vim /etc/security/limits.conf
* soft nofile 10000
* hard nofile 10000
注:
*:服务器
nofile:打开文件的限制
soft:软限制达到之,想要打开设置。
hard:硬限制,最多打开限制,后有硬限制报警。
9.2.4、压测
ab -c 2000 -n 2000 http://192.168.65.21/ # -c访问人数,-n访问次数,100%证明测试成功
9.3、会话管理
9.3.1、hash
根据客户端的IP地址转发同一台服务器,可以保持回话。这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。
upstream jiangying {
ip_hash;
server 192.168.65.22:80;
server 192.168.65.10:80;
}
其他:
【hash $cookie_jsessionid; 】:根据jsessionid地址转发同一台服务器;
【hash $request_uri;】:根据uri地址转发同一台服务器,适用于访问不同的服务器资源;
注意:
在nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
ip_hash不能与backup同时使用。
此策略适合有状态服务,比如session。
当有服务器需要剔除,必须手动down掉。
9.3.2、缓存
客户登录:session与Cookie,作用避免客户重复登录。客户端登陆时由服务器端的session与客户端的cookies的id作对比。
—Session:【服务端】存储在服务器端,保存用户名、登陆状态等信息,
—Cookies:【客户端】由服务器下发给客户端,保存在客户端/var/lib/php/session。保存的内容主要包括:SessionID
memcached简介:可以利用内存读写数据的数据库服务,创建分布式缓存服务器,高性能的分布式缓存服务器,集中缓存数据库查询结果,减少数据库访问次数,以提高动态web应用的响应速度;官方网站:http://memcached.org/
9.3.2.1、环境配置
关闭防火墙和selinux
部署有登录界面的LNMP动态网站,配置代理集群
在后端服务器 /usr/local/nginx/html/存储PHP网页
部署memcached(存储服务器)、telnet(远程登录工具)
yum -y install memcached telnet
systemctl start memcached.service
systemctl enable memcached.service
查看memcached的端口
cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""
telnet测试memcached
telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
memcached常用指令
set name 0 180 10 # 添加或替换变量,创建变量name,0不压缩,存活190s,存放10个字符
get name # 读取变量
delete name # 删除变量
add name 0 180 10 # 变量不存在则添加
replace name 0 180 10 # 替换
flush_all # 清空所有
quit # 退出登记
9.3.2.2、session共享配置
安装php-pecl-memcache工具,关联PHP和memcache
yum -y install php-pecl-memcache
systemctl start php-fpm
登录后端服务器节点,配置session存储
vim /etc/php-fpm.d/www.conf
php_value[session.save_handler] = memcache # 存储的方式
php_value[session.save_path] = tcp://192.168.65.21:11211 # 存储的地址
测试session共享
浏览器访问服务器,刷新页面后,登录账户会被记录在memcached服务器,再次刷新页面,调度器切换服务器后,账户信息还在,两台后端服务器使用的是同一个帐户。
9.3.2、sticky模块
Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为route。
官网:https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/src/master/
工作原理:
1.客户端首次发起访问请求,nginx接收后,发现请求头没有cookie,则以轮询方式将请求分发给后端服务器。
2.后端服务器处理完请求,将响应数据返回给nginx。
3.此时nginx生成带route的cookie,返回给客户端。route的值与后端服务器对应,可能是明文,也可能是md5、sha1等Hash值
4.客户端接收请求,并保存带route的cookie。
5.当客户端下一次发送请求时,会带上route,nginx根据接收到的cookie中的route值,转发给对应的后端服务器。
安装依赖
yum -y install openssl
上传解压
unzip nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d.zip
进到源码目录重新编译
./configure --prefix=/usr/local/nginx --add-module=/root/nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d
备注:
--add-module:添加第三方模块
错误:make报错
![](https://i-blog.csdnimg.cn/blog_migrate/334a27b01d59a2aaddc8b95610123a9d.png)
解决:修改源码,修改后重新执行编译
vim /root/nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d/ngx_http_sticky_misc.h
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <ngx_string.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
备份之前的程序
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
编译好的Nginx程序替换到原来的目录里
cp nginx-1.19.3/objs/nginx /usr/local/nginx/sbin/
升级检测
make upgrade
检查程序
/usr/local/nginx/sbin/nginx -V
配置sticky模块的使用
upstream jiangying {
sticky;
server 192.168.65.21;
server 192.168.65.22;
}
备注:
每台后端真实服务器都会有一个唯一的route值,所以不管你真实服务器前端有几个装了sticky的nginx代理,他都是不会变化的。
参数:
sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h] [hash=index|md5|sha1] [no_fallback] [secure] [httponly];
— [name=route]:设置用来记录会话的cookie名称
— [domain=.foo.bar]:设置cookie作用的域名
— [path=/]:设置cookie作用的URL路径,默认根目录
— [expires=1h]:设置cookie的生存期,默认不设置,浏览器关闭即失效,需要是大于1秒的值
— [hash=index|md5|sha1]:设置cookie中服务器的标识是用明文还是使用md5值,默认使用md5
— [no_fallback]:设置该项,当sticky的后端机器挂了以后,nginx返回502 (Bad Gateway or Proxy Error) ,而不转发到其他服务器,不建议设置
— [secure]:设置启用安全的cookie,需要HTTPS支持
— [httponly]:允许cookie不通过JS泄漏,没用过
9.4、防盗链
防盗链简单来说就是存在我们服务中的一些资源,只有我们规定的合法的一类人才能去访问,其他人就不能去访问的资源
(如css,js,img等资源)。
具体点就是用户发送请求给nginx服务器,nginx服务器根据请求去寻找资源,请求的比如说是有个index.html文件,这个文件中会包含很多js,css,img等资源,这些文件在这个骨架中会被二次请求,在第二次请求时,会在请求头部上加上有个referer,这个referer只会在第二次请求时才会被加上。(referer表示第二次资源的来源地址)
9.4.1、防盗链配置
valid_referers:nginx会通过查看referer自动和valid_referers后面的内容进行匹配,如果匹配到了就将$invalid_referer变量置0,如果没有匹配到,则将$invalid_referer变量置为1,匹配的过程不区分大小写
语法:valiad_referers none|blocked|server_names|string
— none:如果header中的referer为空,允许访问
— blocked:在header中的referer不为空,但是该值被防火墙或代理服务器进行伪装过,如不带“http://”、“https://”等协议头的资源允许访问。
— server_names:指定具体的域名或者IP
默认值:-
位置(可以书写的地方):server,location
在需要防盗链的location中配置
valid_referers 192.168.65.21;
if ($invalid_referer){
rewrite ^/ /image/x.png break; # 匹配的提示页面
return 403; # 返回的提示码
}
9.5、curl
安装curl
yum -y install curl
使用curl测试,显示head的信息
curl -I http://192.168.65.21
HTTP/1.1 200 OK
Server: nginx/1.19.3
Date: Mon, 13 Mar 2023 08:12:30 GMT
Content-Type: text/html
Content-Length: 5
Connection: keep-alive
Last-Modified: Fri, 03 Mar 2023 03:56:47 GMT
ETag: "64016fff-5"
Accept-Ranges: bytes
9.6、keepalive
HTTP协议的Keep-Alive意图在于短时间内连接复用,希望可以短时间内在同一个连接上进行多次请求/响应,在http协议header中可以看到当前连接状态。
TCP的KeepAlive机制意图在于保活、心跳,检测连接错误。当一个TCP连接两端长时间没有数据传输时(通常默认配置是2小时),发送keepalive探针,探测链接是否存活。
应用场景:明显的预知用户会在当前连接上有下一步操作,复用连接,有效减少握手次数,尤其是https建立一次连接开销会更大。
关闭场景: 访问内联资源一般用缓存,不需要keepalive,长时间的tcp连接容易导致系统资源无效占用。
9.6.1、客户端
客户端使用keepalive,在http区域配置。
vim /usr/local/nginx/conf/nginx.conf
keepalive_timeout 65;
keepalive_time 1h;
keepalive_request 1000;
send_timeout 60;
备注:
keepalive_timeout:超过配置时间没有活动,会让keepalive失效,用于设置Nginx服务器与客户端保持连接的超时时间,0即关闭,默认65s
keepalive_time:一个tcp连接总时长,超过之后强制失效,默认1h
keepalive_request:单个连接中可处理的请求数,一个tcp复用中可以并发接收的请求个数,默认1000
keepalive_disable:不对某些浏览器建立长连接,默认msie6
send_timeout:【注意:准备过程中,不是传输过程】,系统中若有耗时操,超过时间强制断开连接,默认60s
9.6.2、上游服务器
upstream中配置
vim /usr/local/nginx/conf/nginx.conf
keepalive 100;
keepalive_timeout 65;
keepalive_request 1000;
备注:
keepalive:向上游服务器的保留连接数
keepalive_timeout:连接保留时间
keepalive_requests:一个tcp复用中 可以并发接收的请求个数
server中配置
首先需要配置使用http1.1协议。以便建立更高效的传输,默认使用http1.0,默认使用http1.0协议,需要在request中增加”Connection: keep-alive“ header才能在Upstream中所配置的上游服务器默认都是用短连接,即每次请求都会在完成之后断开,而HTTP1.1默认支持。
vim /usr/local/nginx/conf/nginx.conf
proxy_http_version 1.1;
proxy_set_header Connection ""; # 清除close信息
9.6.3、验证
AB安装
yum install httpd-tools
参数:
- -n 即requests,用于指定压力测试总共的执行次数。
- -c 即concurrency,用于指定的并发数。
- -t 即timelimit,等待响应的最大时间(单位:秒)。
- -b 即windowsize,TCP发送/接收的缓冲大小(单位:字节)。
- -p 即postfile,发送POST请求时需要上传的文件,此外还必须设置-T参数。
- -u 即putfile,发送PUT请求时需要上传的文件,此外还必须设置-T参数。
- -T 即content-type,用于设置Content-Type请求头信息,例如:application/x-www-form-urlencoded,默认值为text/plain。
- -v 即verbosity,指定打印帮助信息的冗余级别。
- -w 以HTML表格形式打印结果。
- -i 使用HEAD请求代替GET请求。
- -x 插入字符串作为table标签的属性。
- -y 插入字符串作为tr标签的属性。
- -z 插入字符串作为td标签的属性。
- -C 添加cookie信息,例如:"Apache=1234"(可以重复该参数选项以添加多个)。
- -H 添加任意的请求头,例如:"Accept-Encoding:gzip",请求头将会添加在现有的多个请求头之后(可以重复该参数选项以添加多个)。
- -A 添加一个基本的网络认证信息,用户名和密码之间用英文冒号隔开。
- -P 添加一个基本的代理认证信息,用户名和密码之间用英文冒号隔开。
- -X 指定使用的和端口号,例如:"126.10.10.3:88"。
- -V 打印版本号并退出。
- -k 使用HTTP的KeepAlive特性。
- -d 不显示百分比。
- -S 不显示预估和警告信息。
- -g 输出结果信息到gnuplot格式的文件中。
- -e 输出结果信息到CSV格式的文件中。
- -r 指定接收到错误信息时不退出程序。
- -h 显示用法信息,其实就是ab -help。
9.7、 获取客户端真实IP
X-Real-IP额外模块,不推荐使用。proxy_set_header在location模块中设置,X-Forwarded-For真实的客户端IP,写入到$remote_addr。
proxy_set_header X-Forwarded-For $remote_addr;
9.8、压缩
9.8.1、Gzip静态压缩
gzip属于在线压缩,在资源通过http发送报文给客户端的过程中,进行压缩,可以减少客户端带宽占用,减少文件传输大小。一般写在http、server或者location均可。
配置说明
参 数 | 作 用 |
gzip on; | 开关,默认关闭 |
gzip_buffers 32 4k; | 缓冲区大小 |
gzip_comp_level 1; | 压缩等级 1-9,数字越大压缩比越高 |
gzip_http_version 1.1; | 使用gzip的最小版本 |
gzip_min_length 256; | 设置将被gzip压缩的响应的最小长度。 长度仅由“Content-Length”响应报头字段确定。 |
gzip_proxied any; | 多选
expired - 启用压缩,如果header头中包含 "Expires" 头信息 no-cache - 启用压缩,如果header头中包含 "Cache-Control:no-cache"头信息 no-store - 启用压缩,如果header头中包含"Cache-Control:no-store" 头信息 private - 启用压缩,如果header头中包含 "Cache-Control:private"头信息 no_last_modified - 启用压缩,如果header头中不包含 "Last-Modified" 头信息 no_etag - 启用压缩 ,如果header头中不包含"ETag" 头信息 auth - 启用压缩 , 如果header头中包含 "Authorization"头信息
|
gzip_vary on; | 增加一个header,适配老的浏览器 `Vary: Accept-Encoding` |
gzip_types ; | 哪些mime类型的文件进行压缩 |
gzip_disable ; | 禁止某些浏览器使用gzip |
完整实例
gzip on;
gzip_buffers 16 8k;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types text/plainapplication/x-javascript text/css application/xml;
gzip_types
text/xml application/xmlapplication/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
text/javascriptapplication/javascript application/x-javascript
text/x-json application/jsonapplication/x-web-app-manifest+json
text/css text/plaintext/x-component
font/opentypeapplication/x-font-ttf application/vnd.ms-fontobject
image/x-icon;
gzip_disable "MSIE[1-6]\.(?!.*SV1)";
9.8.2、gzip_static动态压缩
在前端代码打包构建bundle的时候,一般都有根据一定的算法自动压缩代码成gz文件的webpack插件;当我们不在 nginx 开启 gzip_static的时候,发现生产的gz文件并没有被运行;gzip_static是会自动执行gz文件的,这样的就避免了通过gzip自动压缩;一般写在http、server或者location均可。
ngx_http_gunzip_module模块帮助不支持gzip的客户端解压本地文件。
重新编译nginx
./configure --with-http_gzip_static_module --with-http_gunzip_module
make
systemctl stop nginx
cd ..
cp nginx /usr/local/sbin/
systemctl start nginx
配置说明
参 数 | 作 用 |
gzip_static on; | on|off|always: on:检查客户端支不支持gzip,不支持的话就不会发送gzip包 off:关闭 always:不管客户端支不支持,都会发送gzip包; |
9.8.3、Brotli
#### 安装
- 官网
-`https://github.com/google/ngx_brotli`
-`https://codeload.github.com/google/brotli/tar.gz/refs/tags/v1.0.9`
- 下载 两个项目
- 解压缩
模块化编译
```shell
./configure --with-compat --add-dynamic-module=/root/ngx_brotli-1.0.0rc--prefix=/usr/local/nginx/
```
或
```
--add-dynamic-module=brotli目录
```
- make
- 将`ngx_http_brotli_filter_module.so``ngx_http_brotli_static_module.so`拷贝到`/usr/local/nginx/modules/`
- 复制nginx主程序
- 配置文件中添加
```
load_module"/usr/local/nginx/modules/ngx_http_brotli_filter_module.so";
load_module"/usr/local/nginx/modules/ngx_http_brotli_static_module.so";
```
```
brotli on;
brotli_static on;
brotli_comp_level 6;
brotli_buffers 16 8k;
brotli_min_length 20;
brotli_types text/plain text/csstext/javascript application/javascript text/xml application/xmlapplication/xml+rss application/json image/jpeg image/gif image/png;
```
- 测试
默认http协议是没有br的
```
curl -H 'Accept-Encoding: gzip' -I http://localhost
```