基于单TCP连接的高吞吐模型设计
????????對于服務(wù)與服務(wù)之間往往需要高效的吞吐的信息交互,但在絕大部分服務(wù)應(yīng)用中為了實現(xiàn)高吞吐交互都是基于連接池模式,即通過多個TCP連接來提高吞吐量,這種設(shè)計完全是通過增加IO的讀寫量來實現(xiàn)高效吞吐。
????????如果能減少連數(shù)和降低IO量(合并)來提高吞吐量那在同樣吞吐交互的情況即可以節(jié)省更多的資源。但這種設(shè)計需要從上層應(yīng)用調(diào)度和協(xié)議設(shè)計相結(jié)合才能實現(xiàn),同樣這個應(yīng)用調(diào)度設(shè)計會變得比較復(fù)雜。接下來介紹一下如何實現(xiàn)這樣一個應(yīng)用模型。
協(xié)議制定
????????如果想在一個TCP連接上達到最高的吞吐能力,那必須制定一個連接可復(fù)用的協(xié)議,即協(xié)議支持一個TCP連接給多個會話并發(fā)接收和發(fā)送消息。接下來通過一些協(xié)議的工作情況來做對比
HTTP1.1
????????這協(xié)議是當(dāng)前使用最廣泛的通訊應(yīng)用協(xié)議,它的通訊模式如下:
協(xié)議約束了當(dāng)前連接必須等待響應(yīng)后才能繼續(xù)下一個請求,如果需要高吞吐交互那只能通過更多的連接來支持;上層應(yīng)用大量的連接和IO讀寫會帶來更多資源的開銷。每個請求最少使用一次socket ?write和read.
HTTP1.1 Pipelining
????????這是一種特性則是針對場景的應(yīng)用方式,其處理方式如下
這樣的好處理就即多個請求響應(yīng)可以合并到單個socket write和read里,節(jié)省IO讀寫的次數(shù)大大提高性能。但這種模式下一個連接也只能針對一個會話使用,很難應(yīng)用多到個會話并發(fā)中。它的請求響應(yīng)順序還需要保持一致。
HTTP2.0
??????? HTTP2.0協(xié)議提供了連接復(fù)用能力,這樣多個請求就無須排列等上一個完成即可以處理下一下。
它們的請求響應(yīng)并沒有固定的順序,不過有一個ID標(biāo)簽來維護它們的響應(yīng)關(guān)系。只要不同會話的通訊交互ID不同,那即使多會話在并發(fā)上用同一個連接處理也不會產(chǎn)生影響。對于多個Request和Response是不是會合并到一個socket write和read里那就要看應(yīng)用的模型設(shè)計了。
????????總體上來說HTTP2.0協(xié)議支持單TCP連接的高吞吐應(yīng)用需求,在設(shè)計過程中可能參考相關(guān)特性。只有協(xié)議并不能滿足應(yīng)用的需要,更重要是多個會話使用同一個連接進行交互的同時相互不存在影響。
調(diào)度模型設(shè)計
????????如果想一個連接滿足多個會話并發(fā)需要,那必須設(shè)計一個針對消息的發(fā)送和接收調(diào)度模型;通過這個調(diào)度模型把會話并發(fā)之前的影響切割出來。同樣這個模型對消息處理進行分離切割外還需要加入IO合并處理,把多請求響應(yīng)盡可能用最少的socket write和read來處理從而達到更低的資源使用。
整個邏輯設(shè)計起來比較復(fù)雜,通過Stream把Socker操作的buffer進行隔離,這樣在讀和寫的過程都可以做一個批量的Socket read和write.消息解碼和編碼通過隊列做一個分隔,在消息處理通過線程池把不同會話的請求進行一個隔離處理。
應(yīng)用效果
????????由于BeetleX已經(jīng)完全基于這種模型來設(shè)計,但上層擴展還是需要做消息處理調(diào)度。接下來看一下BeetleX.XRPC基于這種模型進行遠程接口調(diào)用達到怎樣的效果。以下是一個簡單用戶信息獲取的服務(wù)和Client接口調(diào)用測試代碼
開啟了500個用戶用同一個tcp client進行服務(wù)調(diào)用的測試結(jié)果,
RPS達到30萬,針對E3-1230V2這CPU資源來說,使用連接池的方式都難以達到20萬RPS的接口調(diào)用,但基于一個連接反而提升到30萬;這么高的吞吐歸功于連接復(fù)用的過程中對讀寫網(wǎng)絡(luò)IO合并了。
????????由于這個模型設(shè)計每個連接只能由于一個線程來處理協(xié)議分析,當(dāng)協(xié)議比較復(fù)雜的情況那一定程度限制了吞吐能力。當(dāng)這種模型碰到CPU資源充足的情況下可以適當(dāng)?shù)丶佣嘁坏絻蓚€連接即可滿足需求。
? ? ? ? 接下來針對一個連接多會話并發(fā)能跑到多大的帶寬?把測試代碼修改一下
改成每次返回100個對象。
E3-1230V2的CPU在測試過程占用50%的資源 ,單個TCP連接跑到接近2G的帶寬,RPS大概在2.5萬,每個請求返回100個對象列表;大量消息序列化占用了比較多的協(xié)議處理資源。
注意
????????在這種模型不要刻意去通過加連接數(shù)來提高吞吐,加大連接數(shù)意味著socket的write和read合并數(shù)量降低,同樣數(shù)量的吞吐可能引起更高的write和read這樣反倒影響性能。具體分配多少個連接是最優(yōu)則看硬件資源而定,就拿E3-1230V2這個測試情況來說,如果多加一個連接吞吐量并沒有太多提高但CPU使用率則提升了好多,主要是socket的write和read的數(shù)量增加太多了。
????????這種模型還有一個缺點是低吞吐的情況延時有所提高,主要是跨越幾個線程調(diào)度,每個環(huán)節(jié)不飽和的情況下會引線程在線池間的切換引起一些調(diào)度上的延時。
示例代碼:
https://github.com/beetlex-io/BeetleX-Samples/tree/master/XRPC.Performance
BeetleX開源跨平臺通訊框架(支持TLS)
提供高性能服務(wù)和大數(shù)據(jù)處理解決方案
https://beetlex.io
總結(jié)
以上是生活随笔為你收集整理的基于单TCP连接的高吞吐模型设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于 registry 搭建 Docke
- 下一篇: 使用 Source Generator