Nginx进程结构

Nginx有两种进程结构:一种是 单进程结构,一种是 多进程结构。

单进程结构实际上不适用于生产环境,只适合在开发、调试时使用。这是因为在生产环境中需要保证Nginx足够健壮,且能够充分利用 CPU多核的特性。

因此默认配置中也是打开多进程的Nginx。

Nginx多进程结构下,进程种类有三类:

master进程 + worker进程 + cache进程

Master进程的功能是用来管理Worker进程,真正处理用户请求的是Worker进程,Master进程负责监控每一个Worker进程是否在正常工作、是否需要热部署等。

Cache进程负责对上游服务器发来的动态请求响应做缓存处理,缓存是需要在多个worker进程间共享的,CL进程(Cache Loader)负责做缓存的载入,CM进程(Cache Manager)负责做缓存的管理,实际上如果需要对用户请求返回缓冲中的内容,则还是由Worker进程来处理。

Worker进程的个数:

Master进程只有一个,Cache进程分别有一个Manage进程和一个Load进程。
对于Worker进程,一般配置为与CPU的核数一致,Nginx希望每一个Worker进程从头到尾占有一个核。
因此在配置Nginx时,除了需要把Worker进程的数量配置成与CPU核数一致外,还需要把Worker进程与某一个CPU核绑定,这样可以更好的使用每个核上的CPU缓存,提高缓存命中率。

另外,在配置Nginx时也会把Nginx的进程优先级调到最高,这样在操作系统进行进程调度时会为Nginx分配更多的时间片,从而减少无谓的进程间切换。

进程结构图

进程结构图

为什么Nginx使用的是多进程结构而不是多线程结构?

最核心的目的,就是要保证Nginx的高可用性和高可靠性。

如果Nginx使用多线程结构,因为线程之间是共享内存地址空间的,如果某个第三方模块因为内存地址访问越界等问题引发了段错误,将会导致整个Nginx进程都挂掉。而采用多进程结构则基本不会出现这样的问题。

Nginx在多进程结构设计上同样遵循了实现高可用性、高可靠性的思路:
在Master进程中,通常第三方模块是不会加入功能代码的。虽然Nginx允许第三方模块在Master进程中添加独有的、自定义的一些方法,但是通常没有第三方模块会这么做。

Liunx信号量管理机制

所有信号量

Linux信号量

常用信号量

  • SIGCHLD kill -17 $PID
  • SIGQUIT kill -3 $PID
  • SIGTERM kill -15 $PID
  • SIGKILL kill -9 $PID
  • SIGHUP kill -1 $PID
  • SIGUSER1 kill -10 $PID
  • SIGUSER2 kill -12$PID
  • SIGWINCH kill -17 $PID

使用信号量管理master和worker

master进程

Mster进程

worker进程

work

命令行

命令行

演示
终止
[root@wzj ~]# ps -ef | grep nginx | grep -v grep 
root      4847     1  0 11月16 ?      00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     4848  4847  0 11月16 ?      00:00:00 nginx: worker process
[root@wzj ~]# kill -s SIGTERM 4847
[root@wzj ~]# ps -ef | grep nginx | grep -v grep
重载配置
[root@wzj ~]# ps -ef | grep nginx | grep -v grep 
root     41438     1  0 16:42 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx    42585 41438  0 16:42 ?        00:00:00 nginx: worker process
[root@wzj ~]# kill -s SIGHUP 41438
// 关掉旧的worker进程,重载配置开启新的worker进程,可以看到master ID是不变的
[root@wzj ~]# ps -ef | grep nginx | grep -v grep 
root     41438     1  0 16:42 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx    42892 41438  0 16:43 ?        00:00:00 nginx: worker process

热升级的流程

不停机生效新的配置

btj

热升级的流程

1、将旧的nginx文件替换成新的nginx文件

2、向master进程发送USER2信号

3、master进程修改pid文件,加后缀.oldbin

4、master进程用新nginx文件启动新master进程

5、向旧的master进程发送WINCH信号,旧的worker子进程退出

6、回滚情形:向旧master发送HUP,向新的master发送QUIT

Nginx热部署完整步骤演示

