讲个故事,告诉你网络性能瓶颈分析

本贴最后更新于 1410 天前,其中的信息可能已经时移世异

讲个故事,告诉你网络性能瓶颈分析

在性能测试中,谈到网络问题,其实,在没有特别说明的情况下,我们一般讲的都是HTTP协议下的网络瓶颈问题,那,对于这个问题,我们如何来分析呢?
计算机中的网络,跟我们现实生活中的交通网络,其实也是一个道理,可以类比。你从住的地方,到你公司上班,人的位置,在整个过程中发生了移动,就相当于我们网络中一个数据包进行了传输,我们可以这样类比,来剖析下这个移动过程:

现在,我们知道了影响我们上班是否迟会到的瓶颈了,其实,在我们网络性能分析中,也是类似的。用HTTP协议来规范网络通信,用TCP\UDP进行数据传输,它就是我们上班的交通工具。

TCP连接有四个组成元件,源地址、源端口、目的地址、目的端口。源地址,就是你自己机器的ip,相当于你住的地址,一般都是唯一的;源端口,就是发起通信的端口,就是你从家里出来的门,你发起一次通信,就会要先找一个端口,打开端口,从端口出去,然后关闭端口。这个过程,作为常规的使用,完全没有问题,所以平常大家都不关注这个。但是,端口是很多,也耐不住你使劲的‘造’啊(就像你家很豪华,门再多,也耐不住你浪费啊。)在我们性能测试时,就是使劲的‘造’,会打开大量的端口,处于占用状态,没有获得到端口的就出不去,从而就可能出现,端口不够用的情况。

ok,现在明白网络性能的第一个可能的瓶颈是什么了吧!端口不够用!!

一、源地址端口不够用

大家在公司日常用的更多的电脑就是Windows,那windows的电脑端口有多少呢?这个要说原理和理论,估计很多同学就会蒙圈了,所以就不大谈理论了。

看了这样一组数据,知道在做性能测试时,你本机TCP通信最多能消耗多少个端口了吗?

—— 65535

—— 16384

哈哈,都不对。

实际上,一台电脑TCP通信端口应该是在16400+ 个,当然也不会超过太多。为什么不是16384,而是这样一个值呢?

因为‘注册端口’中有部分端口,也会用于tcp通信。所以在性能测试时,最大可用端口范围会稍微大一点。

看到这,是不是就特别想知道怎么查看Windows系统中,TCP端口连接占用情况呢?

那,接下来就给大家讲解一个非常简单的命令:

Windows系统查看当前TCP连接数

netstat -ano | find "TCP" /i /c

# netstat 显示协议统计信息和当前TCP/IP网络连接情况
# -a	显示所有连接和侦听端口
# -n	以数字形式显示地址和端口号
# -o	显示拥有的与每个连接关联的进程ID

# /i	指定搜索不区分大小写
# /c	对包含指定的信息进行计数,并显示总计

linux呢?是你的菜吗?

netstat -ano |grep 'tcp' | wc -l这个知道吗?

好,现在已经知道如何实时查看了,那实际执行性能测试,如果出现源地址端口不够用,会出现什么样的问题表现呢?

Address already in use: connect

java.net.BindException: Address already in use: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)
at ......

对于这样的错,你见过吗?

相信只要做过性能测试的人员,或多或少都遇到过吧!

虽然出现Address already in use: connect这个问题,原因很多,但源地址端口不够用,就是其中一个常见的原因。

我们可以尝试如下方法调优:

第一个调优办法

如果是使用jmeter进行性能测试,出现上述报错,可以直接去掉http取样器的 【使用 KeepAlive】 复选勾。

第二个调优办法:

完成这一步,我们已经知道,我们的系统当前端口可用范围已经达到最大。

接下来,我们还需要知道,端口被使用后,如果我们能及时回收,再利用是不是能提高端口利用率,这样是不是就变相增加了端口了呢?

所以,第二个调优方法就是,释放、回收端口。

第三个调优办法

完成了这两步,我们就已经完成了发送方的网络调优。


现在,我们已经知道如何解决从家里出来可能的问题了,接下来,就是开车,去上班。
把车开出来,先经过一段引路,然后才能进入主干道,主干道通行一段距离后,下主干道,进入一段公司引路,再进入公司。

对吧!

其实,我们的网络数据传输,也可以这样类比,网络数据包要通过网卡,使用网络传输介质(如网线)在网络中进行传输,进过多次周转,找到目标服务器,通过服务器网卡,进入服务器内部。

同样的,我们能分析出:

有这么多可能的瓶颈,哪我们怎么判定网络传输有没有问题呢?这个相信大家都知道怎么做。

c:\>ping ke.qq.com

正在 Ping ke.qq.com [101.89.15.159] 具有 32 字节的数据:
来自 101.89.15.159 的回复: 字节=32 时间=22ms TTL=54
来自 101.89.15.159 的回复: 字节=32 时间=23ms TTL=54
来自 101.89.15.159 的回复: 字节=32 时间=22ms TTL=54
来自 101.89.15.159 的回复: 字节=32 时间=23ms TTL=54

101.89.15.159 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失)往返行程的估计时间(以毫秒为单位):
最短 = 22ms,最长 = 23ms,平均 = 22ms

通过ping对方的域名或ip,在性能测试同时,网络传输时延以及丢包情况。丢包或时延比较严重,那么说明网络已经阻塞,需要做上述瓶颈分析;如果没有丢包,时延也很低,说明网络比较正常。

