读书笔记-深入理解Nginx-模块开发与架构解析(第二版)
参考文献
- 深入理解Nginx-模块开发与架构解析(第二版) 陶辉
第一部分 Nginx
能帮我做什么
第一章 研究Nginx
前的准备工作
Nginx
的优点
- 高并发,高性能
- 高扩展性
- 高可靠性
- 热部署
- 最自由的BSD许可证
使用Nginx
的必备软件
-
GCC
编译器1
yum install -y gcc-c++
-
PCRE
库1
yum install -y pcre pcre-devel
-
zlib
库1
yum install -y zlib zlib-devel
-
OpenSSL
开发库1
yum install -y openssl openssl-devel
磁盘目录
Nginx
源代码存放目录Nginx
编译阶段产生的中间文件存放目录- 该目录用于放置在
configure
命令执行后所生成的源文件及目录,以及make
命令执行后生成的目标文件和最终连接成功的二进制文件. - 默认情况下,
configure
命令会将目录命名为objs
,并放在Nginx
源代码目录下
- 该目录用于放置在
- 部署目录
- 该目录存放实际
Nginx
服务运行期间所需要的二进制文件,配置文件等. - 默认情况下,该目录为
/usr/local/nginx
- 该目录存放实际
- 日志文件存放目录
Nginx
的命令行控制
- 默认情况下,
Nginx
被安装在目录/usr/local/nginx/
中,其二进制文件路径为/usr/local/nginx/sbin/nginx
,其配置文件路径为/usr/local/nginx/conf/nginx.conf
启动方式
-
默认启动方式
1
/usr/local/nginx/sbin/nginx
- 会读取默认路径下的配置文件:
/usr/local/nginx/conf/nginx.conf
- 会读取默认路径下的配置文件:
-
另行指定配置文件的启动方式
-c
参数指定配置文件
1
/usr/local/nginx/sbin/nginx -c /tmp/nginx.conf
-
另行指定安装目录的启动方式
-p
参数指定Nginx
的安装目录
1
/usr/local/nginx/sbin/nginx -p /usr/local/nginx
-
另行指定全局配置项的启动方式
- 可以通过
-g
参数临时指定一些全局配置项,以使新的配置项.
1
/usr/local/nginx/sbin/nginx -g "pid /var/nginx/test.pid;"
-
-g
参数的约束条件是指定的配置项不能与默认路径下的nginx.conf
中的配置项冲突,否则无法启动. -
另外一个约束条件是,以
-g
方式启动的Nginx
服务执行其他命令行时,需要把-g
参数也带上,否则可能会出现配置项不匹配的情况.例如,要停止Nginx
服务,那么需要执行下面代码:1
/usr/local/nginx/sbin/nginx -g "pid /var/nginx/test.pid;" -s stop
- 可以通过
测试配置信息是否由有误
-
在不启动
Nginx
的情况下,使用-t
参数仅测试配置文件是否有误.1
/usr/local/nginx/sbin/nginx -t
-
在测试配置阶段不输出信息
-
测试配置选项时,使用
-q
参数可以不把error
级别以下的信息输出到屏幕.1
/usr/local/nginx/sbin/nginx -t -q
-
显示版本信息
1 | /usr/local/nginx/sbin/nginx -v |
显示编译阶段的参数
1 | /usr/local/nginx/sbin/nginx -V |
快速停止服务
1 | /usr/local/nginx/sbin/nginx -s stop |
优雅地停止服务
1 | /usr/local/nginx/sbin/nginx -s quit |
日志文件回滚
1 | /usr/local/nginx/sbin/nginx -s reopen |
平滑升级Nginx
-
当
Nginx
服务升级到新的版本时,必须要将旧的二进制文件Nginx
替换掉,通常情况下这是需要重启服务的,但是Nginx
支持不重启服务来完成新版本的平滑升级. -
升级时包括以下步骤:
-
通知正在运行的旧版本
Nginx
准备升级.通过向master
进行发送USR2
信号可达到目的.如1
kill -s SIGUSR2 <nginx master pid>
- 这时,运行的
Nginx
会将pid
文件重命名,如将/usr/local/nginx/logs/nginx.pid
重命名为/usr/local/nginx/logs/nginx.pid.oldbin
,这样新的Nginx
才有可能启动成功.
- 这时,运行的
-
启动新版本的
Nginx
,可以使用以上任意一种启动方式.这时通过ps
命令可以发现新旧版本的Nginx
在同时运行. -
通过
kill
命令向旧版本的master
进程发送SIGQUIT
信号,以优雅的方式关闭旧版本的Nginx
.随后将只有新版本的Nginx
服务运行,此时平滑升级完毕.
-
第二章 Nginx
的配置
Nginx
服务的基本配置
- 按用户使用时的预期功能分成以下4类
- 用于调试,定位问题的配置项
- 正常运行的必备配置项
- 优化性能的配置项
- 事件类配置项
用于调试进行和定位问题的配置项
-
是否以守护进程方式运行
Nginx
1
2语法: daemon on | off;
默认: daemon on; -
是否以
master/worker
方式工作1
2语法: master_process on | off;
默认: master_process on; -
error
日志的设置1
2语法: error_log /path/file level;
默认: error_log logs/error/log error;level
是日志的输出级别,取值范围是debug.info,notice,warn,error,crit,alert,emerg
,从左至右级别依次增大.- 当设定为一个级别时,大于或等于该级别的日志都会被输出到
/path/file
文件中,小于该级别的日志则不会输出. - 如果日志级别设定到
debug
,必须要在configure
时加入--with-debug
配置项
-
仅对指定的客户端输出
debug
级别的日志1
语法: debug_connection [IP|CIDR]
-
这个配置项实际上属于事件类配置,因此,它必须放在
events {...}
中才有效.它的值可以是IP
地址或CIDR
地址,如:1
2
3
4events {
debug_connection 10.224.66.14;
debug_connection 10.224.57.0/24;
} -
使用
debug_connection
前,需要确保在执行configure
时已加如了--with-debug
参数,否则不会生效.
-
正常运行的配置项
-
定义环境变量
1
语法: env VAR | VAR=VALUE;
-
这个配置项可以让用户直接设置操作系统上的环境变量.如:
1
env TESTPATH=/tmp/;
-
-
嵌入其他配置文件
1
语法: include /path/file;
-
include
配置项可以将其他配置文件嵌入到当前的nginx.conf
中,它的参数既可以是绝对路径,也可以是相对路径(相对于Nginx
的配置目录,即nginx.conf
所在的目录),例如:1
2include mime.types;
include vhost/*.conf;
-
-
pid
文件的路径1
2语法: pid /path/file;
默认: pid logs/nginx.pid;- 保存
master
进程ID
的pid
文件存放路径.默认与configure
执行的参数--pid-path
所指定的路径相同的,也可以随时修改,但应确保Nginx
有权在相应的目标中创建pid
文件,该文件直接影响Nginx
是否可以运行.
- 保存
-
Nginx worker
进程运行的用户以及用户组1
2语法: user username[groupname];
默认: user nobody nobody; -
指定
Nginx worker
进程可以打开的最大句柄描述符个数1
语法: worker_rlimit_nofile limit;
优化性能的配置项
-
Nginx worker
进程个数1
2语法: worker_processes number;
默认: worker_processes 1;- 在
master/worker
运行方式下,定义worker
进行的个数. - 一般情况下,用户要配置与CPU内核相等的
worker
进程,并且使用下面的worker_cpu_affinity
配置来绑定CPU
内核.
- 在
-
绑定
Nginx worker
进程到指定的CPU
内核1
语法: worker_cpu_affinity cpumask[cpumask...]
1
2worker_processes 4;
worker_cpu_affinity 1000 0100 0010 0001;worker_cpu_affinity
配置仅对Linux
操作系统有效.Linux
操作系统使用sched_setaffinity()
系统调用实现这个功能.
-
SSL
硬件加速1
语法: ssl_engine device;
-
如果服务器上有
SSL
硬件加速设备,那么就可以进行配置以加快SSL
协议的处理速度.可以使用OpenSSL
提供的命令来查看是否有SSL
硬件加速设备:1
openssl engine -t
-
虚拟主机与请求的分发
监听端口
1 | Syntax: listen address[:port] [default_server] [ssl] [http2 | quic] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; |
主机名称
1 | Syntax: server_name name ...; |
server_name
可以跟多个主机名称,如server_name www.testweb.com download.testweb.com;
- 在开始处理一个
HTTP
请求时,Nginx
会取出header
头中的Host
,与每个server
中的server_name
进行匹配,以此决定到底由哪一个server
块来处理这个请求.有可能一个Host
与多个server
块中的server_name
都匹配,这时会根据匹配优先级来选择实际处理的server
块. server_name
与Host
的匹配优先级如下:- 首先选择所有字符串完全匹配的
server_name
,如www.testweb.com
- 其次选择通配符在前面的
server_name
,如*.testweb.com
- 再次选择通配符在后面的
server_name
,如www.testweb.*
- 首先选择所有字符串完全匹配的
- 如果
Host
与所有的server_name
都不匹配,这时会按照下列顺序选择处理的server
块- 优先选择在
listen
配置项后加入[default|default_server]
的server
块 - 找到匹配
listen
端口的第一个server
块
- 优先选择在
- 如果
server_name
后跟着空字符串(如server_name "";
),那么表示匹配没有Host
这个HTTP
头部的请求. Nginx
正是使用server_name
配置项针对特定的Host
域名的请求提供不同的服务,以此实现虚拟主机功能.
serve_names_hash_bucket_size
1 | Syntax: server_names_hash_bucket_size size; |
- 为了提高快速寻找到相应
server_name
的能力,Nginx
使用散列表来存储server_name
.server_names_hash_bucket_size
设置了每个散列桶占用的内存大小.
server_names_hash_max_size
1 | Syntax: server_names_hash_max_size size; |
location
1 | Syntax: location [ = | ~ | ~* | ^~ ] uri { ... } |
-
location
会尝试根据用户请求中的URI
来匹配上面的/uri
表达式,如果可以匹配,就选择location {}
块中的匹配来处理用户请求. -
location
的匹配规则:-
=
表示把URI
作为字符串,以便与参数中的uri
做完全匹配.例如:1
2
3location = / {
# 只有当用户请求是/时,才会使用该location下的配置
} -
^~
:表示uri
以某个常规字符串开头,理解为匹配url
路径即可.Nginx
不对url
做编码.因此请求为/static/20%/aa
可以被规则^~/static/ /aa
匹配到; -
~
表示区分大小写(字母大小写敏感)的正则匹配; -
~*
表示不区分大小写的正则匹配; -
!~
表示区分大小写不匹配的正则; -
!~*
表示不区分大小写不匹配的正则; -
/
通用匹配,任何请求都会匹配到,默认匹配;
-
-
匹配优先级
- 第一优先级: 等号类型(
=
)的优先级最高.一旦匹配成功,则不再查找其他匹配项. - 第二优先级:
^~
类型表达式.一旦匹配成功,则不再查找其他匹配项. - 第三优先级: 正则表达式类型(
~
~*
)的优先级次之.如果有多个location的正则能匹配的话,则使用正则表达式最长的那个. - 第四优先级: 常规字符串匹配类型.按前缀匹配.
1
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)
- 第一优先级: 等号类型(
文件路径的定义
-
以
root
方式设置资源路径1
2
3语法: root path
默认值: root html
配置段: http、server、location、if -
以
alias
方式设置资源路径1
2语法: alias path
配置段: location-
使用
alias
时,目录名后面一定要加上/
-
alias
可以指定任何名称 -
alias
在使用正则匹配时,必须捕捉匹配的内容并指定的内容处使用 -
alias
只能位于location
块中 -
例如,如果有一个请求的
URI
是/conf/nginx.conf
,而用户实际想访问的文件在/usr/local/nginx/conf/nginx.conf
,那么想要使用alias
来进行设置的话,可以采用如下方式:1
2
3location /conf {
alias /usr/local/nginx/conf/;
} -
如果用
root
设置,那么语句如下所示:1
2
3location /conf {
root /usr/local/nginx/;
} -
使用
alias
时,在URI
向实际文件路径的映射过程中,已经把location
后配置的/conf
这部分字符串丢弃掉,因此,/conf/nginx.conf
请求将根据alias path
映射为path/nginx.conf
-
root
则不然,它会根据完整的URI
请求来映射,因此,/conf/nginx.conf
请求会根据root path
映射为path/conf/nginx.conf
.
-
-
访问首页
1
2
3Syntax: index file ...;
Default: index index.html;
Context: http, server, location -
根据
HTTP
返回码重定向页面1
2
3Syntax: error_page code ... [=[response]] uri;
Default: —
Context: http, server, location, if in location1
2error_page 404 /404.html;
error_page 500 502 503 504 /50x.html