深入理解nginx如何实现高性能和可扩展性

2019-10-17 16:47:12刘景俊

NGINX内部的工作进程

Inside the NGINX Worker Process

每一个NGINX的工作进程都是NGINX配置(NGINX configuration)初始化的,并被主进程设置了一组监听套接字(listen sockets)。

NGINX工作进程会监听套接字上的事件(accept_mutex和kernel socket sharding),来决定什么时候开始工作。事件是由新的连接初始化的。这些连接被会分配给状态机(state machine)——HTTP状态机是最常用的,但NGINX还为流(原生TCP)和大量的邮件协议(SMTP,IMAP和POP3)实现了状态机。

状态机本质上是一组告知NGINX如何处理请求的指令。大多数和NGINX具有相同功能的web服务器也使用类似的状态机——只是实现不同。

调度状态机

Scheduling the State Machine

把状态机想象成国际象棋的规则。每个HTTP事务(HTTP transaction)都是一局象棋比赛。棋盘的一边是web服务器——坐着一位可以迅速做出决定的大师级棋手。另一边是远程客户端——在相对较慢的网络中,访问站点或应用程序的web浏览器。

然而,比赛的规则可能会很复杂。例如,web服务器可能需要与各方沟通(代理一个上游的应用程序),或者和认证服务器交流。web服务器的第三方模块也可以拓展比赛规则。

阻塞状态机

A Blocking State Machine

回忆一下我们之前对进程和线程的描述:是一组操作系统可调度的、运行在CPU内核上的独立指令集。大多数web服务器和web应用都使用一个连接 /一个进程或一个连接/一个线程的模型来进行这局国际象棋比赛。每个进程或线程都包含一个将比赛玩到最后的指令。在这个过程中,进程是由服务器来运行的,它的大部分时间都花在“阻塞(blocked)”上,等待客户端完成其下一个动作。

1.web服务器进程(web server process)在监听套接字上,监听新的连接(客户端发起的新比赛)。

2.一局新的比赛发起后,进程就开始工作,每一步棋下完后都进入阻塞状态,等待客户端走下一步棋。

3.一旦比赛结束,web服务器进程会看看客户是否想开始新的比赛(这相当于一个存活的连接)。如果连接被关闭(客户端离开或者超时),web服务器进程会回到监听状态,等待全新的比赛。

记住重要的一点:每一个活跃的HTTP连接(每局象棋比赛)都需要一个专用的进程或线程(一位大师级棋手)。这种架构非常易于扩展第三方模块 (“新规则”)。然而,这里存在着一个巨大的不平衡:一个以文件描述符(file descriptor)和少量内存为代表的轻量级HTTP连接,会映射到一个单独的进程或线程——它们是非常重量级的操作系统对象。这在编程上是方便的,但它造成了巨大的浪费。

NGINX是真正的大师

NGINX is a True Grandmaster

也许你听说过车轮表演赛,在比赛中一个象棋大师要在同一时间对付几十个对手。