文章目录
-
前言
- nginx配置
-
部分异常
- 系统配置
- 压测
- 测试部分问题
前言
以前没有动手实践高并发系统搭建,对它的认知局限在事务控制,异步处理,微服务,负载均衡的应用层处理上。这两天在服务器的实践调优,了解如何配置参数,更重要的是知道为什么要这么配置,从而认识到了应用与操作系统的一些相关联系。
这个过程遇到了许多bug和系统相关,在这次记录中也会一起提到。文章后面会附上实测情况。
nginx配置
下面是nginx的主要主要配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 1# 避免权限问题
2user root;
3# 一般设置逻辑cpu数,可参看自身系统配置:cat /proc/cpuinfo| grep "processor"| wc -l
4worker_processes 6;
5# 内核一切皆文件,所以有客户端连接就会有文件使用。
6worker_rlimit_nofile 256000;
7
8events {
9 # Linux内核为处理大批量文件选择的模式
10 use epoll;
11 # 收到一个新连接通知后接受尽可能多的连接。
12 multi_accept on;
13 # 单个进程连接数
14 worker_connections 65535;
15}
16
17http {
18 # 负载均衡服务器,我这里用了10个节点不一一列举
19 upstream load{
20 server dc-sit-226:8881 max_fails=1 fail_timeout=60s;
21 ...
22 server dc-sit-226:8890 max_fails=1 fail_timeout=60s;
23 }
24
25 open_file_cache max=102400 inactive=20s;
26 client_header_buffer_size 4k;
27 sendfile on;
28 tcp_nopush on;
29 tcp_nodelay on;
30 keepalive_timeout 30;
31
32 server {
33 listen 80;
34 server_name dc-sit-226;
35 location / {
36 proxy_pass http://load;
37 }
38 }
39}
40
41
配置完成后记得重新加载配置: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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 1# 打开文件句柄数量
2fs.file-max = 655360
3# 最大ip跟踪数
4net.nf_conntrack_max = 655360
5#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为2分钟。
6net.netfilter.nf_conntrack_tcp_timeout_established = 120
7
8# 允许系统打开的端口范围,扩大端口数
9net.ipv4.ip_local_port_range = 10000 65535
10
11# 用来限制监听(LISTEN)队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制,
12net.core.somaxconn = 65535
13# 每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
14net.core.netdev_max_backlog = 262144
15
16# 开启时就是同一个源IP来连接同一个目的端口的数据包时间戳必须是递增的,否则就丢弃
17net.ipv4.tcp_timestamps = 0
18# 是否启用timewait 快速回收。如果服务器身处NAT环境,tcp_timestamps为1,安全起见,要禁止
19net.ipv4.tcp_tw_recycle = 1
20# 开启重用。允许将TIME-WAIT sockets 重新用于新的TCP 连接。
21net.ipv4.tcp_tw_reuse = 1
22# timeout状态时间
23net.ipv4.tcp_fin_timeout = 15
24
25# 在TIME_WAIT数量等于该值时,不会有新的产生,
26net.ipv4.tcp_max_tw_buckets = 262144
27# 系统中最多有多少个TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。
28net.ipv4.tcp_max_orphans = 262144
29# 是指定所能接受SYN同步包的最大客户端数量。
30net.ipv4.tcp_max_syn_backlog = 262144
31# 为了打开对端的连接,内核需要发送一个SYN,以确认收到上一个 SYN连接请求包。也就是所谓三次握手中的第二次握手。
32# 这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。
33net.ipv4.tcp_synack_retries = 1
34# 对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,测试感觉两个更稳定
35net.ipv4.tcp_syn_retries = 2
36# 开启SYN Cookies,当出现SYN 等待队列溢出时,启用cookies 来处理,目的是为了防止syn flood攻击。合法用户的高负载应该调整tcp_max_syn_backlog、tcp_synack_retries属性,
37net.ipv4.tcp_syncookies = 0
38
39
-
/etc/security/limits.conf 末尾添加文件打开数量
1
2
3
4
5
6 1* soft nofile 65535
2* hard nofile 65535
3* soft nproc 65535
4* hard nproc 65535
5
6
通过sysctl -p 使得配置生效,可用通过ulimit -a查看file配置是否生效,临时设置也可用通过ulimit -u 65535 配置。
压测
- apache-ab
ab单条测试-c 不能超过1w。下面是测试发送60w请求,服务器每秒处理1.3w,90%响应在1.4s内。
1
2
3
4
5
6
7
8
9 1# 通过脚本多线程压测,3个线程每个并发1w,实现3w Concurrency Level,总共24w请求
2#!/bin/bash
3for((i=1;i<=3;i++));
4do
5 ab -k -n 80000 -c 10000 http://dc-sit-226/value > request.log${i} &
6done
7sleep 10
8
9
下面为执行成功结果,单个分析打印在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文件又比较繁琐,所以没选择这个工具。大家可以根据自己情况选择压测工具。
测试部分问题
- 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 等系统配置
- connect() failed (110: Connection timed out) while connecting to upstream
要查看系统日志:dmesg
异常信息:nf_conntrack: table full, dropping packet.
解决方案:查看系统上述net.nf_conntrack_max 配置。
当然如果并发数达到一定数量、业务系统服务器也会超过承载极限,出现请求超时。
- apr_pollset_poll: The timeout specified has expired (70007)
主要是timeout连接超时了,可以加个-k参数,让连接KeepAlive,另外注意nginx的超时配置。
- apr_socket_connect(): 由于目标系统积极拒绝
业务系统服务器引起,可能是请求过载。
- 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。可以考虑增加业务服务器数据或者改进接口效率。