[root@wzj ~]# ps -ef | grep nginx | grep -v grep 
root     41438     1  0 16:42 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx    42892 41438  0 16:43 ?        00:00:00 nginx: worker process
[root@wzj ~]# kill -s SIGUSR2 41438
# 可以看到启动了新的master进程
[root@wzj ~]# ps -ef | grep nginx | grep -v grep 
root      8380 41438  0 19:18 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     8383  8380  0 19:18 ?        00:00:00 nginx: worker process
root     41438     1  0 16:42 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx    42892 41438  0 16:43 ?        00:00:00 nginx: worker process
[root@wzj ~]# ls /usr/local/nginx/logs/
access.log  error.log  nginx.pid  nginx.pid.oldbin
#存的旧的master的pid号
[root@wzj ~]# cat /usr/local/nginx/logs/nginx.pid.oldbin 
41438

#可以从上面看到此时nginx是新旧并存的,这里不能直接退出master这样就不能回滚了,发送SIGWINCH信号将旧的worker子进程退出
[root@wzj ~]# kill -s SIGWINCH 41438 
#可以看到就剩下旧的master了,旧的worker都退出了(注: 要是回滚的话用kill -s SIGHUB pid 就行)
[root@wzj ~]# ps -ef | grep nginx | grep -v grep
root      8380 41438  0 19:18 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     8383  8380  0 19:18 ?        00:00:00 nginx: worker process
root     41438     1  0 16:42 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx

#如果测试没问题不需要回滚了那就可以退出旧的master进程了
[root@wzj ~]# kill -s SIGQUIT 41438
[root@wzj ~]# ps -ef | grep nginx | grep -v grep
root      8380     1  0 19:18 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     8383  8380  0 19:18 ?        00:00:00 nginx: worker process
//存放旧的pid文件也删除了
[root@wzj ~]# ls /usr/local/nginx/logs/ 
access.log  error.log  nginx.pid


Nginx模块化管理机制

模块结构图

模块结构图

模块体系结构

Nginx编译安装

Nginx编译安装的配置参数

参数 含义
–prefix 指定安装的目录
–user 运行nginx的worker子进程
–group 运行nginx的worker子进程
–pid-path 存放进程运行pid’文件的路径
–config-path 配置文件nginx.conf的存放路径
–error-log-path 错误日志error.log的存放路径
–http-log-path 访问日志access.log的存放路径
–wit-pcre pcre库的存放路径,正则表达式会用到
–with-zlib zlib库的存放路径,gizp模块会用到

内置参数默认原则

显示加上,默认不内置:–with

显示去掉,默认内置:–without

演示


Nginx配置文件

配置文件结构

虚拟主机分类

基于多IP的虚拟主机

基于多端口的虚拟主机

基于域名的虚拟主机

Nginx基础应用-核心指令

配置文件main段核心参数用法

核心参数

user  USERNAME [GROUP]
			解释:指定运行nginx和worker子进程的属主和属组,其中属组可以不指定
			实例:
					user nginx nginx;

pid DIR
			解释:指定运行nginx的master主进程的pid文件存放路径
			示例:
					pid /opt/nginx/logs/nginx.pid;
					
worker_rlimit_nofile number
			解释:指定worker子进程可以打开的最大文件句柄数
			示例:
					worker_rlimit_nofile 20480;
					
worker_rlimit_core size
			解释:指定worker子进程异常终止后的core文件,用于记录分析问题
			示例:
					Worker_rlimit_core 50M;
					working_directory /opt/nginx/tmp;
					
worker_processes number | auto
			解释:指定nginx启动的worker子进程数量
			示例:
					worker_processes 4;
					worker processes auto;
					
worker_cpu_affinity cpumask1 cpumask2...
			解释:将每个worker子进程与我们的CPU物理核心绑定
			示例:
					worker_cpu_affinity 0001 0010 0100 1000;
					4个物理核心,4个worker子进程
					worker cpu affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;  #8物理核心,8个worker子进程
					worker_cpu_affinity 01 10 01 10; #2个物理核心,4个子进程
			备注:将每个worker子进程与特定CPU物理核心绑定,优势在于:避免同一个worker子进程在不同的CPU核心上切换,缓存失效降低性能;其并不能真正的避免进程切换
			
worker_priority number
			解释:指定worker子进程的nice值,以调整运行nginx的优先级,通常设定为负值,以优点调用nginx
			示例:
					worker_priority -10;
			备注:Liunx默认进程的优先级是120,值越小越优先;nice设定范围为-20到+19
      
worker_shutdown_timeout time
			解释:指定worker子进程优雅退出时的超时时间
			示例:
				worker_shutdown_tieout 5s;
					
timer_reslution time
			解释:worker子进程内部使用的计时器精度,调整时间间隔越大,系统调用越少,有利于性能提升;反之,系统调用越多,性能下降
			示例:
					worker_resolution 100ms;
	
