性能侧测试压力机瓶颈分析及优化

性能测试过程中,为了给服务器足够的压力,少不了要使用压力机,即模拟客户端的服务器,压力如果使用不当,测试结果就会不准确,反映不了服务器的真实性能情况
因此,需要充分了解压力机,并对其进行调优,从而避免压力机自身瓶颈对压测带来的影响,未得到准确可好的测试结果,提供前置条件、
以下,分三步来确保压力机靠谱:
第一步:了解压力机自身可能成为瓶颈的配置,并调优; 
第二步:了解被模拟程序自身可能成为瓶颈的配置,并调优; 
第三步:找到压力机上,单进程的性能瓶颈,以避免在施压过程中受此干扰;

第一步:
  1.网络通讯协议相关配置调优(以TCP为例),优化最大连接数,理论上TCP最大连接数为5,因此理论上单机的瞬时并发最大不可能超过65535;
  既然使用了压力机,必然通过某种网络通讯协议来建立连接,并发送请求。以TCP协议为例,先简单了解下TCP协议:
  在确定最大连接数之前,先来看看系统如何表示一个TCP连接。系统使用一个4元组来唯一标识一个TCP连接:{local ip,local port,remote ip,remote port}
  client最大tcp连接数(理论上)
  client每次发起tcp连接请求时,除非绑定端口,通常会让系统选取一个空闲的本地端口(localhost)该端口是独占的,不能和其他tcp连接共享。tcp端口的数据类型是unsigned short,
  因此本地端口个数最大只有65535,端口0有特殊含义,不能使用,这样可用端口最多只有65535,所以在全部作为client端的情况下,最大tp连接数未65535,者相连接可以连接到不同的server ip.
  server 最大tcp连接数(理论上),参考文档:http://www.cnblogs.com/mydomain/archive/2013/05/27/3100835.html
  上面给出的是理论上的单机最大连接数,在实际环境中,受到机器资源、操作系统等的限制,其最大并发tcp连接数远不能达到理论上限,另外1024以下的端口通常为保留端口。 
除端口限制外,TCP连接的内存设置,也会影响到最大连接数。在默认2.6内核配置下,经过试验,每个socket占用内存在15~20k之间。
  

影响一个socket占用内存的参数包括:

rmem_max

wmem_max

tcp_rmem

tcp_wmem

tcp_mem

grep skbuff /proc/slabinfo

对server端,通过增加内存、修改最大文件描述符个数等参数,单机最大并发TCP连接数超过10万 是没问题的,国外Urban Airship 公司在产品环境中已做到 50 万并发 。在实际应用中,对大规模网络应用,还需要考虑C10K 问题。

综上,关于TCP最大连接数,linux/Unix下有以下三类配置可以调优 
A: Linux 网络内核对本地端口号范围的限制:
修改/etc/sysctl.conf文件,在文件中添加或修改如下行:
```
net.ipv4.ip_local_port_range = 1024 65000
```

这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的最大值则应小于或等于65535。修改完后保存此文件。

  修改完成后,执行sysctl

  sysctl -p

如果系统没有吃错误提示,表明新的本地端口范围设置成功如果按上述端口范围进行设置,则理论上单独一个进程最多可以同时建立60000多个

B:Linux 网络内核的IP_TABLE放过墙对最大跟踪的TCP连接数的限制,如果防火墙已关闭,则忽略

首先确定有没有防火墙:service iptables status

如果有,条件允许,可以直接:service iptables stop iptables

在查看防火墙状态:service iptables status

运行结果:iptables: Firewall is not running.

如果不能关闭防火墙,则修改IP_TABLE防火墙对最大跟踪的TCP连接数: 
修改/etc/sysctl.conf文件,在文件中添加或修改如net.ipv4.ip_conntrack_max = 40960 
修改完成后,执行sysctl 
sysctl -p 
如果系统没有错误提示,就表明系统对新的最大跟踪的TCP连接数限制修改成功。若按上述参数进行设置,则理论上单独一个进程最多可以同时建立40960个TCP客户端连接。 

C:TCP相关内存限制
在默认2.6内核配置下,经过试验,每个socket占用内存在15~20K之间。
修改配置文件:etc/sysctl.conf
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
**net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_max_syn_backlog = 262144**
net.core.netdev_max_backlog = 20000
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_max_orphans = 131072

  

配置文件生效:sudo /sbin/sysctl -p 
主要看这几项,按机器内存大小,进行调节: 
net.ipv4.tcp_rmem 用来配置读缓冲的大小,三个值,第一个是这个读缓冲的最小值,第三个是最大值,中间的是默认值。我们可以在程序中修改读缓冲的大小,但是不能超过最小与最大。为了使每个socket所使用的内存数最小,我这里设置默认值为4096。 
net.ipv4.tcp_wmem 用来配置写缓冲的大小。读缓冲与写缓冲在大小,直接影响到socket在内核中内存的占用。 
net.ipv4.tcp_mem 则是配置tcp的内存大小,其单位是页,而不是字节。当超过第二个值时,TCP进入 pressure模式,此时TCP尝试稳定其内存的使用,当小于第一个值时,就退出pressure模式。当内存占用超过第三个值时,TCP就拒绝分配 socket了,查看dmesg,会打出很多的日志“TCP: too many of orphaned sockets”。 
net.ipv4.tcp_max_orphans 这个值也要设置一下,这个值表示系统所能处理不属于任何进程的 socket数量,当我们需要快速建立大量连接时,就需要关注下这个值了。当不属于任何进程的socket的数量大于这个值时,dmesg就会看 到”too many of orphaned sockets”。

