好文收藏- Nginx 单机百万QPS环境搭建(转载)

举报
隔壁老汪 发表于 2022/06/25 23:50:05 2022/06/25
【摘要】 一、背景   最近公司在做一些物联网产品,物物通信用的是MQTT协议,内部权限与内部关系等业务逻辑准备用HTTP实现。leader要求在本地测试中要模拟出百万用户同时在线的需求。虽然该产品最后不一定有这么多,但是既然要求到了就要模拟出来。MQTT用的是erlang的emqtt,这个已经有同事测试在本机可以百万用户在线了。不过HTTP服...

一、背景

  最近公司在做一些物联网产品,物物通信用的是MQTT协议,内部权限与内部关系等业务逻辑准备用HTTP实现。leader要求在本地测试中要模拟出百万用户同时在线的需求。虽然该产品最后不一定有这么多,但是既然要求到了就要模拟出来。MQTT用的是erlang的emqtt,这个已经有同事测试在本机可以百万用户在线了。不过HTTP服务器就一直很难。

  所以这篇博客准备介绍如何在本地模拟一台支持百万qps的HTTP服务器。简单说一下,MQTT的百万在线是指支持百万TCP连接,连接后,只要保持心跳包就可以了,这个比较简单,一般稍微调整一下Linux一些系统参数就可以了。而HTTP的百万在线不一样。HTTP是发送一个连接请求后获得数据然后就关闭连接,百万并发就比较麻烦,而且这个概念用在这里不是很合适。现在比较通用的一种参考值是每秒处理的并发数。就是QPS。(这一点就很多人不理解。包括我leader,这个要在接下来慢慢解释给他听)

 

二、准备

  我以前也没有搞过高并发的网络,最近看了一些博客文章,准备用一个最简单的模型来实现这个百万QPS的模拟。后台我是用Java写的,Tomcat服务器。这种带业务的请求,单机绝对不可能到达百万QPS(1m-qps)。网上所说的1m-qps测试环境是一个静态的网页来测试的。既然带业务的http单机不能达到要求,那就需要用到集群了。就我目前所学到的知识,基本就只会搭建下面如图所示的集群架构了。

  一台性能比较好的机器按照nginx作为负载均衡,剩下的一些普通的机器就在后面。数据库目前只用到一个,后续如何优化和扩展不在本次讨论。

  如果使用上面的架构,出去数据库后,整个HTTP的性能瓶颈就在最前面的Nginx负载均衡上了。其他的HTTP-jsp-tomcat机器如果性能不够,可以通过多加几台机器进行水平扩展。而最前面的Nginx就不行了。所以本次所要测试的就是如何让nginx支持1m-qps,并且机器正常工作。nginx只是做数据转发而已。

  硬件:服务器88核、128G内存

  软件:Debian 8, Nginx 1.11,  wrk压力测试工具

 

三、操作

1. 首先设置一些Linux系统参数 在/etc/sysctl.conf 中增加如下配置

复制代码

 1 vm.swappiness = 0
 2 net.ipv4.neigh.default.gc_stale_time=120
 3 net.ipv4.conf.all.rp_filter=0
 4 net.ipv4.conf.default.rp_filter=0
 5 net.ipv4.conf.default.arp_announce = 2
 6 net.ipv4.conf.all.arp_announce=2
 7 net.ipv4.tcp_max_tw_buckets = 100
 8 net.ipv4.tcp_syncookies = 0
 9 net.ipv4.tcp_max_syn_backlog = 3240000
