一、引出問題點:
在做性能測試中,談到網絡問題時,其實,在沒有特別說明的情況下,我們一般講的都是HTTP協議下的網絡瓶頸問題,那么對于這個問題,我們如何來分析呢?
舉例說明:
計算機中的網絡,跟我們現實生活中的交通網絡,其實也是一個道理,可以類比。
例如:你從住的地方,到你公司上班,人的位置,在整個過程中發生了移動,就相當于我們網絡中一個數據包進行了傳輸,我們可以這樣類比,來剖析下這個移動過程:
首先,住的地方是已知的,住的很豪華,有非常多的門,你要去上班,從任意一個門出來都可以,但是門再多,它也是有一定數量的。
從門出來,你就會想,用什么樣的交通工具,如果使用4個輪子的車子,那接下來就會選擇道路,因為不同的道路,擁堵情況可能不一樣。
現在,你開車到了公司樓下,你又會選擇從哪個門進公司。如果時間緊,人又多,一窩蜂都擠到一個門,你小身板,可能就擠不進去,所以你可能會挑一個足夠寬讓你進去的門。
接下來,我們根據這個過程,分析下,影響我們上班過程的瓶頸有哪些?
門很多,但是總有個數量,萬一門不夠,是不是就出不去了?所以,這個出口門,可能會是個瓶頸。
交通工具和道路。不同的交通工具,速度不一樣;道路等級、寬窄、流通量都會影響通行速度,都可能是瓶頸。
公司入口門,如果大家都在同一時間點從門口進來,是不是就會要排隊,或者進不來,那這個入口門,也可能會是瓶頸。
進入公司后,要進入辦公室,辦公室的門寬度,是不是也可能是個瓶頸。
總結:現在,我們知道了影響我們上班是否遲會到的瓶頸了,其實,在我們網絡性能分析中,也是類似的。用HTTP協議來規范網絡通信,用TCP\UDP進行數據傳輸,它就是我們上班的交通工具。
TCP連接有四個組成元件:源地址、源端口、目的地址、目的端口。
。1)源地址:就是你自己機器的ip,相當于你住的地址,一般都是唯一的;
。2)源端口:就是發起通信的端口,就是你從家里出來的門,你發起一次通信,就會要先找一個端口,打開端口,從端口出去,然后關閉端口。
。3)目的地址:這個過程,作為常規的使用,完全沒有問題,所以平常大家都不關注這個。
。4)目的端口:但是,端口是很多,也耐不住你使勁的‘造’。ň拖衲慵液芎廊A,門再多,也耐不住你浪費啊。)
總結:在我們性能測試時,就是使勁的‘造’,會打開大量的端口,處于占用狀態,沒有獲得到端口的就出不去,從而就可能出現,端口不夠用的情況。
即:現在明白網絡性能的第一個可能的瓶頸是什么了吧!--->端口不夠用。!
二、源地址端口不夠用
大家在公司日常用的更多的電腦就是Windows,那windows的電腦端口有多少呢?
我們可以先簡單理解為端口總共有65535個,其中:
·0~1023(共1024個),為公認端口,緊密的綁定在一些特定服務上,如21端口就是FTP服務,80端口就是HTTP服務;
· 1024~49151(共48127個),為注冊端口,松散的綁定于一些服務,如8080端口常常就用于綁定tomcat服務;
· 49152~65535(共16384個),為動態或私有端口。
。1)看了這樣一組數據,知道在做性能測試時,你本機TCP通信最多能消耗多少個端口了嗎?
即:實際上,一臺電腦TCP通信端口應該是在16400+個,當然也不會超過太多。
。2)為什么不是16384,而是這樣一個值呢?
即:因為‘注冊端口’中有部分端口,也會用于tcp通信。所以在性能測試時,最大可用端口范圍會稍微大一點。
看到這,是不是就特別想知道怎么查看Windows系統中,TCP端口連接占用情況呢?
Windows系統查看當前TCP連接數:
netstat-ano|find"TCP"/i/c
#netstat顯示協議統計信息和當前TCP/IP網絡連接情況
#-a顯示所有連接和偵聽端口
#-n以數字形式顯示地址和端口號
#-o顯示擁有的與每個連接關聯的進程ID
#/i指定搜索不區分大小寫
#/c對包含指定的信息進行計數,并顯示總計
Linux查看當前tcp連接數的方法
netstat-ano|grep'tcp'|wc-l
現在已經知道如何實時查看了,那實際執行性能測試,如果出現源地址端口不夠用,會出現什么樣的問題表現呢?
Addressalreadyinuse:connect
java.net.BindException:Addressalreadyinuse:connect
atjava.net.DualStackPlainSocketImpl.waitForConnect(NativeMethod)
atjava.net.DualStackPlainSocketImpl.socketConnect(UnknownSource)
atjava.net.AbstractPlainSocketImpl.doConnect(UnknownSource)
atjava.net.AbstractPlainSocketImpl.connectToAddress(UnknownSource)
atjava.net.AbstractPlainSocketImpl.connect(UnknownSource)
atjava.net.PlainSocketImpl.connect(UnknownSource)
atjava.net.SocksSocketImpl.connect(UnknownSource)
atjava.net.Socket.connect(UnknownSource)
atorg.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)
at......
雖然出現Addressalreadyinuse:connect這個問題,原因很多,但源地址端口不夠用,就是其中一個常見的原因。
我們可以嘗試如下方法調優:
方法一:
如果是使用jmeter進行性能測試,出現上述報錯,可以直接去掉http取樣器的【使用KeepAlive】復選勾。
方法二:
·打開系統的注冊表-->找到[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]-->
· 看下右側的配置信息-->有沒有MaxUserPort配置項,有-->則修改值為65534(十進制)-->確定
· 沒有-->則新增一個DWORD,name為MaxUserPort,value為65534(十進制)-->確定-->
· 重啟系統
可以參考地址:https://docs.microsoft.com/en-us/troubleshoot/windows-client/networking/connect-tcp-greater-than-5000-error-wsaenobufs-10055
完成這一步,我們已經知道,我們的系統當前端口可用范圍已經達到最大。
接下來,我們還需要知道,端口被使用后,如果我們能及時回收,再利用是不是能提高端口利用率,這樣是不是就變相增加了端口了呢?
所以,第二個調優方法就是,釋放、回收端口。
方法三:
·打開系統的注冊表-->找到[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]-->
· 看下右側的配置信息,有沒有TcpTimedWaitDelay配置項有-->則修改值為10(十進制,10秒)-->確定
· 沒有-->則新增一個DWORD,name為TcpTimedWaitDelay,value為30(十進制)-->確定
· 重啟系統
可以參考地址:https://docs.microsoft.com/en-us/troubleshoot/windows-client/networking/tcpip-and-nbt-configuration-parameters
完成了這兩步,我們就已經完成了發送方的網絡調優。
第二段分析:現在,我們已經知道如何解決從家里出來可能的問題了,接下來,就是開車,去上班。把車開出來,
先經過一段引路,然后才能進入主干道,主干道通行一段距離后,下主干道,進入一段公司引路,再進入公司
其實,我們的網絡數據傳輸,也可以這樣類比,網絡數據包要通過網卡,使用網絡傳輸介質(如網線)在網絡中進行傳輸,進過多次周轉,找到目標服務器,通過服務器網卡,進入服務器內部。
由此可以分析出:
·發送方的網卡速率有10m、百兆、G兆網卡,如果網卡不行,可能成為瓶頸。
· 傳輸介質,有線、無線,有線的介質(如雙絞線、同軸電纜、光纖)、路由的復雜度(如國內、國外)等等,都會影響傳輸速度,這個有可能成為瓶頸。
· 服務器接收數據的網卡速率,照樣也可能成為瓶頸
c:\>pingke.qq.com
正在Pingke.qq.com[101.89.15.159]具有32字節的數據:
來自101.89.15.159的回復:字節=32時間=22msTTL=54
來自101.89.15.159的回復:字節=32時間=23msTTL=54
來自101.89.15.159的回復:字節=32時間=22msTTL=54
來自101.89.15.159的回復:字節=32時間=23msTTL=54
101.89.15.159的Ping統計信息:
數據包:已發送=4,已接收=4,丟失=0(0%丟失),
往返行程的估計時間(以毫秒為單位):
最短=22ms,最長=23ms,平均=22ms
通過ping對方的域名或ip,在性能測試同時,網絡傳輸時延以及丟包情況。丟包或時延比較嚴重,那么說明網絡已經阻塞,需要做上述瓶頸分析;如果沒有丟包,時延也很低,說明網絡比較正常。
三、網絡傳輸通道瓶頸
、、查看發起請求的機器網卡速率。如果是Windows10電腦,可以在“網絡連接”>選中機器網卡,右鍵‘狀態’>查看彈窗中的‘速度’。
、、檢查網絡傳輸路由,Windows下執行:
c:\>tracert-dke.qq.com
通過最多30個躍點跟蹤
到ke.qq.com[101.89.15.159]的路由:
1<1毫秒<1毫秒<1毫秒192.168.1.1
21ms1ms1ms175.8.48.1
35ms5ms5ms61.187.3.33
4***請求超時。
523ms23ms24ms202.97.19.141
624ms24ms24ms101.95.88.77
7***請求超時。
8***請求超時。
9***請求超時。
10***請求超時。
11***請求超時。
1222ms22ms22ms101.89.15.159
跟蹤完成。
第1列,表示路由節點數量;
第2~4列,表示連接到每個路由節點的速度、返回速度、多次連接反饋的平均值;
最后的ip,代表路由地址。
從這個就能看出在哪個節點時間長,可能有優化空間。
、、數據傳輸到服務器了,現在要查看服務器的網卡信息。
[root@localhost~]#ethtoolens33|grep"Speed"
Speed:100Mb/s
#ens33為網卡名稱
通過這個命令,我們可以看到ens33這個網卡,目前設置的速度為100Mb/s,這個已經非常大了,如果這個值過低,可能就需要改大,可以執行:
ethtool-sens33speed1000
#將網卡的速度設置為1000Mb/s
現在我們知道如何查看確認我們數據傳輸通道的問題了。
顯然,我們對于這個環節出現瓶頸,辦法不是很多。就像我們上班的路,我們能在引路上想些辦法,規劃好行車路線,但是我們對于主干道,幾乎無能為力。
?好了,現在網絡數據包,已經到達服務器了。服務器,現在一般情況下,都是linux為主。所以,接下來,就要看linux中可能的瓶頸了。
四、目的地址端口瓶頸
其實我們的請求在服務器上,就是類似這樣,非常多的請求來到服務器,最后都是通過某個端口,或者幾個端口真正獲取響應數據。
首先,我們得知道,一臺機器,再強,也只能接收一定量的請求,這個數量是有最大值的,我們可以通過:
linux機器上查看允許的連接配置
[root@localhost~]#ulimit-a
corefilesize(blocks,-c)unlimited
datasegsize(kbytes,-d)unlimited
schedulingpriority(-e)0
filesize(blocks,-f)unlimited
pendingsignals(-i)7197
maxlockedmemory(kbytes,-l)16384
maxmemorysize(kbytes,-m)unlimited
openfiles(-n)65535
pipesize(512bytes,-p)8
POSIXmessagequeues(bytes,-q)819200
real-timepriority(-r)0
stacksize(kbytes,-s)8192
cputime(seconds,-t)unlimited
maxuserprocesses(-u)7197
virtualmemory(kbytes,-v)unlimited
filelocks(-x)unlimited
如果覺得這個配置的'maxuserprocess'和'openfiles'太小,可以修改/etc/security/limits.conf
[root@localhost~]#vim/etc/security/limits.conf
#添加如下
your_accountsoftnproc32768
your_accounthardnproc32768
rootsoftnproc32768
roothardnproc32768
your_accountsoftnofile16000
your_accounthardnofile16000
rootsoftnofile16000
roothardnofile16000
修改完后,maxuserprocesses就會改成32768,openfiles值變更為16000。
做完這波操作,就相當于你對公司的入口門進行了設置,根據你的需要調整了門的寬度。
五、服務器內部端口瓶頸
首先我們可以查看下你當前服務的端口連接數量:
netstat-ane|grep'端口'|grepESTABLISHED|wc-l
這個命令執行完后,你會獲得一個數值,這個數量到達一定的峰值之后,就不會再增長了,當你測試結束的時候,這個峰值就會逐步降低。
其實,這就是我們服務的連接數量,而這個數量,是可以配置的。
如果你的服務是tomat,可以在tomcat的conten.xml中,配置:
<Executorname="tomcatThreadPool"namePrefix="catalina-exec-"maxThreads="150"minSpareThreads="4"/>
<Connectorexecutor="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不是無限大的,越大-->相應的消耗的資源也會越多。
本文內容不用于商業目的,如涉及知識產權問題,請權利人聯系51Testing小編(021-64471599-8017),我們將立即處理