上面這張圖是應(yīng)用其他人的關(guān)于并發(fā)用戶(hù)數(shù),QPS,用戶(hù)平均等待時(shí)間的一張關(guān)系圖,對(duì)于實(shí)際的系統(tǒng),也應(yīng)該是對(duì)于不同的并發(fā)數(shù),進(jìn)行多次測(cè)試,獲取到這些數(shù)值后,畫(huà)出這樣一張圖出來(lái),以便于分析出系統(tǒng)的最佳并發(fā)用戶(hù)數(shù)。
===============================================
最佳線(xiàn)程數(shù):
性能壓測(cè)的情況下,起初隨著用戶(hù)數(shù)的增加,QPS會(huì)上升,當(dāng)?shù)搅艘欢ǖ拈y值之后,用戶(hù)數(shù)量增加QPS并不會(huì)增加,或者增加不明顯,同時(shí)請(qǐng)求的響應(yīng)時(shí)間卻大幅增加。這個(gè)閥值我們認(rèn)為是最佳線(xiàn)程數(shù)。
為什么要找最佳線(xiàn)程數(shù)
1.過(guò)多的線(xiàn)程只會(huì)造成,更多的內(nèi)存開(kāi)銷(xiāo),更多的CPU開(kāi)銷(xiāo),但是對(duì)提升QPS確毫無(wú)幫助
2.找到最佳線(xiàn)程數(shù)后通過(guò)簡(jiǎn)單的設(shè)置,可以讓web系統(tǒng)更加穩(wěn)定,得到最高,最穩(wěn)定的QPS輸出
最佳線(xiàn)程數(shù)的獲。
1、通過(guò)用戶(hù)慢慢遞增來(lái)進(jìn)行性能壓測(cè),觀察QPS,響應(yīng)時(shí)間
2、根據(jù)公式計(jì)算:服務(wù)器端最佳線(xiàn)程數(shù)量=((線(xiàn)程等待時(shí)間+線(xiàn)程cpu時(shí)間)/線(xiàn)程cpu時(shí)間) * cpu數(shù)量
3、單用戶(hù)壓測(cè),查看CPU的消耗,然后直接乘以百分比,再進(jìn)行壓測(cè),一般這個(gè)值的附近應(yīng)該就是最佳線(xiàn)程數(shù)量。
影響最佳線(xiàn)程數(shù)的主要因素:
1、IO
2、CPU
根據(jù)公式:服務(wù)器端最佳線(xiàn)程數(shù)量=((線(xiàn)程等待時(shí)間+線(xiàn)程cpu時(shí)間)/線(xiàn)程cpu時(shí)間) * cpu數(shù)量
一般來(lái)說(shuō)是IO和CPU。IO開(kāi)銷(xiāo)較多的應(yīng)用其CPU線(xiàn)程等待時(shí)間會(huì)比較長(zhǎng),所以線(xiàn)程數(shù)量可以開(kāi)的多一些,相反則線(xiàn)程數(shù)量要少一些,其實(shí)有兩種極端,純IO的應(yīng)用,比如proxy,則線(xiàn)程數(shù)量可以開(kāi)到非常大(實(shí)在太大了則需要考慮線(xiàn)程切換的開(kāi)銷(xiāo)),這種應(yīng)用基本上后端(比如這個(gè)proxy是代理搜索的)的QPS能有多少,proxy就有多少。
另一種是耗CPU的計(jì)算,這種情況一般來(lái)講只能開(kāi)到CPU個(gè)數(shù)的線(xiàn)程數(shù)量。但是并不是說(shuō)這種應(yīng)用的QPS就不高,往往這種應(yīng)用的QPS可以很高。
QPS和線(xiàn)程數(shù)的關(guān)系
1、在最佳線(xiàn)程數(shù)量之前,QPS和線(xiàn)程是互相遞增的關(guān)系,線(xiàn)程數(shù)量到了最佳線(xiàn)程之后,QPS持平,不在上升,甚至略有下降,同時(shí)相應(yīng)時(shí)間持續(xù)上升。
2、同一個(gè)系統(tǒng)而言,支持的線(xiàn)程數(shù)越多(最佳線(xiàn)程數(shù)越多而不是配置的線(xiàn)程數(shù)越多),QPS越高
QPS和響應(yīng)時(shí)間的關(guān)系
1、對(duì)于一般的web系統(tǒng),響應(yīng)時(shí)間一般有CPU執(zhí)行時(shí)間+IO等待時(shí)間組成
2、CPU的執(zhí)行時(shí)間減少,對(duì)QPS有實(shí)質(zhì)的提升,IO時(shí)間的減少,對(duì)QPS提升不明顯。如果要想明顯提升QPS,優(yōu)化系統(tǒng)的時(shí)候要著重優(yōu)化CPU消耗大戶(hù)。
最佳線(xiàn)程數(shù)和jvm堆內(nèi)存得關(guān)系:
以上都是依據(jù)性能瓶頸在CPU的情況,對(duì)于java應(yīng)用還有一個(gè)因素是FULL GC,我們要保證在最佳線(xiàn)程數(shù)量下,不會(huì)發(fā)生頻繁FULL GC
根據(jù)公式::(小GC時(shí)間間隔/rt)*(并發(fā)線(xiàn)程數(shù)量 * thm) <=young 計(jì)算得到的并發(fā)線(xiàn)程數(shù)量如果<最佳線(xiàn)程數(shù)量 則可能導(dǎo)致FULL GC較頻繁,實(shí)際情況看來(lái)這種情況在web系統(tǒng)上非常少。不過(guò)可以模擬出來(lái)。
所以我們?cè)谠O(shè)置jboss線(xiàn)程的時(shí)候,可以利用內(nèi)存公式計(jì)算出來(lái)的線(xiàn)程數(shù)量來(lái)設(shè)置,通過(guò)壓測(cè)和計(jì)算得到最佳線(xiàn)程數(shù),然后設(shè)置線(xiàn)程數(shù)。
設(shè)置線(xiàn)程數(shù)量:
壓測(cè)最佳線(xiàn)程數(shù)<真實(shí)設(shè)置的線(xiàn)程數(shù)量<內(nèi)存極限線(xiàn)程數(shù)
比如,通過(guò)壓測(cè)得到某系統(tǒng)的最佳線(xiàn)程數(shù)量是10,然后通過(guò)內(nèi)存計(jì)算的線(xiàn)程數(shù)量是20,則,設(shè)置jboss的線(xiàn)程數(shù)量為15是可行的,如果直接設(shè)置了10,由于系統(tǒng)本身會(huì)受到一些依賴(lài)系統(tǒng)的變化而產(chǎn)生一些變化,比如系統(tǒng)依賴(lài)一些IO的響應(yīng)時(shí)間會(huì)突然延長(zhǎng),由于線(xiàn)程數(shù)量還是10,其實(shí)這個(gè)時(shí)候最佳線(xiàn)程數(shù)量已經(jīng)變成了13了,由于我們?cè)O(shè)置死了10,其結(jié)果就是導(dǎo)致qps下降,但是如果超過(guò)20,則又會(huì)引起FULL gc非常頻繁,反過(guò)來(lái)影響QPS的下降。
jboss的線(xiàn)程數(shù)設(shè)置:
對(duì)于jboss而言,設(shè)置線(xiàn)程數(shù)量要看使用了那種線(xiàn)程連接,如http、ajp等
http和ajp的設(shè)置是完全一樣的,非常簡(jiǎn)單:
以ajp為例,找到server.xml或者tomcat-server.xml:
默認(rèn)線(xiàn)程數(shù)量是200個(gè)
<Connector port="8009" address="${jboss.bind.address}" connectionTimeout="15000" protocol="AJP/1.3" maxThreads="200"
minSpareThreads="40" maxSpareThreads="75" maxPostSize="512000"
acceptCount="300" bufferSize="16384" emptySessionPath="false"
enableLookups="false" redirectPort="8443"
useBodyEncodingForURI="true"/>
這里將默認(rèn)的線(xiàn)程數(shù)量改成了20,當(dāng)然相應(yīng)的其他最小空閑線(xiàn)程數(shù)和最大空閑線(xiàn)程數(shù)也做一下調(diào)整:
<Connector port="8009" address="${jboss.bind.address}" connectionTimeout="15000" protocol="AJP/1.3" maxThreads="20"
minSpareThreads="20" maxSpareThreads="20" maxPostSize="512000"
acceptCount="300" bufferSize="16384" emptySessionPath="false"
enableLookups="false" redirectPort="8443"
useBodyEncodingForURI="true"/>