内容简介: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函数式编程核心概念
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Seasoned Schemer
Daniel P. Friedman、Matthias Felleisen / The MIT Press / 1995-12-21 / USD 38.00
drawings by Duane Bibbyforeword and afterword by Guy L. Steele Jr.The notion that "thinking about computing is one of the most exciting things the human mind can do" sets both The Little Schemer (form......一起来看看 《The Seasoned Schemer》 这本书的介绍吧!