NGINX Socket Sharding

NGINX1.9.1引入针对socket处理的选项SO_REUSEPOR,能让多个处理单元监听来自同一IP地址和端口的连接。

Nginx SO_REUSEPORT

该选项适用于较新版本的操作系统,包括DragonFly BSD和Linux(内核版本3.9及更高版本)。

SO_REUSEPORT选项能让多个socket,监听同一个ip地址和端口组合。操作系统内核(kernel)以socket负载均衡方式处理传入连接。

其他作用

可实现滚动升级nginx。对于nginx启用SO_REUSEPORT选项可减少锁争用提高某些场景下的性能。

正常情况下nginx处理用户请求如下图:

NGINX Socket Sharding

当请求到达时单个socket监听会通知所有工作进程,而每个工作进程都尝试执行连接。

启用SO_REUSEPORT该选项后,每个IP地址和端口组合(一个用户连接)有多个socket监听器,每个工作进程一个。

NGINX Socket Sharding

内核(kernel)决定哪个socket侦听器(及暗示哪个worker)可获得连接。这样可减少因接受新连接导致的工作进程之间的锁竞争,提高多核系统性能。

同时,也意味着当一个工作进程因阻塞操作而停顿时,不仅会影响该工作进程已经接受的连接,还会影响后续内核分配给该工作进程的连接请求。

配置Socket Sharding

启用SO_REUSEPORT选项,只需将reuseport参数包含在http或tcp(流模块)的listen指令中,如下所示:

http {
     server {
          listen 80 reuseport;
          server_name  localhost;
          # ...
     }
}

stream {
     server {
          listen 12345 reuseport;
          # ...
     }
}

启用reuseport参数会禁用socket accept_mutex指令(accept_mutex会使工作进程依次接受新连接,相反,将通知所有工作进程,若新连接数量很少,会导致系统资源浪费),在启用了reuseport后mutex是多余的。

如果nginx其他端口没有设置reuseport,accept_mutex仍然是可设置的。

reuseport基准测试

在一个36-core的AWS实例运行4个nginx工作进程,使用http基准测试工具WRK,让nginx返回字符串OK而非文件,为消除网络延迟的影响,以localhost方式运行客户端,比较nginx三种配置:默认(相当于accept_mutex on)、with accept_mutex off和with reuseport。

如图所示,reuseport每秒请求增加2~3倍,并降低客户端和服务器间的交互延迟。

socket sharding nginx

将客户端和nginx运行在各自主机上的基准测试,且nginx返回一个HTML文件。

使用reuseport,延迟的减少与之前的基准相似。其他结果也令人振奋。使用reuseport时,负载均匀分布在工作进程中。

            	Latency (ms)	Latency stdev (ms)	CPU Load
Default	            15.65	       26.59	          0.3
accept_mutex off	15.59	       26.48	          10
reuseport	        12.35	       3.15               0.3

在默认条件下(相当于accept_mutex on),只有部分工作进程的负载比较高,而accept_mutex off所有工作进程都经历了高负荷。

在这些基准测试中,连接请求的速率很高,但请求无需大规模处理。

其他初步测试表明,当流量与profile匹配时,reuseport性能最高(如,listen reuseport参数在mail上下文中不适用,因为电子邮件流量肯定与这个profile不匹配)。