daemon on|off
			解释:设定nginx的运行方式,前台还是后台,前台用户调试,后台用于生产
			示例:
					daemon off;
					
					
					
				

worker子进程与CPU绑定

客户端请求处理流程

配置文件events段核心参数用法

核心参数列表

参数 含义
use nginx使用何种事件驱动模型
worker_connectinos worker子进程能够处理最大迸发连接数
accept_mutex 是否打开负载均衡互斥锁
Accept_mutes_delay 新连接分配给worker子进程的超时时间
muti_accept worker子进程可以接收的新连接个数

use

**语法:**use method

method可选值:select、poll、kqueue、epoll、/dev/poll、eventport

**默认配置:**无

**推荐配置:**不指定,让nginx自己选择

worker_connections

**语法:**worker_connections number

**默认配置:**worker_connections 1024

**推荐配置:**worker_connections 65535/worker_processes | 65535

accept_mutex

**语法:**accept_mutex on | off

**可选值:**on、off

**默认配置:**accept_mutex off

**推荐配置:**accept_mutext on

accept_mutex

Accept_mutex_delay

前提是accpt_mutex 设置为on,设置这个才有意义

**语法:**accept_mutex_delay time

**默认配置:**accept_mutex_delay 500ms

**推荐配置:**accept_mutext_deplay 200ms

multi_accrpt

**语法:**multi_accepton | off

**可选值:**on、off

**默认配置:**multi_accept off

**推荐配置:**multi_accept on

server_name指令用法

语法结构

语法:server_name name1 name2 name3 …;

示例1:server_name www.zhgolang.com;

示例2:server_name *.zhanghaobk.com;

示例3:server_name www.zhanghaobk.com *.zhgolang.com;

四种写法

server_name www.zhgolang.com

server_name *.zhgolang.com

server_name www.zhgolang.*

server_name ~^www.zhgolang.*$

域名匹配优先级

多域名如何匹配

匹配优先级

root和alias用法的区别

语法结构

**相同点:**URI到磁盘文件的映射

**区别:**root会将定义路径与URI叠加;alias则只取定义路径

区别示例

root

location /picture {
  	root /opt/nginx/html/picture;
}
客户请求www.test.com/picture/1.jpg 则对应磁盘映射路径/opt/nginx/html/picture/picture/1.jgp

alias

location /picture {
  	alias /opt/nginx/html/picture;
}
客户请求www.test.com/picture/1.jpg 则对应磁盘映射路径/opt/nginx/html/picture/1.jgp

**注意事项 **

  • 使用alias时,末尾一定加/
  • alias只能位于location中

location基础用法

location语法结构

匹配规则 含义 示例
= 精确匹配 location = /images/
~ 正则匹配,区分大小写 Location ~ .(jpg|gif)$
~* 正则匹配,不区分大小写 Location ~*
^~ 匹配到即停止搜索 location ^~ /images/
不带任何符号 Location /

优先级

深入理解location中URL结尾的反斜线

URL写法区别

不带/

若果没有目录则把test当成文件
location /test {
      .....
}

带/

没有也不会当成目录
location /test/ {
      .....
}

stub_status模块的用法

**语法结构 **

指令:stub_stats;

低于1.7.5版本:stub_status on;

上下文:server location

配置示例:

location /uri {
    stub_status;
}

效果示例

Active connections: 2 
server accepts handled requests
 167 167 163 
Reading: 0 Writing: 1 Waiting: 1 

状态项

状态项 含义
Active Connections 活跃的连接数量
accepts 接收的客户端连接总数量
handled 处理的客户端连接总数量
requests 客户端的请求数量
Reading 读取客户端的连接数
Writing 响应数据到客户端的连接数
Waiting 空闲客户端请求连接数量

内嵌变量

变量名 含义
$connections_active 同Active connections值
$connections_reading 同Reading值
$connections_writing 同Writing值
$connections_waiting 同Waiting值

HTTP核心模块

connection 和 request

**基本含义 **

connection是连接,即常说的tcp连接,三次握手,状态机

request是请求,例如http请求,无状态的协议

request是必须简历在connection之上

请求示意图

请求示意图

limig_conn模块

**基本功能 **

  • 用于限制客户端迸发连接数
  • 默认编译进nginx,通过–without-http_limig_conn_module禁用
  • 使用共享内存,对所有worker子进程生效

**常用指令 **

  • limit_conn_zone
  • limit_conn_status
  • limit_conn_log_level
  • limit_conn

具体用法

limit_conn_zone

语法:limit_conn_zone key zone=name:size

默认值:无

