自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

超高性能管線式HTTP請求(實踐·原理·實現(xiàn))

網(wǎng)絡(luò) 通信技術(shù)
這里的高性能指的就是網(wǎng)卡有多快請求發(fā)送就能有多快,基本上一般的服務(wù)器在一臺客戶端的壓力下就會出現(xiàn)明顯延時。該篇實際是介紹pipe管線的原理,下面主要通過其高性能的測試實踐,解析背后數(shù)據(jù)流量及原理。最后附帶一個簡單的實現(xiàn)。

這里的高性能指的就是網(wǎng)卡有多快請求發(fā)送就能有多快,基本上一般的服務(wù)器在一臺客戶端的壓力下就會出現(xiàn)明顯延時。

該篇實際是介紹pipe管線的原理,下面主要通過其高性能的測試實踐,解析背后數(shù)據(jù)流量及原理。***附帶一個簡單的實現(xiàn)。

實踐

先直接看對比測試方法:

測試內(nèi)容單一客戶的使用盡可能快的方式向服務(wù)器發(fā)送一定量(10000條)請求,并接收返回數(shù)據(jù)。

對于單一客戶端對服務(wù)器進行http請求,一般我們的方式:

1:單進程或線程輪詢請求(這個效能自然很低,原因會講到,也不用測試)

2:多條線程提前準(zhǔn)備數(shù)據(jù)等待信號(對客戶端性能要求較高)

3:提前準(zhǔn)備一組線程同時輪詢操作

4:使用系統(tǒng)/平臺自帶異步發(fā)送機制(實際就是平臺線程池的方式,發(fā)送與接收使用從線程池中的不同線程)

對于測試方案1,及方案2測試中性能較低沒有可比性,后面測試不會展示其結(jié)果。

以下展示后面2種測試方法及當(dāng)前要說的管線式的方式:

  • 先講管線式(pipe)測試方案(原理在后面會講到),測試中使用100條管線(管道),實際上更少甚至一條管線也是能達到近似的性能,不過多數(shù)服務(wù)器nginx限制一條管可以持續(xù)發(fā)送request的數(shù)量(大部分是100也有部分會是200或是更高),每條管線發(fā)送100個請求。
  • 然后是線程組的方式準(zhǔn)備100條線程(100條線程并不是很多不會對系統(tǒng)本身有明顯影響),每條線程輪詢發(fā)送100個request。
  • 異步方式的方式,10000全部提交發(fā)送線程,由線程池控制接收。

測試環(huán)境:普通家用PC,i5 4核,12G ,100Mb電信帶寬。

測試數(shù)據(jù):

GET http://www.baidu.com HTTP/1.1

Content-Type: application/x-www-form-urlencoded

Host: www.baidu.com

Connection: Keep-Alive

這里就是測試最常用的baidu,如果測試接口性能不佳,大部分請求會在應(yīng)用服務(wù)器排隊,難以直觀提現(xiàn)pipe的優(yōu)勢(其實就是還沒有用到pipe的能力,服務(wù)器就先阻塞了)。

