Nginx基本架构

Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少(一个worker进程只占用10-12M内存),启动极快,高并发能力强,在互联网项目中广泛应用。

Nginx使用基于事件驱动架构,使得其可以支持数以百万级别的TCP连接。

Nginx基本架构

Nginx在启动后以daemon的方式在后台运行,会有一个master进程和多个worker进程

  1. Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
  2. master 接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接。
  3. master 进程能监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的 worker 进程。

master进程

读取并验证配置文件nginx.conf用来管理worker进程,包含:

  1. 接收来自外界的信号
  2. 向各worker进程发送信号
  3. 监控worker进程的运行状态
  4. 当worker进程异常退出后,会自动重新启动新的worker进程。

worker进程

处理基本的网络事件了。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求只能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,或者直接设置参数worker_processes auto;

Nginx 的各种功能和操作都由模块来实现。Nginx 的模块从结构上分为:

  • 核心模块:HTTP 模块、EVENT 模块和 MAIL 模块。
  • 基础模块:HTTP Access 模块、HTTP FastCGI 模块、HTTP Proxy 模块和 HTTP Rewrite 模块。
  • 第三方模块:HTTP Upstream Request Hash 模块、Notice 模块和 HTTP Access Key 模块及用户自己开发的模块。

Nginx 特点如下:

  • 反向代理,负载均衡器
  • 高可靠性、单 Master 多 Worker 模式
  • 高可扩展性、高度模块化
  • 非阻塞
  • 事件驱动
  • 低内存消耗
  • 热部署

重启Nginx命令过程

  1. 我们可以输入nginx -s reload来重启Nginx,nginx -s stop来停止Nginx的运行,执行这些命令时其实会启动一个新的Nginx进程,而新的Nginx进程在解析到reload参数后,其实就可以知道用户执行这个命令是控制Nginx重新加载配置文件,于是向master进程发送信号
  2. master进程接到信号会先重新加载配置文件,然后启动新的worker进程并向所有旧worker进程发送信号提示老进程可以停止运行了。
  3. 新的worker启动成功后就开始接收新的请求,而旧worker在收到来自master的信号后停止接收新的请求,在未处理完的请求处理完成后进程就会退出。所以说使用nginx -s reload命令重启Nginx的时候服务是不中断的。

Nginx处理客户端请求方式

一个请求,完全由worker进程来处理,而且只在一个worker进程中处理。

当接收到客户端http请求,Nginx根据请求头的Host字段决定请求应该由哪一台服务器处理,如果Host字段的值没有匹配的服务器或者请求中没有Host字段,Nginx会将请求路由至这个端口的默认服务器。没有显示配置默认服务器,则默认服务器则为第一个配置。当然我们还可以使用default_server参数指定默认服务器。

Nginx实现高并发

Nginx内部采用了异步非阻塞的方式处理请求,使用了epoll和大量的底层代码优化。可以同时处理成千上万个请求的。

异步非阻塞:每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,比如向后端服务器转发request,并等待请求返回。这个处理的worke会在发送完请求后注册一个事件:“如果upstream返回了,再进行执行接下来的工作”。此时,如果再有request 进来,他就可以很快再按这种方式处理。而一旦后端服务器返回了,就会触发这个事件,worker进程会来接手request接着往下执行。

而Nginx采用一个master进程,多个woker进程的模式。master进程主要负责收集、分发请求。每当一个请求过来时,master就拉起一个worker进程负责处理这个请求。同时master进程也负责监控woker的状态,保证高可靠性,woker进程一般设置为跟cpu核心数一致。Nginx的woker进程在同一时间可以处理的请求数只受内存限制,可以处理多个请求。Nginx 的异步非阻塞工作方式可以把当中的进程空闲等待时间利用起来,因此表现为少数几个进程就解决了大量的并发问题。

Nginx中以epoll为例子,当事件没准备好时,放到epoll里面,事件准备好了,Nginx就去读写,当读写返回EAGAIN时,就将它再次加入到epoll里面。这样,只要有事件准备好了,Nginx就可以去处理它,只有当所有事件都没准备好时,才在epoll里面等着。这样便实现了所谓的并发处理请求,但是线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已。

Nginx单线程机制与多线程相比优势:

  • 在于不需要创建线程。
  • 每个请求占用的内存也很少。
  • 没有上下文切换。
  • 事件处理非常的轻量级。
  • 并发数再多也不会导致无谓的资源浪费。