OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。
下载安装
以下操作指令摘抄自OpenResty官网,不做赘述。
sudo yum -y install yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
sudo yum -y install openresty
sudo yum -y install openresty-resty
安装完成之后,我们进入OpenResty所在目录
cd /usr/local/openresty
ll
测试用例
- 创建测试用lua文件
cd /usr/local/openresty/lualib
mkdir test
cd test
vim test.lua
--用于接收前端数据的对象
local args=nil
--获取前端的请求方式 并获取传递的参数
local request_method = ngx.var.request_method
--判断是get请求还是post请求并分别拿出相应的数据
if"GET" == request_method then
args = ngx.req.get_uri_args()
elseif "POST" == request_method then
ngx.req.read_body()
args = ngx.req.get_post_args()
--兼容请求使用post请求,但是传参以get方式传造成的无法获取到数据的bug
if (args == nil or args.data == null) then
args = ngx.req.get_uri_args()
end
end
--获取前端传递的name值
local name = args.name
--响应前端
ngx.say("linux hello:"..name)
- 配置nginx
openresty内置nginx,使用openresty需要使用它内部的nginx。
cd /usr/local/openresty/nginx/conf
vim nginx.conf
最终测试配置为
#user nobody;
worker_processes 2;
events {
use epoll;
worker_connections 150000;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /luatest
{
default_type text/html;
content_by_lua_file /usr/local/openresty/lualib/test/test.lua;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
AB压力测试
安装httpd-tools
yum -y install httpd-tools
试一把1w并发,10w请求
提示
Too many open files (24)
打开的文件太多了
查看允许打开的文件数
ulimit -a
修改允许打开的文件数
ulimit -n 204800
继续试1w并发,10w请求,出现
apr_socket_recv: Connection reset by peer (104)
问题
apr_socket_recv这个是操作系统内核的一个参数,在高并发的情况下,内核会认为系统受到了
SYN flood
(一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式)攻击,导致未完成退出测试,所以在应用服务武器上设置下这个参数为0禁用系统保护
进入管理配置文件
vim /etc/sysctl.conf
#添加如下一行
net.ipv4.tcp_syncookies = 0
#保存退出后执行
sysctl -p
扩展(未测试)
net.ipv4.tcp_syncookies = 0
#此参数是为了防止洪水攻击的,但对于大并发系统,要禁用此设置
net.ipv4.tcp_max_syn_backlog
#参数决定了SYN_RECV状态队列的数量,一般默认值为512或者1024,即超过这个数量,系统将不再接受新的TCP连接请求,一定程度上可以防止系统资源耗尽。可根据情况增加该值以接受更多的连接请求。
net.ipv4.tcp_tw_recycle
#参数决定是否加速TIME_WAIT的sockets的回收,默认为0。
net.ipv4.tcp_tw_reuse
#参数决定是否可将TIME_WAIT状态的sockets用于新的TCP连接,默认为0。
net.ipv4.tcp_max_tw_buckets
好了,现在可以正常测试了
- 1w并发10w请求
ab -c 10000 -n 100000 127.0.0.1/luatest
结果:
#服务器信息,ip,端口
Server Software: openresty/1.13.6.2
Server Hostname: 127.0.0.1
Server Port: 80
#文档/接口,响应数据大小
Document Path: /luatest
Document Length: 541 bytes
#压力测试的结果报表
#并发请求数
Concurrency Level: 10000
#测试耗时
Time taken for tests: 11.361 seconds
#完成请求数
Complete requests: 100000
#失败请求数
Failed requests: 9
(Connect: 0, Receive: 0, Length: 9, Exceptions: 0)
Write errors: 0
Non-2xx responses: 100000
#总网络传输量
Total transferred: 73096724 bytes
#HTML内容传输量
HTML transferred: 54096922 bytes
#吞吐量,平均每秒处理请求数
Requests per second: 8801.77 [#/sec] (mean)
#前端请求平均时间
Time per request: 1136.135 [ms] (mean)
#服务平均处理请求的时间
Time per request: 0.114 [ms] (mean, across all concurrent requests)
#网络传输速度。对于大文件的请求测试,这个值很容易成为系统瓶颈所在。
Transfer rate: 6283.01 [Kbytes/sec] received
#时间消耗报表针对请求平均等待时间`Time per request`的细化分析,只是了解
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 304 884.1 14 7055
Processing: 3 35 65.5 23 11029
Waiting: 0 29 63.4 18 11029
Total: 6 339 902.2 36 11226
#请求时间分布,50%的请求在36毫秒内处理完毕。90%的请求在1077毫秒内处理完毕,最长响应时间为11226毫秒
Percentage of the requests served within a certain time (ms)
50% 36
66% 61
75% 101
80% 171
90% 1077
95% 1197
98% 3160
99% 3235
100% 11226 (longest request)
提取部分参数稍微总结下:
吞吐量(每秒处理的请求数):8801.77
验证:吞吐量(8801.77) * 测试耗时 (11.361) 约等于10W
用户平均等待时间:1136.135
服务器平均处理时间:0.114
验证:由于服务器并发量为1W,那用户前端响应时间,应该接近服务器平均处理时间 * 1w,0.114*10000=1140,1136.135约等于1140
90%的请求在1077ms内完成,最长的请求耗时11226毫秒。
网络传输速度:6283.01kb
- 2w并发10w请求
ab -c 20000 -n 100000 127.0.0.1/luatest
这里简单分析标出重要数据
总结
这里主要测试openresty(实际上是nginx)平台的并发能力,用于测试的电脑,为2核4G的笔记本,2W的并发没有什么压力,可惜AB测试有上限,不太方便做极限测试。
简单来说,OpenResty提供了一种Nginx处理请求,lua脚本处理逻辑(操作MySQL,Redis等)的一种平台响应模式。我们知道Lua 是一种轻量小巧的脚本语言,用标准C语言编写。它的执行效率无疑比java高的多。
特点
- 充分利用Nginx的并发能力和lua的执行效率,分担了Tomcat等Web应用服务器的压力。
- lua属于脚本语言,更新版本只需要更新修改Lua脚本之后,重启Nginx即可完成更新发布。
- 不适合开发复杂业务逻辑
适用 - 高并发,高频率调用的,并且主要目的用于获取数据的接口适用lua编写(比如首页的展示数据)。
- 请求过滤拦截(商城秒杀,商品完了之后的请求拦截)
参考
OpenResty®
Apache ab性能测试结果分析