最近开始关注Nginx源码,粗浅地记录下我的一些学习心得。
Nginx是一款高性能的Web服务器,它既可以作为HTTP服务器,也可以作为反向代理服务器或者邮件服务器,其源码采用C语言编写。
多进程模型
Nginx能够轻松支持万级别的并发,那么其背后的架构是怎样的呢?Nginx启动后,在Unix系统中会以Daemon的方式在后台运行,后台进程包含一个Master进程和多个Worker进程。Master进程主要负责管理所有Worker进程,即监控所有Worker进程的执行状态,并且负责接收来自外界的信号,并将信号传递给Worker进程。所有的网络事件则放在Worker进程中处理,多个Worker进程之间是平等的,它们同等竞争来自客户端的连接和请求。Worker进程的个数可通过配置文件中worker_processes n指令进行配置,一般其个数应该设置与CPU核数一致,且可通过配置文件中worker_cpu_affinity指令将Worker进程与具体CPU核进行绑定。Nginx的多进程模型如下图所示:
事件驱动模型
多个Worker进程相互独立,互不影响,且通过与CPU核的绑定避免了上下文的切换,节约了CPU的资源。不过这里的多进程模型并不意味着一定支持高并发,Apache服务器也是采用多进程方式,对于每一个客户端,Apache服务器都会生成一个新的子进程负责和该客户端的交互,直到连接断开,而面对大量并发请求,Apache则需要开辟大量的进程,就会对系统资源造成压力,从而导致性能的下降。而Nginx中每个工作进程采用异步非阻塞的事件处理机制,能够同时处理多个客户端的请求,当某个工作进程接收到客户端的请求以后,调用IO进行处理,如果不能立即得到结果,就去处理其他的请求,当IO调用返回结果时,就会通知此工作进程,该进程得到通知,便去响应客户端请求。具体来说,Nginx的工作进程采用了select/poll/epoll/kqueue这种系统调用,它们提供了一种机制,使得每个进程能够同时监控多个事件,在超时时间之内,假设有事件准备好了,就返回,这里对epoll等多路复用机制就不详细介绍了。这里需要注意的是,异步指的是Nginx的事件处理机制。