二、网络传输通道瓶颈

Ⅰ、查看发起请求的机器网卡速率。如果是Windows10电脑,可以在 “网络连接” > 选中机器网卡,右键‘状态’ > 查看弹窗中的‘速度’

localhostnetwork.gif

Ⅱ、 检查网络传输路由,Windows下执行:

c:>tracert -d ke.qq.com
通过最多 30 个跃点跟踪
到 ke.qq.com [101.89.15.159] 的路由:

1    <1 毫秒   <1 毫秒   <1 毫秒 192.168.1.1
2     1 ms     1 ms     1 ms  175.8.48.1
3     5 ms     5 ms     5 ms  61.187.3.33
4     *        *        *     请求超时。
5    23 ms    23 ms    24 ms  202.97.19.141
6    24 ms    24 ms    24 ms  101.95.88.77
7     *        *        *     请求超时。
8     *        *        *     请求超时。
9     *        *        *     请求超时。
10     *        *        *     请求超时。
11     *        *        *     请求超时。
12    22 ms    22 ms    22 ms  101.89.15.159

跟踪完成。第1列,表示路由节点数量;第2~4列,表示连接到每个路由节点的速度、返回速度、多次连接反馈的平均值;最后的ip,代表路由地址。

从这个就能看出在哪个节点时间长,可能有优化空间。

Ⅲ、数据传输到服务器了,现在要查看服务器的网卡信息。

[root@localhost ~]# ethtool ens33 | grep "Speed"
Speed: 100Mb/s

# ens33 为网卡名称

通过这个命令,我们可以看到ens33这个网卡,目前设置的速度为100Mb/s,这个已经非常大了,如果这个值过低,可能就需要改大,可以执行:

ethtool -s ens33 speed 1000
# 将网卡的速度设置为 1000Mb/s

好了,现在我们知道如何查看确认我们数据传输通道的问题了。

显然,我们对于这个环节出现瓶颈,办法不是很多。就像我们上班的路,我们能在引路上想些办法,规划好行车路线,但是我们对于主干道,几乎无能为力。


好了,现在网络数据包,已经到达服务器了。服务器,现在一般情况下,都是linux为主。所以,接下来,就要看linux中可能的瓶颈了

三、目的地址端口瓶颈

sj.png

这张图,是不是完全没有看懂什么意思?

其实我们的请求在服务器上,就是类似图片这样,非常多的请求来到服务器,最后都是通过某个端口,或者几个端口真正获取响应数据。

首先,我们得知道,一台机器,再强,也只能接收一定量的请求,这个数量是有最大值的,我们可以通过:

linux机器上查看允许的连接配置

[root@localhost ~]# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7197
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7197
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

如果觉得这个配置的‘max user process' 和 'open files'太小,可以修改 /etc/security/limits.conf

[root@localhost ~]# vim /etc/security/limits.conf

# 添加如下

your_account soft    nproc           32768

your_account hard    nproc           32768

root         soft    nproc           32768

root         hard    nproc           32768

your_account soft    nofile          16000

your_account hard    nofile          16000

root         soft    nofile          16000

root         hard    nofile          16000

修改完后, max user processes 就会改成32768, open files 值变更为 16000

做完这波操作,就相当于你对公司的入口门进行了设置,根据你的需要调整了门的宽度。

接下来,就是要进入你的办公室了。

四、服务内部端口瓶颈

首先我们可以查看下你当前服务的端口连接数量:

netstat -ane |grep '端口' | grep ESTABLISHED |wc -l

这个命令执行完后,你会获得一个数值,这个数量到达一定的峰值之后,就不会再增长了,当你测试结束的时候,这个峰值就会逐步降低。

这是怎么回事呢?

其实,这就是我们服务的连接数量,而这个数量,是可以配置的。

如果你的服务是tomat,可以在tomcat的conten.xml中,配置

<Executor name="tomcatThreadPool" namePrefix ="catalina-exec-" 
maxThreads="150" minSpareThreads="4" />
<Connector executor="tomcatThreadPool" port="8080" 
protocol="HTTP/1.1" connectionTimeout="20000" 
redirectPort="8443" acceptCount="1000" />

<!---
name:该线程池的标记
maxThreads:线程池中最大活跃线程数,默认值200(Tomcat7和8都是)
minSpareThreads:线程池中保持的最小线程数,最小值是25
maxIdleTime:线程空闲的最大时间,当空闲超过该值时关闭线程
(除非线程数小于minSpareThreads),单位是ms,默认值60000(1分钟)
daemon:是否后台线程,默认值true
threadPriority:线程优先级,默认值5
namePrefix:线程名字的前缀,线程池中线程名字为:namePrefix+线程编号
    --->

修改maxThreads的值,就是在修改我们的最大峰值。

注意,maxThreads 不是无限大的, 越大,相应的消耗的资源也会越多。

好了,这就是我们常常进行网络性能瓶颈分析的几个方面。你是不是都已经掌握了呢?

6 操作
Allen 在 2021-01-05 14:23:19 更新了该帖
Allen 在 2020-08-26 19:43:43 更新了该帖
Allen 在 2020-08-19 14:35:05 更新了该帖
Allen 在 2020-08-19 14:32:12 更新了该帖 Allen 在 2020-08-19 14:31:08 更新了该帖 Allen 在 2020-08-19 14:28:16 更新了该帖
回帖
请输入回帖内容 ...