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