nginx服务器高并发配置详解(单机3w+并发)

前言

以前没有动手实践高并发系统搭建,对它的认知局限在事务控制,异步处理,微服务,负载均衡的应用层处理上。这两天在服务器的实践调优,了解如何配置参数,更重要的是知道为什么要这么配置,从而认识到了应用与操作系统的一些相关联系。
这个过程遇到了许多bug和系统相关,在这次记录中也会一起提到。文章后面会附上实测情况。

nginx配置

下面是nginx的主要主要配置。

# 避免权限问题
user root;
# 一般设置逻辑cpu数,可参看自身系统配置:cat /proc/cpuinfo| grep "processor"| wc -l 
worker_processes 6;
# 内核一切皆文件,所以有客户端连接就会有文件使用。
worker_rlimit_nofile 256000;

events {
	# Linux内核为处理大批量文件选择的模式
    use epoll;
    # 收到一个新连接通知后接受尽可能多的连接。
    multi_accept on;
    # 单个进程连接数
    worker_connections 65535;
}

http {
	# 负载均衡服务器,我这里用了10个节点不一一列举
	upstream load{
        server dc-sit-226:8881 max_fails=1 fail_timeout=60s;
        ...
        server dc-sit-226:8890 max_fails=1 fail_timeout=60s;
    }
    
    open_file_cache max=102400 inactive=20s;    
    client_header_buffer_size 4k;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   30;
    
    server {
        listen       80;
        server_name  dc-sit-226;
    	location / {
            proxy_pass http://load;
        }
    }
}

配置完成后记得重新加载配置:nginx -s reload。可先测试请求是否正常,并查看nginx日志是否存在异常。

部分异常

  • connect() to 192.168.9.226:8885 failed (13: Permission denied) while connecting to upstream, client: 192.168.64.243, server: dc-sit-226, request: “GET /value HTTP/1.1”, upstream: “http://192.168.9.226:8885/value”, host: “dc-sit-226”
    设置网络访问配置:setsebool -P httpd_can_network_connect 1
  • [alert] 12637#0: setrlimit(RLIMIT_NOFILE, 50000) failed (1: Operation not permitted)
    很多人知道nginx配置了worker_rlimit_nofile这个参数,但是成功没有就不知道了,reload时如果error.log日志中有这个异常我们就需要先执行:setsebool -P httpd_setrlimit 1,当然除了nginx需要配置文件限制,内核也不要进行修改。
  • [alert] 12291#0: *55710 socket() failed (24: Too many open files) while connecting to upstream, client: 192.168.9.226, server: dc-sit-226, request: “GET /value HTTP/1.0”, upstream: “http://192.168.9.226:8882/value”, host: “dc-sit-226”
    当我们worker_rlimit_nofile没有设置成功,超过1024文件访问会抛出这种异常,当然除了设置nginx的值,linux也需要做ulimit配置。下面我们会讲到系统配置。

系统配置

网上的实践配置每篇不是写的很全,或者适配自身系统,有时候还是要通过实际bug针对性的进行配置的添加、修改。这里你也更有机会了解其背后实际作用。

  • /etc/sysctl.conf
# 打开文件句柄数量
fs.file-max = 655360
# 最大ip跟踪数
net.nf_conntrack_max = 655360
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为2分钟。
net.netfilter.nf_conntrack_tcp_timeout_established = 120

# 允许系统打开的端口范围,扩大端口数
net.ipv4.ip_local_port_range = 10000 65535

# 用来限制监听(LISTEN)队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制,
net.core.somaxconn = 65535
# 每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
net.core.netdev_max_backlog = 262144

# 开启时就是同一个源IP来连接同一个目的端口的数据包时间戳必须是递增的,否则就丢弃
net.ipv4.tcp_timestamps = 0
# 是否启用timewait 快速回收。如果服务器身处NAT环境,tcp_timestamps为1,安全起见,要禁止
net.ipv4.tcp_tw_recycle = 1
# 开启重用。允许将TIME-WAIT sockets 重新用于新的TCP 连接。
net.ipv4.tcp_tw_reuse = 1
# timeout状态时间
net.ipv4.tcp_fin_timeout = 15

