Nginx listen reuseport参数带来的性能提升
NGINX发布的1.9.1版本引入了一个新的特性:允许使用SO_REUSEPORT
套接字选项,该选项在许多操作系统的新版本中是可用的,包括Bsd和Linux(内核版本3.9及以后)。该套接字选项允许多个套接字监听同一IP和端口的组合。内核能够在这些套接字中对传入的连接进行负载均衡。(对于NGINX Plus客户,此功能将在年底发布的版本7中出现)SO_REUSEPORT
选项有许多潜在的实际应用。其他服务也可以使用它来简单实现执行中的滚动升级(Nginx已经通过不同的办法支持了滚动升级)。对于NGINX而言,启用该选项可以减少在某些场景下的锁竞争而改善性能。
如下图描述,当SO_REUSEPORT选项有效时,一个单独的监听socket通知工作进程接入的连接,并且每个工作线程都试图获得连接。
当SO_REUSEPORT选项启用是,存在对每一个IP地址和端口绑定连接的多个socket监听器,每一个工作进程都可以分配一个。系统内核决定哪一个有效的socket监听器(通过隐式的方式,给哪一个工作进程)获得连接。这可以减少工作进程之间获得新连接时的封锁竞争(译者注:工作进程请求获得互斥资源加锁之间的竞争),同时在多核系统可以提高性能。然而,这也意味着当一个工作进程陷入阻塞操作时,阻塞影响的不仅是已经接受连接的工作进程,也同时让内核发送连接请求计划分配的工作进程因此变为阻塞。
设置共享Socket
为了让``SO_REUSEPORT socket```选项起作用,应为HTTP或TCP(流模式)通信选项内的listen项直接引入新近的reuseport参数,就像下例这样:
引用reuseport参数后,对引用的socket
,accept_mutex
参数将会无效,因为互斥量(mutex)对reuseport来说是多余的。对没有使用reuseport的端口,设置accept_mutex
仍然是有价值的。accept_mutex
默认是开启的,下面提供两个Nginx Core模块互斥锁的指令。
1)accept_mutex
互斥锁,就是各个worker接受用户请求的负载均衡锁,默认启用,表示让各个worker轮流地,序列化地响应用户请求;如果关闭那么所有的worker进程都会接收一个新的请求,如果连接数量不高的情况下,这么做只是会浪费系统资源。
2)lock_file
既然启动了负载均衡锁,那么就需要指定一个锁文件了。nginx使用锁机制来实现accept_mutex
和序列化访问共享内存。
reuseport的基准性能测试
我在一个36核的AWS实例运行wrk基准测试工具,测试4个NGINX工作进程。为了减少网络的影响,客户端和NGINX都运行在本地,并且让NGINX返回OK字符串而不是一个文件。我比较三种NGINX配置:默认(等同于accept_mutex on
),accept_mutex off
和reuseport。如图所示,reuseport的每秒请求是其余的两到三倍,同时延迟和延迟标准差也是减少的。
Nginx listen reuseport参数带来的性能提升
我又运行了另一个相关的性能测试——客户端和NGINX分别在不同的机器上且NGINX返回一个HTML文件。如下表所示,用reuseport减少的延迟和之前的性能测试相似,延迟的标准差减少的更为显著(接近十分之一)。其他结果(没有显示在表格中)同样令人振奋。使用reuseport ,负载被均匀分离到了worker进程。在默认条件下(等同于 accept_mutex on
),一些worker分到了较高百分比的负载,而用accept_mutex off
所有worker都受到了较高的负载。
Nginx listen reuseport参数带来的性能提升
在这些性能测试中,连接请求的速度是很高的,但是请求不需要大量的处理。其他的基本的测试应该指出——当应用流量符合这种场景时 reuseport 也能大幅提高性能。(reuseport 参数在 mail 上下文环境下不能用在 listen 指令下,例如email,因为email流量一定不会匹配这种场景。)我们鼓励你先测试而不是直接大规模应用。关于测试NGNIX性能的一些技巧,看看Konstantin Pavlov在nginx2014大会上的演讲。
原文链接:http://www.ywnds.com/?p=4543
- eclipse搭建ssh后台
- 解决mysql漏洞 Oracle MySQL Server远程安全漏洞(CVE-2015-0411)
- im4java包处理图片
- centOS7 mini配置linux服务器(五) 安装和配置tomcat和mysql
- RedisPool操作Redis,工具类实例
- centOS7 mini配置linux服务器(四) 配置jdk
- 老司机教你“飙”EventBus3
- Android listView异步下载和convertView复用产生的错位问题
- 实用Android 屏幕适配方案分享
- java-FFmpeg(一) 实现视频的转码和截图功能
- websocket(二) websocket的简单实现,识别用户属性的群聊
- websocket教程(一) 非常有趣的理解websocket
- 前端插件——头像截图上传插件的使用(带后台)
- 如何减轻ajax定时触发对服务器造成的压力和带宽的压力?ajax-长轮训
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法