上下文:http

示例:limit_conn_zone $binary_remote_addr zone=addr:10m

limit_conn_status

语法:limit_conn_status code;

默认值:limit_conn_status 503;

上下文:http、server、location

limit_conn_log_level

语法:limit_conn_log_level info | notice | warn | error;

默认值limit_conn_log_level error;

上下文:http、server、location

limit_conn

语法:limit_conn zone number;

默认值:无

上下文:http、server、location

limit_req模块

基本功能

  • 用于限制客户端处理请求的平均速率
  • 默认编译进nginx,通过–without-http_limit_req_module禁用
  • 使用共享内存,对所有worker子进程生效
  • 限流算法:leaky_bucket

leaky_bucket算法

limit_req_zone

语法:limit_req_zone key zone=name:size rate=rate

默认值:无

上下文:http

示例:limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m

limit_req_status

语法:limit_req_status code;

默认值:limit_req_status 503;

上下文:http、server、location

limit_req_log_level

语法:limit_req_log_level info | notice | warn | error;

默认值:limit_req_log_level error;

limit_req

语法:limit_req zone=name [burst=number] [nodelay | delay=number];

默认值:无

上下文:http、server、location

示例1: limit_req zone=one;

限制特定IP或网段访问的access模块

**指令集 **

  • allow
  • deny

allow

语法结构:allow address | CIDR | UNIX | all

默认值:无

上下文:http、server、location、limit_except

示例:allow 192.168.1.1;

deny

语法结构:deny address | CIDR |UNIX | all;

默认值:无

上下文:http、server、location、limit_except

示例:deny 192.168.1.0/24;

组合示例

location / {
  deny 192.168.1.1;
  allow 192.168.1.0/24;
  allow 10.0.0.0/16;
  allow 10.1.1.0/16;
  allow 2001:0db8::/32;
  deny all;
}

限制特定用户访问的auth_basic模块

基本功能

  • 基于HTTP Basic Authentication 协议进行用户名密码认证
  • 默认已编译进Nginx 通过–without-http_auth_basic_module禁用

**指令 **

语法:auth_basic string | off;

默认值:auth_basic off;

上下文: http、server、location、limit_except

语法:auth_basic_user_file file;

默认值:-

上下文:http、server、location、limit_except

**生成密码文件工具 **

可执行程序:htpasswd

所属软件包:httpd-tools

生成新的密码文件:htpasswd-bc encrypt_pass jack 123456

添加新用户密码:htpasswd -b encrypt_pass mike 123456

auth_request模块

功能极原理

**启用禁用 **

  • 默认并未编译进Nginx,通过–with-http_auth_request_module启用

**指令 **

语法:auth_request uri | off;

默认值:auth_request off;

上下文:http、server、location

语法:auth_request_set $variable value;

默认值: -

上下文:http、server、location

示例:

location /private/ {
  	auth_request /auth;
}
locatino /auth{
  	proxy_pass http://127.0.0.1:8080/verify;
  	proxy_pass_request_body off;
  	proxy_set_header Content-Length "";
  proxy_set_header X-Original-url $request_uri;
}

rewrite模块

return

  • 停止处理请求,直接返回响应码或重定向到请他URL
  • 执行return指令后,location中后续指令将不会被执行
location / {
   .... ... 
    return 404;
  ..... .. 
}


location /cm/ {
    proxy_pass http://1.1.1.1:27180/;
}

**语法结构 **

语法:

  • return code [text];
  • return code URL;
  • return URL;

默认值: 无

上下文:server、location、if

HTTP状态码

重定向状态码

rewrite

  • 根据知道你个正则表达式匹配规则,重写URL

语法:rewrite regex replacement [flag];

默认值:-

上下文:server、location、if

示例:rewrite /images/(.*.jpg)$/pic/$1;

flag

flag可选值及含义

last 重写后的URL发起新请求,再此进入server段,重试location中的匹配
break 直接使用重写后的URL,不在匹配其他location中语句
redirect 返回302临时重定向
permanent 返回301永久重定向

–with-stream_ssl_module

return和rewrite指令执行顺序

更新中。。。

rewrite模块中的if指令

**语法结构 **

语法: if (condition) {....};
默认值:-
示例: if ($http_user_agent ~ Chrome) {
  rewrite /(.*)/browser/$1 break;
}

condition

