




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第Go標(biāo)準(zhǔn)庫(kù)http與fasthttp服務(wù)端性能對(duì)比場(chǎng)景分析目錄1.背景2.性能測(cè)試3.對(duì)結(jié)果的簡(jiǎn)要分析4.優(yōu)化途徑
1.背景
Go初學(xué)者學(xué)習(xí)Go時(shí),在編寫了經(jīng)典的hello,world程序之后,可能會(huì)迫不及待的體驗(yàn)一下Go強(qiáng)大的標(biāo)準(zhǔn)庫(kù),比如:用幾行代碼寫一個(gè)像下面示例這樣擁有完整功能的webserver:
//來(lái)自/pkg/net/http/#example_ListenAndServe
packagemain
import(
"io"
"log"
"net/http"
funcmain(){
helloHandler:=func(whttp.ResponseWriter,req*http.Request){
io.WriteString(w,"Hello,world!\n")
http.HandleFunc("/hello",helloHandler)
log.Fatal(http.ListenAndServe(":8080",nil))
}
gonet/http包是一個(gè)比較均衡的通用實(shí)現(xiàn),能滿足大多數(shù)gopher90%以上場(chǎng)景的需要,并且具有如下優(yōu)點(diǎn):
標(biāo)準(zhǔn)庫(kù)包,無(wú)需引入任何第三方依賴;對(duì)http規(guī)范的滿足度較好;無(wú)需做任何優(yōu)化,即可獲得相對(duì)較高的性能;支持HTTP代理;支持HTTPS;無(wú)縫支持HTTP/2。
不過(guò)也正是因?yàn)閔ttp包的均衡通用實(shí)現(xiàn),在一些對(duì)性能要求嚴(yán)格的領(lǐng)域,net/http的性能可能無(wú)法勝任,也沒(méi)有太多的調(diào)優(yōu)空間。這時(shí)我們會(huì)將眼光轉(zhuǎn)移到其他第三方的http服務(wù)端框架實(shí)現(xiàn)上。
而在第三方http服務(wù)端框架中,一個(gè)行如其名的框架fasthttp被提及和采納的較多,fasthttp官網(wǎng)宣稱其性能是net/http的十倍(基于gotestbenchmark的測(cè)試結(jié)果)。
fasthttp采用了許多性能優(yōu)化上的最佳實(shí)踐,尤其是在內(nèi)存對(duì)象的重用上,大量使用sync.Pool以降低對(duì)GoGC的壓力。
那么在真實(shí)環(huán)境中,到底fasthttp能比net/http快多少呢?恰好手里有兩臺(tái)性能還不錯(cuò)的服務(wù)器可用,在本文中我們就在這個(gè)真實(shí)環(huán)境下看看他們的實(shí)際性能。
2.性能測(cè)試
我們分別用net/http和fasthttp實(shí)現(xiàn)兩個(gè)幾乎零業(yè)務(wù)的被測(cè)程序:
nethttp:
///bigwhite/experiments/blob/master/http-benchmark/nethttp/main.go
packagemain
import(
_"expvar"
"log"
"net/http"
_"net/http/pprof"
"runtime"
"time"
funcmain(){
gofunc(){
for{
log.Println("當(dāng)前routine數(shù)量:",runtime.NumGoroutine())
time.Sleep(time.Second)
http.Handle("/",http.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){
w.Write([]byte("Hello,Go!"))
log.Fatal(http.ListenAndServe(":8080",nil))
}
fasthttp:
///bigwhite/experiments/blob/master/http-benchmark/fasthttp/main.go
packagemain
import(
"fmt"
"log"
"net/http"
"runtime"
"time"
_"expvar"
_"net/http/pprof"
"/valyala/fasthttp"
typeHelloGoHandlerstruct{
funcfastHTTPHandler(ctx*fasthttp.RequestCtx){
fmt.Fprintln(ctx,"Hello,Go!")
funcmain(){
gofunc(){
http.ListenAndServe(":6060",nil)
gofunc(){
for{
log.Println("當(dāng)前routine數(shù)量:",runtime.NumGoroutine())
time.Sleep(time.Second)
s:=fasthttp.Server{
Handler:fastHTTPHandler,
s.ListenAndServe(":8081")
}
對(duì)被測(cè)目標(biāo)實(shí)施壓力測(cè)試的客戶端,我們基于hey這個(gè)http壓測(cè)工具進(jìn)行,為了方便調(diào)整壓力水平,我們將hey包裹在下面這個(gè)shell腳本中(僅適于在linux上運(yùn)行):
///bigwhite/experiments/blob/master/http-benchmark/client/http_client_load.sh
#./http_client_load.sh31000010GET81:8080
echo"$0task_numcount_per_heyconn_per_heymethodurl"
task_num=$1
count_per_hey=$2
conn_per_hey=$3
method=$4
url=$5
start=$(date+%s%N)
for((i=1;i=$task_num;i++));do{
tm=$(date+%T.%N)
echo"$tm:task$istart"
hey-n$count_per_hey-c$conn_per_hey-m$method$urlhey_$i.log
tm=$(date+%T.%N)
echo"$tm:task$idone"
}done
end=$(date+%s%N)
count=$(($task_num*$count_per_hey))
runtime_ns=$(($end-$start))
runtime=`echo"scale=2;$runtime_ns/1000000000"|bc`
echo"runtime:"$runtime
speed=`echo"scale=2;$count/$runtime"|bc`
echo"speed:"$speed
該腳本的執(zhí)行示例如下:
bashhttp_client_load.sh81000000200GET34:8080
http_client_load.shtask_numcount_per_heyconn_per_heymethodurl
16:58:09.146948690:task1start
16:58:09.147235080:task2start
16:58:09.147290430:task3start
16:58:09.147740230:task4start
16:58:09.147896010:task5start
16:58:09.148314900:task6start
16:58:09.148446030:task7start
16:58:09.148930840:task8start
16:58:45.001080740:task3done
16:58:45.241903500:task8done
16:58:45.261501940:task1done
16:58:50.032383770:task4done
16:58:50.985076450:task7done
16:58:51.269099430:task5done
16:58:52.008164010:task6done
16:58:52.166402430:task2done
runtime:43.02
speed:185960.01
從傳入的參數(shù)來(lái)看,該腳本并行啟動(dòng)了8個(gè)task(一個(gè)task啟動(dòng)一個(gè)hey),每個(gè)task向34:8080建立200個(gè)并發(fā)連接,并發(fā)送100whttpGET請(qǐng)求。
我們使用兩臺(tái)服務(wù)器分別放置被測(cè)目標(biāo)程序和壓力工具腳本:
目標(biāo)程序所在服務(wù)器:81(物理機(jī),Intelx86-64CPU,40核,128G內(nèi)存,CentOs7.6)
$cat/etc/redhat-release
CentOSLinuxrelease7.6.1810(Core)
$lscpu
Architecture:x86_64
CPUop-mode(s):32-bit,64-bit
ByteOrder:LittleEndian
CPU(s):40
On-lineCPU(s)list:0-39
Thread(s)percore:2
Core(s)persocket:10
NUMA節(jié)點(diǎn):2
廠商ID:GenuineIntel
CPU系列:6
型號(hào):85
型號(hào)名稱:Intel(R)Xeon(R)Silver4114CPU@2.20GHz
步進(jìn):4
CPUMHz:800.000
CPUmaxMHz:2201.0000
CPUminMHz:800.0000
BogoMIPS:4400.00
虛擬化:VT-x
L1d緩存:32K
L1i緩存:32K
L2緩存:1024K
L3緩存:14080K
NUMA節(jié)點(diǎn)0CPU:0-9,20-29
NUMA節(jié)點(diǎn)1CPU:10-19,30-39
Flags:fpuvmedepsetscmsrpaemcecx8apicsepmtrrpgemcacmovpatpse36clflushdtsacpimmxfxsrssesse2sshttmpbesyscallnxpdpe1gbrdtscplmconstant_tscartarch_perfmonpebsbtsrep_goodnoplxtopologynonstop_tscaperfmperfeagerfpupnipclmulqdqdtes64ds_cplvmxsmxesttm2ssse3sdbgfmacx16xtprpdcmpciddcasse4_1sse4_2x2apicmovbepopcnttsc_deadline_timeraesxsaveavxf16crdrandlahf_lmabm3dnowprefetchepbcat_l3cdp_l3intel_ptssbdmbaibrsibpbstibptpr_shadowvnmiflexpriorityeptvpidfsgsbasetsc_adjustbmi1hleavx2smepbmi2ermsinvpcidrtmcqmmpxrdt_aavx512favx512dqrdseedadxsmapclflushoptclwbavx512cdavx512bwavx512vlxsaveoptxsavecxgetbv1cqm_llccqm_occup_llccqm_mbm_totalcqm_mbm_localdthermidaaratplnptspkuospkespec_ctrlintel_stibpflush_l1d
壓力工具所在服務(wù)器:33(物理機(jī),鯤鵬arm64cpu,96核,80G內(nèi)存,CentOs7.9)
#cat/etc/redhat-release
CentOSLinuxrelease7.9.2009(AltArch)
#lscpu
Architecture:aarch64
ByteOrder:LittleEndian
CPU(s):96
On-lineCPU(s)list:0-95
Thread(s)percore:1
Core(s)persocket:48
NUMA節(jié)點(diǎn):4
型號(hào):0
CPUmaxMHz:2600.0000
CPUminMHz:200.0000
BogoMIPS:200.00
L1d緩存:64K
L1i緩存:64K
L2緩存:512K
L3緩存:49152K
NUMA節(jié)點(diǎn)0CPU:0-23
NUMA節(jié)點(diǎn)1CPU:24-47
NUMA節(jié)點(diǎn)2CPU:48-71
NUMA節(jié)點(diǎn)3CPU:72-95
Flags:fpasimdevtstrmaespmullsha1sha2crc32atomicsfphpasimdhpcpuidasimdrdmjscvtfcmadcpopasimddpasimdfhm
我用dstat監(jiān)控被測(cè)目標(biāo)所在主機(jī)資源占用情況(dstat-tcdngym),尤其是cpu負(fù)荷;通過(guò)[expvarmon監(jiān)控memstats],由于沒(méi)有業(yè)務(wù),內(nèi)存占用很少;通過(guò)gotoolpprof查看目標(biāo)程序中對(duì)各類資源消耗情況的排名。
下面是多次測(cè)試后制作的一個(gè)數(shù)據(jù)表格:
圖:測(cè)試數(shù)據(jù)
3.對(duì)結(jié)果的簡(jiǎn)要分析
受特定場(chǎng)景、測(cè)試工具及腳本精確性以及壓力測(cè)試環(huán)境的影響,上面的測(cè)試結(jié)果有一定局限,但卻真實(shí)反映了被測(cè)目標(biāo)的性能趨勢(shì)。我們看到在給予同樣壓力的情況下,fasthttp并沒(méi)有10倍于nethttp的性能,甚至在這樣一個(gè)特定的場(chǎng)景下,兩倍于net/http的性能都沒(méi)有達(dá)到:我們看到在目標(biāo)主機(jī)cpu資源消耗接近70%的幾個(gè)用例中,fasthttp的性能僅比net/http高出30%~70%左右。
那么為什么fasthttp的性能未及預(yù)期呢?要回答這個(gè)問(wèn)題,那就要看看net/http和fasthttp各自的實(shí)現(xiàn)原理了!我們先來(lái)看看net/http的工作原理示意圖:
圖:nethttp工作原理示意圖
http包作為server端的原理很簡(jiǎn)單,那就是accept到一個(gè)連接(conn)之后,將這個(gè)conn甩給一個(gè)workergoroutine去處理,后者一直存在,直到該conn的生命周期結(jié)束:即連接關(guān)閉。
下面是fasthttp的工作原理示意圖:
圖:fasthttp工作原理示意圖
而fasthttp設(shè)計(jì)了一套機(jī)制,目的是盡量復(fù)用goroutine,而不是每次都創(chuàng)建新的goroutine。fasthttp的Serveraccept一個(gè)conn之后,會(huì)嘗試從workerpool中的ready切片中取出一個(gè)channel,該channel與某個(gè)workergoroutine一一對(duì)應(yīng)。一旦取出channel,就會(huì)將accept到的conn寫到該channel里,而channel另一端的workergoroutine就會(huì)處理該conn上的數(shù)據(jù)讀寫。當(dāng)處理完該conn后,該workergoroutine不會(huì)退出,而是會(huì)將自己對(duì)應(yīng)的那個(gè)channel重新放回workerpool中的ready切片中,等待這下一次被取出。
fasthttp的goroutine復(fù)用策略初衷很好,但在這里的測(cè)試場(chǎng)景下效果不明顯,從測(cè)試結(jié)果便可看得出來(lái),在相同的客戶端并發(fā)和壓力下,net/http使用的goroutine數(shù)量與fasthttp相差無(wú)幾。這是由測(cè)試模型導(dǎo)致的:在我們這個(gè)測(cè)試中,每個(gè)task中的hey都會(huì)向被測(cè)目標(biāo)發(fā)起固定數(shù)量的[長(zhǎng)連接(keep-alive)],然后在每條連接上發(fā)起飽和請(qǐng)求。這樣fasthttpworkerpool中的goroutine一旦接收到某個(gè)conn就只能在該conn上的通訊結(jié)束后才能重新放回,而該conn直到測(cè)試結(jié)束才會(huì)close,因此這樣的場(chǎng)景相當(dāng)于讓fasthttp退化成了net/http的模型,也染上了net/http的缺陷:goroutine的數(shù)量一旦多起來(lái),goruntime自身調(diào)度所帶來(lái)的消耗便不可忽視甚至超過(guò)了業(yè)務(wù)處理所消耗的資源占比。下面分別是fasthttp在200長(zhǎng)連接、8000長(zhǎng)連接以及16000長(zhǎng)連接下的cpuprofile的結(jié)果:
200長(zhǎng)連接:
(pprof)top-cum
Showingnodesaccountingfor88.17s,55.35%of159.30stotal
Dropped150nodes(cum=0.80s)
Showingtop10nodesoutof60
flatflat%sum%cumcum%
0.46s0.29%0.29%101.46s63.69%/valyala/fasthttp.(*Server).serveConn
00%0.29%101.46s63.69%/valyala/fasthttp.(*workerPool).getCh.func1
00%0.29%101.46s63.69%/valyala/fasthttp.(*workerPool).workerFunc
0.04s0.025%0.31%89.46s56.16%internal/poll.ignoringEINTRIO(inline)
87.38s54.85%55.17%89.27s56.04%syscall.Syscall
0.12s0.075%55.24%60.39s37.91%bufio.(*Writer).Flush
00%55.24%60.22s37.80%net.(*conn).Write
0.08s0.05%55.29%60.21s37.80%net.(*netFD).Write
0.09s0.056%55.35%60.12s37.74%internal/poll.(*FD).Write
00%55.35%59.86s37.58%syscall.Write(inline)
(pprof)
8000長(zhǎng)連接:
(pprof)top-cum
Showingnodesaccountingfor108.51s,54.46%of199.23stotal
Dropped204nodes(cum=1s)
Showingtop10nodesoutof66
flatflat%sum%cumcum%
00%0%119.11s59.79%/valyala/fasthttp.(*workerPool).getCh.func1
00%0%119.11s59.79%/valyala/fasthttp.(*workerPool).workerFunc
0.69s0.35%0.35%119.05s59.76%/valyala/fasthttp.(*Server).serveConn
0.04s0.02%0.37%104.22s52.31%internal/poll.ignoringEINTRIO(inline)
101.58s50.99%51.35%103.95s52.18%syscall.Syscall
0.10s0.05%51.40%79.95s40.13%runtime.mcall
0.06s0.03%51.43%79.85s40.08%runtime.park_m
0.23s0.12%51.55%79.30s39.80%runtime.schedule
5.67s2.85%54.39%77.47s38.88%runtime.findrunnable
0.14s0.07%54.46%68.96s34.61%bufio.(*Writer).Flush
16000長(zhǎng)連接:
(pprof)top-cum
Showingnodesaccountingfor239.60s,87.07%of275.17stotal
Dropped190nodes(cum=1.38s)
Showingtop10nodesoutof46
flatflat%sum%cumcum%
0.04s0.015%0.015%153.38s55.74%runtime.mcall
0.01s0.0036%0.018%153.34s55.73%runtime.park_m
0.12s0.044%0.062%153s55.60%runtime.schedule
0.66s0.24%0.3%152.66s55.48%runtime.findrunnable
0.15s0.055%0.36%127.53s46.35%poll
127.04s46.17%46.52%127.04s46.17%runtime.epollwait
00%46.52%121s43.97%/valyala/fasthttp.(*workerPool).getCh.func1
00%46.52%121s43.97%/valyala/fasthttp.(*workerPool).worker
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 健康線上教程課件下載網(wǎng)
- 國(guó)一花木蘭數(shù)學(xué)試卷
- 2025年中國(guó)煉膠機(jī)械行業(yè)市場(chǎng)深度分析及發(fā)展趨勢(shì)預(yù)測(cè)報(bào)告
- 2021-2026年中國(guó)轉(zhuǎn)基因農(nóng)業(yè)市場(chǎng)供需現(xiàn)狀及投資戰(zhàn)略研究報(bào)告
- 2024-2030全球水源熱工業(yè)熱泵行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- “以竹代塑”主要產(chǎn)品名錄(2025年版)
- 醫(yī)院醫(yī)保政策解讀課件
- 綠色轉(zhuǎn)型觀察|中國(guó)基礎(chǔ)設(shè)施公募在可再生能源領(lǐng)域進(jìn)展研究 2025
- 營(yíng)口市公共場(chǎng)所管理辦法
- 藍(lán)天救援隊(duì)車牌管理辦法
- 中藥濕敷技術(shù)
- 2023年上海市教師招聘考試《教育心理學(xué)》考前模擬題及答案
- DLT-969-2023年變電站運(yùn)行導(dǎo)則
- ZAPI交流故障表 薩牌代碼
- 《健康經(jīng)濟(jì)學(xué)》課件Chapter16
- 兒童用藥劑量
- 2023年感動(dòng)中國(guó)十大人物頒獎(jiǎng)詞-范文匯編
- 人教版高中化學(xué)必修1教師用書
- 四員一長(zhǎng)抽考題庫(kù)
- 魯班獎(jiǎng)大型游樂(lè)場(chǎng)施工組織設(shè)計(jì)
- 牛津譯林版小學(xué)英語(yǔ)二年級(jí)下冊(cè)同步練習(xí)試題(全冊(cè))
評(píng)論
0/150
提交評(píng)論