内容简介:32核64G, 数千万并发链接nginx-1.14.0 14 双数版本, 为稳定版, 奇数为不稳定版替换 nginx 的二进制执行文件
nginx 核心知识100讲笔记
主要应用场景
-
静态资源服务
- 本地文件系统
-
反向代理服务
- 缓存
- 负载均衡
-
API 服务
- OpenRestry
32核64G, 数千万并发链接
nginx 组成
- 二进制可执行文件
- 配置文件 nginx.conf
- access.log , 记录每一条 http 请求信息
- error.log , 定位问题
nginx-1.14.0 14 双数版本, 为稳定版, 奇数为不稳定版
nginx 编译
nginx-1.14.1 ├── CHANGES ├── CHANGES.ru ├── LICENSE ├── README ├── auto # 提供编译的包, 识别操作系统 ├── conf # 实例文件 ├── configure # 编译脚本 ├── contrib # 提供 vim 语法. cp -r contrib/vim/* ~/.vim/ ├── html # 50x.html, index.html ├── man # nginx 帮助文件 └── src # 源代码
./configure --help
- 文件目录. 主要使用 --prefix
- 参数, with 表示默认不包括, 需要手动添加. without 表示默认包括, 需要手动排除
- 特殊参数
./configure # 会生成中间文件, 路径 objs/, 里面有个 ngx_modules.c, 内容是编辑中包含的模块 make # 生成中间文件, 和运行的二进制文件, 路径 objs/ . !!!做版本升级的时候, 把二进制文件拷贝到目录, 不需要执行 make install !!! make install # 首次安装时使用的命令
nginx 配置语法
- 配置文件由指令与指令快构成, http {} 指令快
- 每条指令以 ; 结尾, 指令与参数之间以空格分割
- 指令快以 {} 将多个指令组织在一起
- include 语句允许组合多个配置文件以提升可维护性
- # 注释
- $ 使用变量
- 支持正则
时间单位
- ms 毫秒
- s 秒
- m 分
- h 小时
- d 天
- w 周
- M 月
- y 年
空间单位
- 不加表示 bytes 字节
- k/K 千字节
- m/M 兆
- g/G
http 指令快
- http
- server
- location
- upstream
nginx 命令行
- nginx -s reload
- -? -h
- -c 配置文件
- -g 配置指令
- -p 运行目录
- -s 发送信号 stop/quit(优雅停止)/reload/reopen(重新开始记录日志文件)
- -t -T
- -v -V
热部署, 版本升级
替换 nginx 的二进制执行文件
kill -USR2 12345
# 12345 是 nginx 运行的主进程号
这时会有两个 nginx 进程, 一个老的, 一个新的
kill -WINCH 12345
# 优雅的关闭老的所有进程
这时还是有两个 nginx 进程
旧的会保留在那里, 用作版本回退, 把老的 nginx 恢复回去, 然后 kill -USR1 12345
来重新启用.
如果没问题, 用 kill -QUIT
把老进程号杀掉
lsof -p 进程号
# 可以看到进程打开的句柄, 也包括监听的端口
日志切割
mv access.log access.log.bak nginx -s reopen
简单服务器
# 命名为 main
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" ';
'"$http_user_agent" "$http_x_forwarded_for"'
gzip on;
gzip_min_length 1; # 小于1字节就不再压缩了
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css applicatioin/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; # 要压缩的文件类型
server {
listen 8080;
location / {
alias dlib/; # 相对路径
autoindex on; # 显示目录
set $limit_rate 1k; # 限制速度, 每秒传输
}
access_log logs/access.log main;
}
具有缓存的反向代理
# 设置缓存目录, 10M 共享内存
proxy_cache_path /tmp/nginxcache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m user_temp_path=off;
server {
listen 127.0.0.1:8080;
}
upstream local {
server 127.0.0.1:8080;
}
server {
server_name abc.com;
listen 80;
location / {
proxy_set_header Host $host; #
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache my_cache;
proxy_cache_key $host$uri$is_args$args; # 设定 key
proxy_cache_valid 200 304 302 1d;
proxy_pass http://local;
}
}
goaccess
goaccess access.log -o report.html --log-format=COMBINED
Let's Encrypt
详细参考官方文档
yum install python2-certbot-nginx certbot --nginx --nginx-server-root=/usr/loca/nginx/conf -d www.abc.com # 该命令自动增加了 listen 443 ssl; ssl_certificate /etc/letsencrypt/live/www.abc.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.abc.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # 表示非对称加密使用的参数 cat /etc/letsencrypt/options-ssl-nginx.conf ssl_session_cache shared:le_nginx_SSL:1m; # ssl 最消耗是握手, 增加 cache 1m, 大约是4000个连接 ssl_session_timeout 1440m; # 每个握手第一次连接, 如果断开了, 在1440分(一天)时间内是可以复用的 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "这里一堆安全套件名称";
OpenResty
下载最新版
openresty-1.13.6.2 ├── COPYRIGHT ├── README-windows.txt ├── README.markdown ├── bundle # 模块 ├── configure ├── patches └── util
编译
./configure make && make install
简单示例, 把用户代理显示到浏览器中
location /lua {
default_type text/html;
content_by_lua 'ngx.say("User-Agent: ", ngx.req.get_headers()["User-Agent"])';
}
nginx 进程结构
多进程结构
nginx -s reload # 关掉 work 和 cache 进程, 重新启用, 不用进程号, 父进程号一样 kill -SIGHUP 9170 # 父进程号, 同 reload kill -SIGTERM 16982 # 子进程号, 杀掉子进程, 父进程会自动重新启用一个子进程
nginx 信号
master 进程
监控 worker 进程
- CHLD # 子进程终止的时候, 会向父进程发送这个信号
管理 worker 进程
接受信号
- TERM, INT # 立刻停止进程
- QUIT # 优雅停止
- HUP # 重载配置文件
- USR1 # 重新打开日志文件, 做日志文件切割
- # 上面4个可以通过 nginx 命令行运行, 下面两个只能通过 kill 直接向父进程发送信号
- USR2 # 这两个热部署
- WINCH
worker 进程
接受信号, 通常不对 work 进程发送信号
- TERM, INT
- QUIT-
- USR1
- WINCH
nginx 命令行
- reload : HUP
- reopen : USR1
- stop : TERM
- quit : QUIT
热升级流程
编译选项, 路径必须一致
- 将旧 nginx 文件换成新 nginx 文件(注意备份)
- 向 master 进程发送 USR2 信号
- master 进程修改 pid 文件名, 加后缀 .oldbin
- master 进程用新 nginx 文件启动新 master 进程
- 向老 master 进程发送 WINCH 信号, 关闭老 worker
- 回滚: 向老 master发送 HUP, 向新 master 发送 quit
共享内存工具 , ngx_slab_stat 模块
下载一个 tengine , 在里面找这个模块
./configure --add-module=../tengine-2.2.2/modules/ngx_slab_stat/
location = /slab_stat {
slab_stat;
}
#######################
connection_pool_size 512; # 连接内存池, 512 字节 request_pool_size 4k; # 请求内存池, 通常是 connection_pool_size 8倍
nginx 请求
- 精准匹配
- 处理 *.liuhonghe.me
- * 在后的泛域名
- 按文件的顺序匹配正则表达式域名
- default . listen 后面指定的 default
server {
server_name first.liuhonghe.me second.liuhonghe.me;
server_name_in_redirect on; # 默认是 off, 表示, 当访问 second.liuhonghe.me/redirect, 会转到 first.liuhonghe.me/redirect
return 302 /redirect;
}
server {
server_name .liuhonghe.me; # 匹配 liuhonghe.me *.liuhonghe.me
server_name _; # 匹配所有
server_name ""; # 匹配没有传递 Host 头部的请求
}
nginx 处理的 11 个阶段
- post read. realip
- server_rewrite. rewrite
- find_config
- rewrite. rewrite
- post_rewrite
- preaccess. limit_conn, limit_req
- access. auth_basic, access, auth_request
- post_access
- precontent. try_files
- content. index, autoindex. concat
- log. access_log
realip 模块, 用户真实 ip
修改客户端地址, --with-http_realip_module
, 提供 realip_remote_addr
和 real_remote_port
两个变量, 指令 set_real_ip_from
real_ip_header
real_ip_recursive
- X-Forwarded-For 可以多个 IP
- X-Real-IP 一个 IP
使用: 拿到真实 ip 后, 基于变量使用, 如 binary_remote_addr
remote_addr
这样的的变量
───────┬────────────────────
│ File: realip.conf
───────┼────────────────────
1 │ server {
2 │ server_name realip.liuhonghe.me;
3 │
4 │ error_log logs/myerror.log debug;
5 │ set_real_ip_from 192.168.1.107; # 如果是这个 IP 连过来的, 进行以下操作
6 │ #real_ip_header X-Real-IP;
7 │ #real_ip_recursive off;
8 │ real_ip_recursive on;
9 │ real_ip_header X-Forwarded-For;
10 │
11 │ location /{
12 │ return 200 "Client real ip: $remote_addr\n";
13 │ }
14 │ }
───────┴────────────────────
rewrite 模块
- 444 关闭连接
- 301 http1.0 永久重定向
- 302 http1.0 临时重定向, 禁止被缓存
- 303 http1.1 临时重定向, 允许改变方法, 禁止被缓存
- 307 http1.1 临时重定向, 不允许改变方法, 禁止被缓存
- 308 http1.1 永久重定向, 不允许改变方法
语法: rewrite regex replacement [flag];
-
将
regex指定的url替换成replacement这个新的 url, 可以使用正则表达式及变量提取 -
当
replacement以http://或者https://或者$schema开头, 则返回302重定向 -
替换后的
url根据flag指定的方式进行处理replacement
───────┬────────────────────
│ File: rewrite.conf
───────┼────────────────────
1 │ server {
2 │ server_name rewrite.liuhonghe.me;
3 │ rewrite_log on;
4 │ error_log logs/rewrite_error.log notice;
5 │
6 │ root html/;
7 │ location /first {
8 │ rewrite /first(.*) /second$1 last; # 这条会到 /second 中处理
9 │ return 200 'first!\n';
10 │ }
11 │
12 │ location /second {
13 â rewrite /second(.*) /third$1 break;
14 │ #rewrite /second(.*) /third$1;
15 │ return 200 'second!\n';
16 │ }
17 │
18 │ location /third {
19 │ return 200 'third!\n';
20 │ }
21 │
22 │
23 │ location /redirect1 {
24 │ rewrite /redirect1(.*) $1 permanent;
25 │ }
26 │
27 │ location /redirect2 {
28 │ rewrite /redirect2(.*) $1 redirect;
29 │ }
30 │
31 │ location /redirect3 {
32 │ rewrite /redirect3(.*) http://rewrite.taohui.tech$1;
33 │ }
34 │
35 │ location /redirect4 {
36 │ rewrite /redirect4(.*) http://rewrite.taohui.tech$1 permanent;
37 │ }
38 │
39 │ }
───────┴────────────────────
rewrite if 指令
条件表达式
-
检查变量为
空或者值是否为0, 直接使用 -
将变量与字符串做匹配, 使用
=或者!= -
将变量与正则表达式做匹é
-
大小写敏感,
~或者!~ -
大小写不敏感,
~*或者!~*
-
大小写敏感,
-
检查文件是否存在, 使用
-f或!-f -
检查目录是否存在, 使用
-d或!-d -
检查文件/目录/软连接是否存在, 使用
-e或!-e -
检查是否为可执行文件, 使用
-x或!-x
error_page
- error_page 404 /404.html;
- error_page 500 502 503 505 /50x.html
- error_page 404 =200 /empty.gif;
- error_page 404 = /404.php;
- location / { error_page 404 = @fallback; } location @fallback {proxy_pass http://backend;}
- error_page 403 http://example.com/forbidden.html;
- error_page 404 =301 http://example.com/notfound.htm;
───────┬────────────────────
│ File: return.conf
───────┼────────────────────
1 │ server {
2 │ server_name return.liuhonghe.me;
3 │ listen 8080;
4 │
5 │ root html/;
6 │ error_page 404 /403.html;
7 │ return 405; # 最先执行
8 │ location /{
9 │ return 404 "find nothing!\n"; # 后 return 执行, 不会执行上面的404
10 │ }
11 │ }
───────┴────────────────────
location 匹配规则
仅匹配 URI, 忽略参数
- 常规
-
=精准匹配 -
^~匹配上后, 则不再进行正则表达式的匹配 -
merge_slashed on;合并连续的斜杠/符号 -
@用于内部跳转的命名location -
~大小写敏感的正则匹配 -
~*忽略大小写的正则匹配
匹配规则
=
> ^~
> 顺序依次匹配正则表达式 location(如果没有, 就匹配最长的)
> 最长匹配的 location
下面有 6个规则
/Test1 /Test1/ /Test1/Test2 /Test1/Test2/ /test1/Test2
───────┬────────────────────
│ File: locations.conf
───────┼────────────────────
1 │ server {
2 │ server_name location.liuhonghe.me;
3 │ error_log logs/error.log debug;
4 │ #root html/;
5 │ default_type text/plain;
6 │ merge_slashes off;
7 │
8 │ location ~ /Test1/$ { # 第一条
9 │ return 200 'first regular expressions match!\n';
10 │ }
11 │
12 │ location ~* /Test1/(\w+)$ { # 第二条
13 │ return 200 'longest regular expressions match!\n';
14 │ }
15 │
16 │ location ^~ /Test1/ { # 第三条
17 │ return 200 'stop regular expressions match!\n';
18 │ }
19 │
20 │ location /Test1/Test2 { # 第四条
21 │ return 200 'longest prefix string match!\n';
22 │ }
23 │
24 │ location /Test1 { # 第五条
25 │ return 200 'prefix string match!\n';
26 │ }
27 │
28 │
29 │ location = /Test1 { # 第六条
30 │ return 200 'exact match!\n';
31 │ }
32 │
33 │ }
───────┴─────────────────────────
限制每个客户端并发连接数 && 限制每个客户端每秒请求数
───────┬────────────────────
│ File: limit_conn.conf
───────┼────────────────────
1 │ limit_conn_zone $binary_remote_addr zone=addr:10m; # 定义一个10m的共享内存, 用二进制IP 地址
2 │ limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m; # 定义10m 共享内存和速率
3 │
4 │ server {
5 │ server_name limit.liuhonghe.me;
6 │ root html/;
7 │ error_log logs/myerror.log info;
8 │
9 │ location /{
10 │ limit_conn_status 500; # 定义返回的 code
11 │ limit_conn_log_level warn;
12 │ limit_rate 50; # 限制向用户返回的速度, 每秒钟 50个字节
13 │ limit_conn addr 1; # 限制并发连接数
14 │ #limit_req zone=one burst=3 nodelay;
15 │ limit_req zone=one;
16 │ }
17 │ }
───────┴─────────────────────
access 对 ip 地址做限制
location / {
deny 192.168.1.100; # 顺序匹配执行
allow 192.168.1.0/24;
deny all;
}
用户名密码访问 auth_basic
生成账号密码文件
install httpd-tools
htpasswd -c file -b user pass
───────┬────────────────────
│ File: access.conf
───────┼────────────────────
1 │ server {
2 │ server_name access.liuhonghe.me;
3 │ error_log logs/error.log debug;
4 │ #root html/;
5 │ default_type text/plain;
6 │ location /auth_basic {
7 │ satisfy any;
8 │ auth_basic "test auth_basic"; # 提示串
9 │ auth_basic_user_file examples/auth.pass; # 用户名密码文件
10 │ deny all;
11 │ }
12 │
13 │ location / {
14 │ auth_request /test_auth; # 生成一个子请求, 访问 /test_auth, 权限由è¿个自路由同一配置
15 │ }
16 │
17 │ location = /test_auth {
18 │ proxy_pass http://127.0.0.1:8090/auth_upstream; # 反向代理
19 │ proxy_pass_request_body off;
20 │ proxy_set_header Content-Length "";
21 │ proxy_set_header X-Original-URI $request_uri;
22 │ }
23 │ }
───────┴────────────────────
auth_request
--with-http_auth_request_module
例子在上
satisfy
all | any
- all 都满足条件
- any 满足一个
try_files
───────┬────────────────────
│ File: tryfiles.conf
───────┼────────────────────
1 │ server {
2 │ server_name tryfiles.liuhonghe.me;
3 │ error_log logs/myerror.log info;
4 │ root html/;
5 │ default_type text/plain;
6 │
7 │ location /first {
8 │ try_files /system/maintenance.html
9 │ $uri $uri/index.html $uri.html
10 │ @lasturl; # 依次找这几个文件, 如果没有, 范文 lasturl
11 │ }
12 │
13 │ location @lasturl {
14 │ return 200 'lasturl!\n';
15 │ }
16 │
17 │ location /second {
18 │ try_files $uri $uri/index.html $uri.html =404; # 都找不到时返回 404
19 │ }
20 │
21 │ }
───────┴────────────────────
mirror 模块
处理请求时, 生成子请求访问其他服务, 对子请求的返回值不做处理
server {
listen 800;
error_log logs/error.log debug;
location / {
mirror /mirror; # copy 一份流量到 /mirror
mirror_request_body off; # 测试, 不复制 body
}
location = /mirror {
internal; # 只能内部请求
proxy_pass http://127.0.0.1:10020$request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URL $request_uri;
}
}
───────┬────────────────────
│ File: mirror.conf
───────┼────────────────────
1 │ server {
2 │ listen 10020;
3 │ location / {
4 │ return 200 'mirror response!';
5 │ }
6 │ }
───────┴────────────────────
alias & root
- request_filename 访问文件的完整路径
- document_root 由URI 和 root/alias 规则生成的文件夹路径
- realpath_root 将 document_root 中的软连接等换成真实路径
───────┬────────────────────
│ File: static.conf
───────┼────────────────────
1 │ server {
2 │ server_name static.liuhonghe.me;
3 │ error_log logs/myerror.log info;
4 │
5 │ location /root { # /html/root
6 │ root html;
7 │ }
8 │
9 │ location /alias {
10 │ alias html;
11 │ }
12 │
13 │ location ~ /root/(\w+\.txt) {
14 │ root html/first/$1;
15 │ }
16 │
17 │ location ~ /alias/(\w+\.txt) {
18 │ alias html/first/$1;
19 │ }
20 │
21 │ location /RealPath/ {
22 │ alias html/realpath/;
23 │ return 200 '$request_filename:$document_root:$realpath_root\n';
24 │ }
25 │
26 │ }
───────┴─────────────────────
static 模块对 url 不以斜杠结尾却访问目录的做法
nginx 访问一个 url, url 末尾没有加 /, 会返回 301
- absolute_redirect on;
- server_name_in_redirect off;
- port_in_redirect on;
───────┬────────────────────
│ File: dirredirect.conf
───────┼────────────────────
1 │ server {
2 │ server_name return.liuhonghe.me dir.liuhonghe.me;
3 │ server_name_in_redirect on;
4 │ listen 8088;
5 │ port_in_redirect on;
6 │ #absolute_redirect off;
7 │
8 │ root html/;
9 │ }
───────┴─────────────────────
index 和 autoindex
───────┬────────────────────
│ File: autoindex.conf
───────┼────────────────────
1 │ server {
2 │ server_name autoindex.liuhonghe.me;
3 │ listen 8080;
4 │ location / {
5 │ alias html/;
6 │ autoindex on;
7 │ index a.html;
8 │ autoindex_exact_size off;
9 │ autoindex_format html; # 格式
10 │ autoindex_localtime on;
11 │ }
12 │ }
───────┴────────────────────
提升多个小文件性能的 concat
在一次请求, 访问多个小文件
alibaba https://github.com/alibaba/nginx-http-concat
--add-module=../nginx-http-concat/
使用, 在 URI 后加两个问好 ??
https://liuhonghe.me/??file01.js,js/file02.js,css/style.css
- concat: on | off; 开关
- concat_delimiter: string 分隔符
- concat_types: MIME types 类型
- concat_unique: on | off; 是否只对某一种类型进行合并
- concat_ignore_file_error on | off; 发现某些文件不存在, 继续返回其他文件
- concat_max_files: numberp 最多合并多少个文件
───────┬────────────────────
│ File: concat.conf
───────┼────────────────────
1 │ server {
2 │ server_name concat.liuhonghe.me;
3 │
4 │ error_log logs/myerror.log debug;
5 │ concat on;
6 │ root html;
7 │
8 │ location /concat {
9 │ concat_max_files 20;
10 │ concat_types text/plain;
11 │ concat_unique on;
12 │ concat_delimiter ':::';
13 │ concat_ignore_file_error on;
14 │ }
15 │
16 │ }
───────┴────────────────────
access 日志模块 log
默认 combined 格式
log_format combined '$remote_addr - $remote_user [$time_local]' '"$request" $status $body_bytes_sent' '"$http_referer" "$http_user_agent"';
语法
- access_log off;
- access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
过滤模块
--with-http_sub_filter_module
- sub_filter string replacement
- sub_filter_last_modified off | on;
- sub_filter_once on | off;
- sub_filter_types mime-type;
───────┬────────────────────
│ File: sub.conf
───────┼────────────────────
1 │ server {
2 │ server_name sub.liuhonghe.me;
3 │ error_log logs/myerror.log info;
4 │
5 │ location / {
6 │ sub_filter 'Nginx.oRg' '$host/nginx'; # 忽略大小写的, 替换 html 字符串内容
7 │ sub_filter 'nginX.cOm' '$host/nginx';
8 │ #sub_filter_once on; # 只替换一个
9 │ sub_filter_once off;
10 │ #sub_filter_last_modified off;
11 │ sub_filter_last_modified on; # 头部的 last_modified
12 │ }
13 │ }
───────┴────────────────────
addition
可以在响应前后添加
--with-http_addition_module
- add_before body
- add_after_body
- addition_types mime-type
───────┬────────────────────
│ File: addition.conf
───────┼────────────────────
1 │ server {
2 │ server_name addition.liuhonghe.me;
3 │ error_log logs/myerror.log info;
4 │
5 │ location / {
6 │ add_before_body /before_action;
7 │ add_after_body /after_action;
8 │ addition_types *;
9 │ }
10 │ location /before_action {
11 │ return 200 'new content before\n';
12 │ }
13 │ location /after_action {
14 │ return 200 'new content after\n';
15 │ }
16 │
17 │ location /testhost {
18 │ uninitialized_variable_warn on;
19 │ set $foo 'testhost';
20 │ return 200 '$gzip_ratio\n';
21 │ }
22 │
23 │ }
───────┴─────────────────────
以上所述就是小编给大家介绍的《nginx 核心知识100讲笔记(一)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Android 学习笔记核心篇
- nginx 核心知识100讲笔记(二)
- nginx 核心知识100讲笔记(三)
- elasticsearch学习笔记(三)——Elasticsearch的核心概念
- 《DeepLearning.ai 深度学习核心笔记》发布,黄海广博士整理
- 【愣锤笔记】嗯,真香!精简ES函数式编程核心概念
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。