10 net.ipv4.tcp_window_scaling = 1
11 #net.ipv4.tcp_keepalive_time = 60
12 net.ipv4.tcp_synack_retries = 2
13 net.ipv6.conf.all.disable_ipv6 = 1
14 net.ipv6.conf.default.disable_ipv6 = 1
15 net.ipv6.conf.lo.disable_ipv6 = 1
16 net.ipv4.conf.lo.arp_announce=2
17 fs.file-max = 40000500
18 fs.nr_open = 40000500
19 net.ipv4.tcp_tw_reuse = 1
20 net.ipv4.tcp_tw_recycle = 1
21 net.ipv4.tcp_keepalive_time = 1
22 net.ipv4.tcp_keepalive_intvl = 15
23 net.ipv4.tcp_keepalive_probes = 3
24 
25 net.ipv4.tcp_fin_timeout = 5
26 net.ipv4.tcp_mem = 768432 2097152 15242880
27 net.ipv4.tcp_rmem = 4096 4096 33554432
28 net.ipv4.tcp_wmem = 4096 4096 33554432
29 net.core.somaxconn = 6553600
30 net.ipv4.ip_local_port_range = 2048 64500
31 net.core.wmem_default = 183888608
32 net.core.rmem_default = 183888608
33 net.core.rmem_max = 33554432
34 net.core.wmem_max = 33554432
35 net.core.netdev_max_backlog = 2621244
36 kernel.sem=250 65536 100 2048
37 kernel.shmmni = 655360
38 kernel.shmmax = 34359738368
39 kerntl.shmall = 4194304
40 kernel.msgmni = 65535
41 kernel.msgmax = 65536
42 kernel.msgmnb = 65536
43 
44 net.netfilter.nf_conntrack_max=1000000
45 net.nf_conntrack_max=1000000
46 net.ipv4.netfilter.ip_conntrack_max=1000000
47 kernel.perf_cpu_time_max_percent=60
48 kernel.perf_event_max_sample_rate=6250
49 
50 net.ipv4.tcp_max_orphans=1048576
51 kernel.sched_migration_cost_ns=5000000
52 net.core.optmem_max = 25165824
53 
54 kernel.sem=10000 2560000 10000 256

复制代码

还有在命令行中输入 ulimit -n 20000500 

上面的所有参数,这里就不多讲了,具体想要了解的可以上网找资料

2.Nginx 安装 及其配置

nginx用最简单的apt-get 也可以,用源码按照也可以。没有什么特殊要求。下面的配置就有点要求了。 $NGINX/conf/nginx.conf (/etc/nginx/conf/nginx.conf)

复制代码

 1 worker_processes  88;  #这个根据硬件有多少核CPU而定
 2 pid        logs/nginx.pid;
 3 
 4 events {
 5     worker_connections  1024;
 6 }
 7 
 8 http {
 9     include       mime.types;
10     default_type  application/octet-stream;
11     sendfile        on;
12     tcp_nopush     on;
13 
14     keepalive_timeout  65;
15 
16     gzip  off;
17     access_log off;   #日志功能要关闭
18 
19     server {
20         listen       888 backlog=168888;
21         server_name  localhost;
22       root /dev/shm/;
23     }
24 
25 }

复制代码

  上面这个是最简单的配置,具体的Nginx还有很多可以调优的,还有nginx负载均衡配置,请参考我的另外一片博客<Nginx + Tomcat 动静分离实现负载均衡 http://www.cnblogs.com/wunaozai/p/5001742.html>

 

 View Code

 

 

 

3. 创建一个简单的html文件

  看到 root  /dev/shm/ 了吗, 这个就是http服务器根目录了。 echo "a" > /dev/shm/a.html

4. 安装wrk

  git clone https://github.com/wg/wrk.git  然后 make

 

四、运行

  启动nginx

  启动wrk 进行并发请求测试

./wrk -t88 -c10000 -d20s "http://127.0.0.1:888/a.html"

  top结果图

  wrk 结果图

  基本在120万QPS。nginx设置一些调优参数,加上如果不在本机上运行wrk的话,150万QPS基本是没有问题的。

 

五、要达到1m-qps需要注意

 Linux 参数一定要进行调整 (坑: 这个坑是比较小的,基本提到高并发Linux,就会有提到要修改这些参数了)

 Nginx 里 access_log off; 日志功能一定要关闭 (坑: 这个影响还是比较大的,由于Nginx日志是写在磁盘的,而我服务器的磁盘是普通的磁盘,所以这里会成为磁盘IO瓶颈,所以一开始用最简单的配置,然后根据硬件的不同修改参数。有些参数在其他机器很快,在我的机器就很慢)

 测试并发工具最好用我上面的wrk进行测试 (坑: 一开始用apache的ab进行测试,后面发现ab测试高性能时不行,最后使用wrk工具)

 最好在本机测试wrk (坑: 从上面的wrk图可以看到,传输的数据在每秒262MB左右,普通的100M网卡是远远达不到的。虽然我的a.html只有一个字节,但是http头部信息太多了。这里还有一个小坑,就是我的服务器是有千兆网卡的,但是我用另外一台测试机也是千兆网卡,但是中间的交换机或者路由器或者网线都达不到要求,所以这里会成为网络瓶颈) 

 上面那几个就是我遇到的坑了,特别是最后两个,一度还怀疑nginx性能问题。因为网上很多评测都说Nginx做代理可以达到百万QPS,我总是测试不到,基本在2~3万QPS而已。最后发现是测试工具和网卡原因。

 