# 在TIME_WAIT数量等于该值时,不会有新的产生,
net.ipv4.tcp_max_tw_buckets = 262144
# 系统中最多有多少个TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。
net.ipv4.tcp_max_orphans = 262144
# 是指定所能接受SYN同步包的最大客户端数量。
net.ipv4.tcp_max_syn_backlog = 262144
# 为了打开对端的连接,内核需要发送一个SYN,以确认收到上一个 SYN连接请求包。也就是所谓三次握手中的第二次握手。
# 这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。
net.ipv4.tcp_synack_retries = 1
# 对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,测试感觉两个更稳定
net.ipv4.tcp_syn_retries = 2
# 开启SYN Cookies,当出现SYN 等待队列溢出时,启用cookies 来处理,目的是为了防止syn flood攻击。合法用户的高负载应该调整tcp_max_syn_backlog、tcp_synack_retries属性,
net.ipv4.tcp_syncookies = 0
  • /etc/security/limits.conf 末尾添加文件打开数量
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

通过sysctl -p 使得配置生效,可用通过ulimit -a查看file配置是否生效,临时设置也可用通过ulimit -u 65535 配置。

压测

  • apache-ab

ab单条测试-c 不能超过1w。下面是测试发送60w请求,服务器每秒处理1.3w,90%响应在1.4s内。
在这里插入图片描述

# 通过脚本多线程压测,3个线程每个并发1w,实现3w Concurrency Level,总共24w请求
#!/bin/bash
for((i=1;i<=3;i++));  
do   
  ab -k -n 80000 -c 10000 http://dc-sit-226/value > request.log${i} &
done
sleep 10 

下面为执行成功结果,单个分析打印在request.log${i} 中,
在这里插入图片描述
我们抽选一个结果可能看到3w 并发的情况下,服务器90% 的响应时长在3.3s内。高并发以响应90%请求5s内返回指标来看,服务器的理论极限承载应该可以调整到4w左右RPS(requests per second)
在这里插入图片描述

  • webbench
    webbench据说可以直接实现3w并发、测试前两次数据量小还正常,后面就有问题了,通过命令netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}',才发现测试请求全部变CLOSE_WAIT占用资源。
  • jmeter
    因为服务器没有GUI界面,生成jmt文件又比较繁琐,所以没选择这个工具。大家可以根据自己情况选择压测工具。

测试部分问题

  1. apr_socket_connect(): Cannot assign requested address (99)
    查看net.ipv4.ip_local_port_range、net.ipv4.tcp_tw_recycle、net.ipv4.tcp_tw_reuse、net.ipv4.tcp_timestamps 等系统配置
  2. connect() failed (110: Connection timed out) while connecting to upstream
    要查看系统日志:dmesg
    异常信息:nf_conntrack: table full, dropping packet.
    解决方案:查看系统上述net.nf_conntrack_max 配置。
    当然如果并发数达到一定数量、业务系统服务器也会超过承载极限,出现请求超时。
  3. apr_pollset_poll: The timeout specified has expired (70007)
    主要是timeout连接超时了,可以加个-k参数,让连接KeepAlive,另外注意nginx的超时配置。
  4. apr_socket_connect(): 由于目标系统积极拒绝
    业务系统服务器引起,可能是请求过载。
  5. no live upstreams while connecting to upstream, client: 192.168.9.226, server: dc-sit-226, request: “GET /value HTTP/1.0”, upstream: “http://load/value”, host: “dc-sit-226”
    与第二个问题类似,这里的load 我配置的负载均衡服务名,所以nginx应该是端时间找不到后端可用server,就会报no live upstream。可以考虑增加业务服务器数据或者改进接口效率。
发布了62 篇原创文章 · 获赞 33 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/yyoc97/article/details/103754483