另外,附上LINUX 查看tcp连接数及状态,

LINUX 查看tcp连接数及状态

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

TIME_WAIT 8947 等待足够的时间以确保远程TCP接收到连接中断请求的确认
FIN_WAIT1 15 等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN_WAIT2 1 从远程TCP等待连接中断请求
ESTABLISHED 55 代表一个打开的连接
SYN_RECV 21 再收到和发送一个连接请求后等待对方对连接请求的确认
CLOSING 2 没有任何连接状态
LAST_ACK 4 等待原来的发向远程TCP的连接中断请求的确认

TCP连接状态详解
LISTEN: 侦听来自远方的TCP端口的连接请求
SYN-SENT: 再发送连接请求后等待匹配的连接请求
SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认
ESTABLISHED: 代表一个打开的连接
FIN-WAIT-1: 等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2: 从远程TCP等待连接中断请求
CLOSE-WAIT: 等待从本地用户发来的连接中断请求
CLOSING: 等待远程TCP对连接中断的确认
LAST-ACK: 等待原来的发向远程TCP的连接中断请求的确认
TIME-WAIT: 等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED: 没有任何连接状态

2、调整最大打开文件数;http://www.cnblogs.com/peida/archive/2013/02/26/2932972.html 
在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。 
lsof打开的文件可以是: 
普通文件、目录、网络文件系统的文件、字符或设备文件、(函数)共享库、管道,命名管道、符号链接、网络文件(例如:NFS file、网络socket,unix域名socket)、还有其它类型的文件,等等 
故,作为压力机,每个TCP/UDP连接都会占用一个文件打开数,此处,可能成为瓶颈。

    1. 打开进程数限制(root用户本项是无限)

      如果你对进程总数量没有特殊要求,可以不修改本选项。 
      执行命令: 
      ulimit -a 
      查看结果: 
      max user processes (-u) 16484 
      如果此项可能成为瓶颈,则修改此项。

    2. 确认网卡、路由不会成为瓶颈 
      此处不做详解。

    3. 确认网络带宽

      此处不做详解,查看实时带宽流量 https://help.aliyun.com/knowledge_detail/5988901.html?pos=11

    4. 压力机其他可调优的参数:http://blog.csdn.net/my_yang/article/details/45788717第二步:

第二步:以java为例:

java堆内存、栈内存,理论详见:http://blog.csdn.net/qh_java/article/details/9084091 重要的是: 

在java中每new一个线程,jvm都是向操作系统请求new一个本地线程,此时操作系统会使用剩余的内存空间来为线程分配内存,而不是使用jvm的内存。这样,当操作系统的可用内存越少,则jvm可用创建的新线程也就越少。见:http://blog.sina.com.cn/s/blog_684fe8af0100wzg5.html 

因此,可以理解为线程使用的内存,不在“使用-Xms -Xmx设置的内存”中,需要根据实际情况进行调节,不宜过大,否则能启动的线程数量越小; 

如果是maven项目,使用jemeter,且使用maven的jemeter插件,那么在POM里,jmeter插件中设置此内存大小;

另外,附上如何计算,只考虑内存的情况下,机器理论上能打开的最大线程数:http://blog.csdn.net/feng27156/article/details/19333575 

官网查线程栈默认值(64位为1M)http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html 

maven内存

maven本身编译的内存也不宜设置过小或过大,会影响能启动的线程数;

其他施压程序的瓶颈

有的框架或程序,可以限制单台机器,连接到本服务的最大线程数,此配置可能成为瓶颈,比如dubbo的 actives配置(每服务消费者每服务每方法最大并发调用数) 

其他类似的配置;找到压力机上,施压程序单进程的性能瓶颈; 

如果是物理机,且并发数不大(几百到4/5千),可以忽略此条。 

除以上已知配置可能会影响压力机性能瓶颈以外,不排除其他影响压力机性能的因素,因此,在远程机器上,搭建一个mock程序,该程序什么都不做,直接返回成功。注意:mock程序部署机器物理配置最好能和压力机对等(对等时,至少部署两台),如果不能对等,部署多台,以排除部署机器的瓶颈; 

通过逐步增加线程数,观察平均响应时间和TPS,随着线程数的增加,TPS很难上升,平均响应时间明显增加的情况下,基本可以说明已经达到压力机的瓶颈,记下此时的线程数,在压测时,单台压力机最大线程数不宜超过该线程数,否则压测结果中,TPS和平均响应时间不准,压测结果不准确。

总结: 

STEP3很重要,因为在实践中,一台8核 64G内存的机器,单进程,最大的线程数超过10000时,被测服务(20台机器做实验)的压力很难再上去,因此STEP1只能说是排除那些可能成为瓶颈的机器配置,STEP2为避免踩已知的坑,STEP3才能确认压力机的单进程施压能力到底是多少;
 
目前还在学习中,希望会对大家有所帮助,觉得不错,就点赞支持一下。 另外,转载时请附带链接。谢谢!
原文地址:https://www.cnblogs.com/dangkai/p/9001173.html