六、最后多说两句

  其实整个安装搭建测试环境都比较简单,这篇博客最主要的点还是最后的几点注意,由于以前没有搞过这方面,所以没有经验,这里记录下来,以后提醒自己。前端的负载均衡器保证没有问题后,接下来的问题是后面的HTTP服务集群了。我现在的Java功能后台一台普通的服务器(Tomcat)就只能支持一万多的简单请求(因为jvm和web框架等种种原因),然后如果是那种需要简单查询数据库的功能API就只有2~3K的QPS,最后那些需要事务操作的一台服务器仅仅只能支持120~150QPS。第一个还好,通过加机器就可以水平扩展,但是后面那两个跟数据库相关的就比较麻烦了,各种新的名词(NoSQL、缓存、读写分离、分库分表、索引、优化SQL语句等)都来了。能力有限,后续要学的东西太多了。

 

---- 2016-11-22 19:27:18  增加----- 

  单机进行测试的时候好多配置都没有用到,原因是,所有的请求和应答基本都是在内存处理的,没有创建socket连接,没有经过网卡网线路由器交换机等。这两天测试发现经过nginx代理后连接并发数上不去,查了一天,发现问题是nginx的keepalive参数没有打开。这个参数没有打开的话, 会造成每次代理,都会创建一个http-socket,处理完就关闭,这样会比较占用资源,同时连接数上不去。加上keepalive参数后,外网的N个并发请求就可以通过一条socket发送多次请求。(这个描述比较不清楚, 如果对http1.0 http1.1 http2.0 里面的关于HTTP协议连接问题了解的话, 上面的描述就不难理解。)

  集群的upstream设置为

复制代码

1 # 这里要设置keepalive 表示本机与后端机器的连接数
2 # 同时这里还有一些其他设置,如权重,负载类型等
3 upstream wunaozai.cnblogs.com {
4     server 192.168.25.106:888;
5     server 192.168.25.100:888;
6     server 192.168.9.201:888;
7     keepalive 1000;
8 }

复制代码

  server代理设置为

复制代码

 1 server {
 2     listen 88 backlog=168888;
 3     server_name localhost2;
 4     location ~ .*$ {
 5         index index;
 6         proxy_pass http://wunaozai.cnblogs.com;
 7         proxy_set_header Connection "keep-alive";
 8         proxy_http_version 1.1;
 9         proxy_ignore_client_abort on;
10         #下面的timeout跟自己的业务相关设置对应的timeout
11         proxy_connect_timeout 600;
12         proxy_read_timeout 600;
13         proxy_send_timeout 600;
14     }
15 }

复制代码

 

 

 

参考资料:

  http://datacratic.com/site/blog/1m-qps-nginx-and-ubuntu-1204-ec2

  http://serverfault.com/questions/408546/how-to-achieve-500k-requests-per-second-on-my-webserver

  https://lowlatencyweb.wordpress.com/2012/03/20/500000-requestssec-modern-http-servers-are-fast/

  http://blog.jobbole.com/87531/

  https://github.com/wg/wrk 

作者:无脑仔的小明 
出处:http://www.cnblogs.com/wunaozai/ 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 
如果文中有什么错误,欢迎指出。以免更多的人被误导。有需要沟通的,可以站内私信,文章留言,或者关注“无脑仔的小明”公众号私信我。一定尽力回答。 

文章来源: blog.csdn.net,作者:隔壁老瓦,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/wxb880114/article/details/107322164

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。