Nginx

本文主要介绍以下几点,关于Nginx的部署,读者可自行参考其他资料。

  • Nginx核心配置文件解读
  • Nginx应用场景之反向代理
  • Nginx应用场景之负载均衡
  • Nginx应用场景之动静分离
  • Nginx底层进程机制解剖

1. Nginx核心配置文件解读

Nginx的核心配置文件conf/nginx.conf包含三个部分内容:全局部分、events部分、http部分。

1.1. 全局部分

从配置文件开始到events块之间的内容,此处的配置影响nginx服务器整体的运行,比如worker进程的数量、错误日志的位置等。

图1 全局部分

1.2. events部分

events块主要影响Nginx服务器与用户的网络连接,比如worker_connections 1024,标识每个worker进程支持的最大链接数为1024。

图2 events部分

1.3. http部分

http部分是配置最频繁的部分,虚拟主机的配置,监听端口的配置,请求转发、反向代理、负载均衡等。

图3 http部分
图4 http部分

2. Nginx应用场景之反向代理

2.1. 场景1

需求:

浏览器请求Nginx服务器,Nginx将请求转发给一个目标服务器,用户看到的是目标服务器的相应页面。整个过程中目标服务器对客户端不可见,服务端向外暴露的是Nginx的地址。

实现:

  • 部署Tomcat,保持默认监听8080端口;
  • 修改Nginx配置,并重新加载;
    • 修改Nginx配置,如图5
    • 重新加载Nginx配置(./nginx -s reload)
  • 测试,访问http://[Nginx IP]:9003,返回Tomcat的页面
图5 修改后的Nginx配置

2.2. 场景2

需求:

在场景1的基础上,目标服务器有两个,分别是127.0.0.1:8080,127.0.0.1:8081
当访问http://[Nginx IP]:9003/a的时候,实际访问目标服务器127.0.0.1:8080
当访问http://[Nginx IP]:9003/b的时候,实际访问目标服务器127.0.0.1:8081

实现:

  • 再部署一个Tomcat,并保持默认监听8081端口;
  • 修改Nginx配置,并重新加载
    • 修改Nginx配置,如图6
    • 重新加载Nginx配置(./nginx -s reload)
图6 修改后的Nginx配置

*若不在端口号后面加上/,Nginx会转发请求至http://127.0.0.1:8080/a
加上/,Nginx会转发请求至http://127.0.0.1:8080

location语法

location [=|~|~*|^~] /uri/ {...}

在Nginx配置文件中,location主要有这几种形式:

  1. 正则表达式 location ~/a {…}
  2. 不区分大小写的正则匹配 location ~*/a {…}\
  3. 匹配路径的前缀 location ^~/a {…}
  4. 精确匹配 location = /a {…}
  5. 普通路径前缀匹配 location /a {…}

优先级:4 > 3 > 2 > 1 >5

3. Nginx应用场景之负载均衡

Nginx负载均衡策略有以下三个:

  • 轮询
  • weight
  • ip_hash

3.1. 轮询

默认策略,每个请求按时间顺序逐一分配到不同的服务器,如果某一个服务器下线,能自动剔除。

 upstream robinServer{
server [Nginx IP]:8080;
server [Nginx IP]:8082;
}

location /abc {
proxy_pass http://robinServer/;
}

3.2. weight

weight代表权重,默认每一个负载的服务器都为1,权重越高被分配的请求越多。(可用于服务器性能不均衡的场景)

upstream robinServer{
server [Nginx IP]:8080 weight=1;
server [Nginx IP]:8082 weight=2;
}

3.3. ip_hash

每个请求按照ip的hash结果分配,每一个客户端的请求会固定分配到同一个目标服务器处理,可以解决session问题。

upstream robinServer{
ip_hash;
server [Nginx IP]:8080;
server [Nginx IP]:8082;
}

4. Nginx应用场景之动静分离

动静分离就是讲动态资源和静态资源的请求处理分配到不同的服务器上,比较经典的组合就是Nginx+Tomcat架构。(Nginx处理静态资源请求,Tomcat处理动态资源请求)

图7 简单的动静分离架构

Nginx配置

图8 Nginx配置

实际在生产建议可以专门弄个静态资源服务器,架构如下:

图9 动静分离架构

5. Nginx底层进程机制剖析

Nginx启动后,以Daemon多进程方式在后台运行,包括一个Master进程和多个Worker进程。

图10 Nginx进程

Master进程
管理Worker进程,比如:

  • 接收外界信号向各Worker进程发送信号(./nginx -s reload)
  • 监控Worker进程的运行状态,当Worker进程异常推出后Master进程会自动重新启动新的Worker进程等等

Worker进程

Worker进程具体处理网络请求,多个Worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程相互之间是独立的。一个请求只能在一个Worker进程中处理,一个Worker进程不可能处理其他进程的请求。Worker进程的个数是可以设置的,一般设置与服务器CPU核数一致。

图11 Nginx进程模型

以 ./nginx -s reload来说明nginx信号处理这部分

  1. master进程对配置文件进行语法检查;
  2. 尝试配置(比如修改了监听端口,就会尝试分配新的监听端口);
  3. 尝试成功则使用新的配置,新建Worker进程;
  4. 新建成功,给旧的Worker进程发送关闭消息;
  5. 旧的Worker进程收到信号会继续服务,知道把当前进程收到的请求处理完毕

所以reload后Worker进程pid发生了变化

图12 reload nginx配置文件

Worker进程请求处理部分说明

例如,我们监听9003端口,一个请求到来时,如果有多个Worker进程,那么每个Worker进程都有可能处理这个链接。

  • Master进程创建之后,会建立好需要监听的socket,然后Master进程再fork出多个Worker进程。所以,所有Worker进程的监听描述符linstenfd在新链接到来时都变得可读;
  • nginx使用互斥锁来保证只有一个Worker进程能处理请求,拿到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该链接,然后解析、处理、返回客户端。

Nginx多进程模型好处

  • 每个Worker进程都是独立的,不需要加锁,节省开销;
  • 每个Worker进程都是独立的,互不影响,其中一个进程异常导致其结束,其他的照样能提供服务;
  • 多进程模型为reload热部署机制提供了支撑。