$variable 仅变量时,值为空或以0开头字符串都会被当做false处理
= 或 != 相等或不等比较
~ 或!~ 正则匹配或非正则匹配
~* 正则匹配,不区分大小写
-f 或! -f 检查文件存在或不存在
-d 或 ! -d 检测目录存在或不存在
-e 或! -e 检查文件、目录、符号链接等存在或不存在
-x或! -x 检查文件可执行或不可执行
[root@master1 myconf]# cat if.conf  
server {
        listen 8080;
        server_name localhost;
        root html;

        location /search/ {
                if ( $remote_addr = "192.168.14.11" ) {
                return 200 "master request";
        } 
                return 200 "orther request";

        }

}

访问测试

[root@master1 myconf]#  curl 192.168.14.11:8080/search/
master request[root@master1 myconf]# 

[root@node1 ~]# curl 192.168.14.11:8080/search/
orther request[root@node1 ~]# 

autoindex模块

**基本功能 **

  • 用户请求以/结尾时,列出目录结构

**指令集 **

  • autoindex
  • autoindex_exact_size
  • autoindex_format
  • autoindex_localtime
autoindex用法 
语法:autoindex on | off;
默认值:autoindex off;
上下文:http、server、location


autoindex_exact_size用法 
语法:autoindex_exact_size on | off;
默认值:autoindex_exact_size on;
上下文:http、server、location

autoindex_format用法 
语法:autoindex_format html | xml | json | jsonp;
默认值:autoindex_format html;
上下文:http、server、location

autoindex_localtime用法 
语法:autoindex_localtime on | off;
默认值:autoindex_localtime off;
上下文:http、server、location

**alias **

注意路径后面要加/

server {

        listen 8081;
        server_name localhost;

        location /download/ {
                alias /opt/source/;
                index a.html;
                autoindex on;
                autoindex_exact_size on;
                autoindex_format html;
                autoindex_localtime off;
        }

}

root

这个是直接展示/opt/download下面的内容

server {

        listen 8081;
        server_name localhost;

        location /download/ {
                root /opt/source;
                index a.html;
                autoindex on;
                autoindex_exact_size on;
                autoindex_format html;
                autoindex_localtime off;
        }

}

Nginx变量分类

![变量](/Users/zhanghao/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/758d22716c383a2acb5934e3cf9b4e5f/Message/MessageTemp/9e20f478899dc29eb19741386f9343c8/File/HALO博客/Nginx/images/变量.png)

**变量分类 **

  • TCP连接变量
  • HTTP请求变量
  • Nginx处理HTTP请求产生的变量
  • Nginx内部变量

TCP连接相关比变量

变量名 含义
remote_addr 客户端IP地址
remote_port 客户端端口
server_addr 服务端IP地址
server_port 服务端端口
server_protocol 服务端协议
binary_remote_addr 二进制格式的客户端IP地址
connection TCP连接的序号,递增
connection_request TCP连接当前的请求数量
proxy_protocol_addr 若只用了proxy_protocol协议则返回协议中地址否则返回空
proxy_protocol_port 若使用了proxy_protocol协议则返回协议中端口否则返回空

**测试 **

[root@master1 myconf]# cat var_tcp.conf  
server {
        listen 8082;
        server_name localhost;

        location /tcp {
                return 200 "
        remote_addr:            $remote_addr;
        remote_port             $remote_port;
        server_addr:            $server_addr;
        server_port:            $server_port;
        server_protocol:        $server_protocol;
        connection:             $connection
        proxy_protocol_addr     $proxy_protocol_addr;
        proxy_protocol_port:    $proxy_protocol_port
        ";
        }

}
[root@master1 myconf]# curl localhost:8082/tcp

        remote_addr:            127.0.0.1;
        remote_port             57686;
        server_addr:            127.0.0.1;
        server_port:            8082;
        server_protocol:        HTTP/1.1;
        connection:             60
        proxy_protocol_addr     ;
        proxy_protocol_port:
        [root@master1 myconf]# 

**请求过程相关变量 **

变量名 含义
uri 请求的URL,不包含参数
request_uri 请求的URL, 包含参数
scheme 协议名,http或https
request_method 请求方法
request_length 全部请求的长度,包含请求行、请求头、请求体

特殊变量

变量名 含义
host 先看请求行,再看请求头,最后找server_name
http_user_agent 用户浏览器
http_referer 从哪些链接过来的请求
http_via 经过一层代理服务器,添加对应代理服务器的信息
http_x_forwarded_for 获取用户真实IP
http_cookie 用户cookie
args 全部参数字符串
arg_参数名 特定参数值
is_args URL中有参数,则返回?;否则返回空
query_string 与args相同
Remote_user 由HTTP Basic Authentication协议传入的用户名

更新中… …