下文中所有關(guān)于pipe的測試都是使用PipeHttpRuner (http://www.cnblogs.com/lulianqi/p/8167843.html 為該測試工具的下載地址,使用方法及介紹)。

先直接看管道式的表現(xiàn):(截圖全部為windows自帶任務(wù)管理器及資源管理器)

先解釋下截圖含義,后面的截圖也都是同樣的含義:

***副為任務(wù)管理器的截圖實線為接收數(shù)據(jù),虛線為發(fā)送數(shù)據(jù),取樣0.5s,每一個正方形的刻度為1.5s(因為任務(wù)管理器繪圖策略速率上升太快過高的沒有辦法顯示,不過還是可以看到時間線)。

第二副為資源管理器,添加了3個采樣器,紅色為CPU占用率,藍色為網(wǎng)絡(luò)接收速率,綠色為網(wǎng)絡(luò)發(fā)送速率。

測試中 一次原始請求大概130字節(jié),加上tcp,ip包頭,10000條大概也只有1.5Mb(包頭不會太多因為管道式請求里會有多個請求放到一個包里的情況,不過大部分服務(wù)器無法有這么快的響應(yīng)速度會有大量重傳的情況,實際上傳流量可能遠大于理論值)。

一次的回包大概在60Mb左右(因為會有部分連接中途中斷所以不一定每次測試都會有10000個完整回復(fù))。

可以看到使用pipe形式性能表現(xiàn)非常突出,總體完成測試僅僅使用了5s左右。

發(fā)送本身壓力比較小,可以看到0.5秒即到達峰值,其實這個時候基本10000條request已經(jīng)發(fā)送出去了,后面的流量主要來自于服務(wù)器端緩存等待(TCP window Full)來不及處理而照成是重傳,后面會講到。

再來看看response的接收,基本上也僅僅使用了0.5s即達到了接收峰值,使用大概5s 即完成了全部接收,因為測試中cpu占用上升并不明顯,而對于response的接收基本上是從tcp緩存區(qū)讀出后直接就存在了內(nèi)容里,也沒有涉及磁盤操作(所以基本上可以說對于pipe這個測試并沒有發(fā)揮出其全部性能,瓶頸主要在網(wǎng)絡(luò)帶寬上)。

再來看下線程組的方式(100條線程每條100次):

下面是異步接收的方式:

很明顯的差距,對于線程組的形式大概使用了25秒,而異步接收使用了超過1分鐘的時間(異步接收的模式是平臺推薦的發(fā)送模式,正常應(yīng)用情況下性能是十分優(yōu)越的,而對于過高的壓力不如自定義的線程組,主要還是因為其使用了默認(rèn)的線程池,而默認(rèn)線程池不可能在短時間開100條線程出來用來接收數(shù)據(jù),所以大量的回復(fù)對線程池里的線程就會有大量的切換,通過設(shè)置默認(rèn)線程池數(shù)量可以提高測試中的性能)。更為重要的是這2者中的無論哪一種方式在測試中,cpu的占用都幾乎是滿的(即是說為了完成測試計算機已經(jīng)滿負荷工作了,很難再有提高)。

后面其實還針對jd,toabao,youku,包括公司自己的服務(wù)器進行過測試,測試結(jié)果都是類似的,只要服務(wù)器不出問題基本上都有超過10倍的差距(如果客戶端帶寬足夠這個差距會更大)。

下面我們再對接口形式的HTTP進行簡單一次測試:

這里選用網(wǎng)易電商的接口(電商的接口一般可承受的壓力比較大,這里前面已經(jīng)確認(rèn)測試不會對其正常使用造成實質(zhì)的影響)。

http://you.163.com/xhr/globalinfo/queryTop.json?__timestamp=1514784144074 (這里是一個獲取商品列表的接口)。

測試數(shù)據(jù)設(shè)置如下:

 

請求量還是10000條接收的response數(shù)據(jù)大概有326Mb 30s之內(nèi)完成。基本上是網(wǎng)絡(luò)的極限,此時cpu也基本無然后壓力(100條管線,每條100個請求)。

這里其實請求是帶時間戳的,因為測試時使用的是同一個時間戳,所以實際對應(yīng)用服務(wù)器的影響不大,真實測試時可以為每條請求設(shè)置不同時間戳(這里是因為要演示使用了線上公開服務(wù),測試時請使用測試服務(wù))。

注意,這里的測試如果選擇了性能較低的測試對象,大部分流量會在服務(wù)器端排隊等候,導(dǎo)致吞吐量不大,這實際是服務(wù)器端處理過慢,與客戶端關(guān)系不大。

一般情況下一臺普通的pc在使用pipe進行測試時就可以讓服務(wù)器出現(xiàn)明顯延時。

原理

正常的http一般實現(xiàn)都是連接完成后(tcp握手)發(fā)生request流向服務(wù)器,然后及進入等待,收到response后才算結(jié)束(如下圖):

 

當(dāng)然http1.1 即支持keep alive,完成一次收發(fā)后完全可以不關(guān)閉連接使用同一個鏈接發(fā)生下一個請求(如下圖):

 

這種方式對性能的提升還是比較明顯的,特別早些年服務(wù)器性能有限,網(wǎng)絡(luò)資源匱乏,RTT大(網(wǎng)絡(luò)時延大)。不過對如今的情況,其實這些都已經(jīng)不是最主要的問題了。

可以明顯看到上面的模式,是一定要等到response到達后,客戶端才能發(fā)起下一個request的,如果應(yīng)用服務(wù)器需要時間處理,所有后面的請求都需要等待,即使不需要任何處理直接回復(fù)給客戶端,請求,回復(fù)在網(wǎng)絡(luò)上的時間也是必須完整的等下去,而且由于tcp傳輸本身的特性,速率是逐步上升的,這樣斷斷續(xù)續(xù)的發(fā)送接收十分影響tcp迅速達到線路性能***值。

pipe (管線式)正是回避了上面的問題,他不需要等回復(fù)達到即可直接發(fā)送(事實上http1.1協(xié)議也從來沒有講過必須要等response到達后客戶端才能發(fā)送下一個請求,只是為了方便應(yīng)用層業(yè)務(wù)實現(xiàn),一般的http庫都是這樣實現(xiàn)的,而現(xiàn)在看到的絕大多少http服務(wù)器都是默認(rèn)支持pipe的),這樣發(fā)送與接收即可以分離開來(如下圖):

 

在事實情況下,發(fā)生可能會比這個圖表現(xiàn)的更快,請求1,2,3,4很可能被放到一個tcp包里被一次性全部發(fā)出去(這種模式也給部分應(yīng)用帶來了麻煩,后面會講到)。

 

對于pipe相對真實的情況如上圖,多個請求會被打包在一起被發(fā)送,甚至有時是所有request發(fā)送完成后,服務(wù)器才開始回復(fù)***個response。

 

而普通的keepalive的模式如上圖,一條線代表一個請求,不僅一次只能發(fā)送一個,而且必須等待回復(fù)后才能發(fā)下一個。

下面看下實際測試中pipe的模式具體是什么模樣的。

可以看到握手完成后(實際上握手時間也不長只用了4ms),隨后即直接開始了request的發(fā)送,可以看到后面的一個tcp包里直接包含了完整的12個請求。在沒有收到任何一個回復(fù)的情況下,就可以把所有要發(fā)送的請求提前全部發(fā)出(服務(wù)器已經(jīng)關(guān)閉了Nagle算法)。

由于發(fā)送速度過快直到發(fā)出一大半近70個request的時候***個tcp確認(rèn)包序號為353的包(只是確認(rèn)包不是response)才發(fā)出(327的ack),而且服務(wù)器很快就發(fā)現(xiàn)下一個包出問題了并引發(fā)了TCP DUP ACK (https://ask.wireshark.org/questions/29216/why-are-duplicate-tcp-acks-being-seen-in-wireshark-capture 產(chǎn)生原因可以參考這里)。

【TCP DUP ACK 出現(xiàn)在接收方發(fā)現(xiàn)數(shù)據(jù)包缺口時(數(shù)據(jù)包失序),這種情況就會發(fā)送重復(fù)的ACK,這不僅用于快重傳,會觸發(fā)比快重傳更快的恢復(fù)機制(Fast Retransmission)如果發(fā)現(xiàn)重復(fù)的ACK,但是報文中未發(fā)現(xiàn)缺口,這表示你捕獲的是數(shù)據(jù)來源(而不是接收方),這是十分正常的如果數(shù)據(jù)在發(fā)往接收方的時候發(fā)生了丟失。你應(yīng)該會看到一個重傳包】。

其實就是說服務(wù)器沒有發(fā)現(xiàn)下一個包后面又發(fā)了3次(一共4次·)TCP DUP ACK 都是針對353的,所以后面客戶端很快就重傳了TCP DUP ACK 所指定的丟失的包(即下面看到的362)

后面還可以看到由于過快的速度,還造成了部分的失序列(out of order)。不過需要說明的是,這些錯誤在tcp的傳輸中是很常見的,tcp有自己的一套高效的機制對這些錯誤進行恢復(fù),即便有這些錯誤的存在也不會對pipe的實際性能造成影響。

如果服務(wù)器異常誤包不能馬上被恢復(fù)可能會造成指數(shù)退避的情況如下圖:

高速收發(fā)帶來的問題,不僅有丟包,失序,重傳,無論是客戶端還是服務(wù)器都會有接收窗口耗盡的情況,如果接收端窗口耗盡會出現(xiàn)TCP ZeroWIndow / Window full。 所以無論是客戶端還是服務(wù)器都需要快速讀取tcp緩沖區(qū)數(shù)據(jù)。

通過對TCP流的檢查可以確定在本次測試中的部分管道的100條request是全部發(fā)出后,response才逐步被服務(wù)器發(fā)出。

現(xiàn)在看一下response的回復(fù)情況:

因為response本身很大,而客戶端的MSS只有1460 (上面看到的1506不是超過了MSS的意思,實際該數(shù)據(jù)包只有1424,加上48個字節(jié)的TCP包頭,20字節(jié)的ip包頭,14字節(jié)的以太網(wǎng)包頭一共是1506,正常tcp包頭為20字節(jié)因為這個tcp包被拆包了,所以包頭里多了28個字節(jié)的options)所以一個response被拆成了多個包。

通過報文不難看出這個response在網(wǎng)絡(luò)中傳輸大概花了1ms不到的時間(大概730微秒),因為看到是過濾掉過端口(指定管道)的流量,實際上在這不到1ms的時間里另外的管道也是可能同時在接收數(shù)據(jù)的。

pipe之所以能比常規(guī)請求方式性能高出這么多,主要有以下幾點:

1:管線式發(fā)送,每條request不要等response回復(fù)即可直接發(fā)送下一個(重點不在于使用的是同一條線路,而且不約等待回復(fù))

2:多條請求打包發(fā)送,在網(wǎng)絡(luò)條件合適的情況下一個包可以包含多條request

3:只要服務(wù)器允許只需要創(chuàng)建極少tcp鏈接 (因為非局域網(wǎng)的TCP線路一般都遵循慢啟動,網(wǎng)絡(luò)正常情況下需要一定時間后效率才能達到***)

現(xiàn)在我們可以來說下pipe弊端:

實際pipe早就被http1.1所支持,并且大部分nginx服務(wù)器也支持并開啟了這一功能。

相比普通的http keepalive傳輸 pipe http 解決了HOL blocking (Head-of-Line Blocking),而正是不再遵循一發(fā)一收的模式,使得應(yīng)用層不能直接將每個請求與回復(fù)一一對應(yīng)起來,對部分需要提交并區(qū)分返回結(jié)果的POST一類的請求,這種方式顯的不是很友好。

解決方法其實也很簡單,在應(yīng)用服務(wù)上為request于response加上唯一標(biāo)簽即可以區(qū)分,或者直接使用HTTP2.0(https://tools.ietf.org/pdf/rfc7540.pdf)(這也是2.0的一個重要改進,http2.0也是通過類似的方式為其每個幀添加標(biāo)識當(dāng)前stream的id來實現(xiàn)區(qū)分的)。

下面是pipe與常規(guī)http的簡單對比:

實現(xiàn)

如下為pipe的.NET簡單實現(xiàn)類庫,及應(yīng)用該類庫的deom 測試工具。

實現(xiàn)過程還是比較簡單的可直接參看GitHub工程,MyPipeHttpHelper為實現(xiàn)pipe的工具類(代碼中有較詳細的注釋),PipeHttpRuner為使用該工具類編寫的測試工具。

責(zé)任編輯:武曉燕 來源: 博客園
相關(guān)推薦

2011-02-13 09:37:55

ASP.NET

2020-07-16 08:06:53

網(wǎng)關(guān)高性能

2023-03-27 08:49:51

2022-08-15 08:01:35

微服務(wù)框架RPC

2015-06-01 07:02:12

云集群高性能計算

2020-05-22 09:12:46

HTTP3網(wǎng)絡(luò)協(xié)議

2024-09-03 09:15:37

2021-10-28 09:36:12

高并發(fā)數(shù)據(jù)實踐

2024-11-20 19:56:36

2014-03-19 14:34:06

JQuery高性能

2024-11-25 12:00:00

C#日志記錄器

2023-03-09 10:22:00

SpringBootRabbitMQ

2018-05-25 14:12:16

SSD云硬盤塊存儲

2009-11-30 09:40:23

Java 7 NIO2HTTP Server

2024-12-25 14:03:03

2013-07-31 09:55:51

高性能備份災(zāi)備

2013-07-31 10:17:44

備份災(zāi)備

2019-05-21 09:40:47

Elasticsear高性能 API

2011-06-09 08:52:30

LevelDB

2018-01-12 14:37:34

Java代碼實踐
點贊
收藏

51CTO技術(shù)棧公眾號