微服務(wù)之間的HTTP通信
由于分布式的性質(zhì),不同組件之間的通信是通過網(wǎng)絡(luò)進行的。我們可以修復(fù)存在許多問題的網(wǎng)絡(luò),我們的系統(tǒng)隨著時間的流逝而具有彈性和可靠性。
隨著分布式系統(tǒng)的發(fā)展,基于微服務(wù)的應(yīng)用吸引了幾乎每個希望隨時間增長并在市場競爭中生存下來的組織的興趣。微服務(wù)使我們能夠輕松地擴展和管理系統(tǒng)。由于許多團隊之間的不懈努力,縮短了開發(fā)時間,并且大大縮短了新功能的上市時間。
由于分布式的性質(zhì),不同組件之間的通信是通過網(wǎng)絡(luò)進行的。影響通信的因素太多,可能是安全性,增加的延遲或正在進行的通信突然終止,從而導(dǎo)致基礎(chǔ)架構(gòu)成本增加。因此,要么我們可以修復(fù)存在許多問題的網(wǎng)絡(luò),要么可以設(shè)計我們的系統(tǒng)以使其隨著時間的流逝而具有彈性和可靠性。
服務(wù)使用網(wǎng)絡(luò)協(xié)議在分布式環(huán)境中相互通信。我們使系統(tǒng)具有彈性,可靠性和更快性的解決方案也取決于正確使用協(xié)議。對于不同的需求和不同的網(wǎng)絡(luò)層(即OSI網(wǎng)絡(luò)模型),我們有各種協(xié)議。當(dāng)我們談?wù)摲?wù)到服務(wù)通信或瀏覽器到服務(wù)通信時,HTTP通常被用作事實上的標準。所有基于REST的服務(wù)均以此為標準。
但是,我們對HTTP的過多依賴是否正確?HTTP的創(chuàng)建是出于不同的目的,HTTP的創(chuàng)建是為了讓瀏覽器進行后端服務(wù)器通信,以使用請求-響應(yīng)模型來檢索某些數(shù)據(jù)。在當(dāng)今世界,它甚至被用于服務(wù)間通信,從而降低了我們系統(tǒng)的真實功率。
在這里,我將介紹HTTP的問題以及常見用例的可能解決方案。稍后,我將提供有關(guān)RSocket的一些詳細信息,這些細節(jié)可以緩解許多現(xiàn)有問題,并使我們的應(yīng)用程序完全響應(yīng)。
HTTP是OSI網(wǎng)絡(luò)模型中的應(yīng)用程序?qū)訁f(xié)議。隨著時間的推移,HTTP不斷發(fā)展,并提供了不同的版本供采用。讓我們仔細研究它們,并可視化它們所面臨的問題。
HTTP / 1.0
如果客戶端服務(wù)要從另一個服務(wù)中檢索某些數(shù)據(jù),它將首先打開與之連接的連接,然后通過該連接向服務(wù)器發(fā)送請求。服務(wù)器將發(fā)送響應(yīng)并關(guān)閉連接。對于每個請求,必須打開一個新連接。因此,每個請求-響應(yīng)周期的大量額外開銷和結(jié)果將是通信緩慢。
圖1顯示了客戶端和服務(wù)器計算機之間HTTP / 1.0的工作。它還顯示了每個請求-響應(yīng)周期所需的多個連接。
HTTP / 1.1
HTTP / 1.1是對HTTP / 1.0的改進,并提供了持久連接形式的解決方案,并引入了“流水線”功能。因此,客戶端可以通過單個連接發(fā)送多個請求,該請求只能在配置的時間內(nèi)保持活動狀態(tài)。
盡管情況相對有所改善,但這仍然存在一個問題,通常稱為“線路阻塞頭”。由于此問題,如果單個連接上有多個請求,則這些請求將排隊到服務(wù)器中,并且僅以相同順序進行響應(yīng)。而且,如果您的客戶端生成請求的速度很快,或者服務(wù)器響應(yīng)速度很慢,那么這將阻止其他請求被處理。因此,網(wǎng)絡(luò)中的擁塞導(dǎo)致不必要的延遲。
在由于請求#1而使請求#2面向“行頭阻塞”的地方,顯示HTTP / 1.1的工作方式。在服務(wù)器處理請求并以Response#1響應(yīng)之前,Request#2將等待服務(wù)器端的處理。
HTTP / 2
HTTP / 2是對HTTP / 1.1的改進,并引入了“ Multiplexing ”的新功能。這允許通過單個連接將多個請求作為單獨的流發(fā)送到服務(wù)器,并且服務(wù)器將通過流將響應(yīng)發(fā)送回客戶端?,F(xiàn)在,這種方式的服務(wù)間通信相對更快。
如圖3所示,HTTP / 2 在單個連接上使用多路復(fù)用通道。通過相同的通道發(fā)送已處理的響應(yīng),該響應(yīng)可以在其他響應(yīng)幀之間進行交錯。任何延遲或阻止的響應(yīng)都不會影響其他響應(yīng)。
文本傳輸協(xié)議
HTTP / 1.x使用文本格式JSON,XML等進行通信,因為這些格式適用于瀏覽器。出于明顯的原因,文本格式使服務(wù)器響應(yīng)易于閱讀。但是,當(dāng)服務(wù)彼此通信時,它們不需要文本格式的響應(yīng)即可解釋。他們?yōu)槭裁匆残枰??如果服?wù)在對象上工作,則它將以二進制格式駐留在該計算機上,針對其處理進行了優(yōu)化,然后在通過網(wǎng)絡(luò)進行序列化之前將其轉(zhuǎn)換為文本,然后在接收端再次反序列化文本并轉(zhuǎn)換回二進制結(jié)構(gòu)以進一步處理這是一項開銷,會減慢處理速度并增加處理成本。
HTTP / 2也提供了對此類問題的改進。相反,它使用二進制協(xié)議,與文本協(xié)議相比,二進制協(xié)議解析效率更高,并且更緊湊,更不易出錯。僅基于HTTP / 2構(gòu)建的最新開發(fā)的gRPC使用進一步改進的二進制協(xié)議Protobuf作為序列化二進制數(shù)據(jù)的機制,因此生成的數(shù)據(jù)更簡單,更小,并提高了處理速度。因為這是RPC,所以就像在客戶端服務(wù)中將遠程方法作為本地方法調(diào)用一樣,并刪除了許多用于HTTP用法的應(yīng)用程序級語義的樣板代碼。
注意:gRPC Protobuf當(dāng)前僅用于服務(wù)間通信,并且消息不可讀。gRPC不適用于瀏覽器,但是許多瀏覽器都提供對HTTP / 2的支持。
到目前為止,HTTP / 2似乎解決了主要的服務(wù)間通信問題。
消息流控制
讓我們考慮一個用例,在這種情況下,客戶端以比服務(wù)器可以處理的速率更高的速率不斷轟炸對服務(wù)器的請求。這將使服務(wù)器超負荷,并使其難以響應(yīng)。我們需要在應(yīng)用程序級別進行某種流量控制。
建立在HTTP / 2 和 HTTP / 2之上的gRPC使用TCP作為傳輸層協(xié)議,該協(xié)議僅提供字節(jié)級流控制。這種類型的流控制將無法在應(yīng)用程序?qū)酉拗普埱?。我們?nèi)匀恍枰獞?yīng)用程序級別的流量控制,或者需要實現(xiàn)斷路器以保持系統(tǒng)的響應(yīng)速度。而且有時我們需要實現(xiàn)重試邏輯以使系統(tǒng)更具彈性。這是構(gòu)建和管理的開銷,仍然由gRPC和 HTTP / 2承擔(dān) 。
實時更新
另一個用例是客戶一直希望自己擁有最新數(shù)據(jù)。在這種情況下,一種選擇是使用HTTP并繼續(xù)向服務(wù)器發(fā)送輪詢請求,以在可用時獲取更新。這樣,將生成許多不必要的請求,從而導(dǎo)致不必要的流量和資源使用。
由于HTTP提供了一個單一的交互模型,即Request-Response,因此在這種情況下使用HTTP不是正確的選擇。
SSE(服務(wù)器發(fā)送的事件)是一種將實時更新從服務(wù)器流傳輸?shù)娇蛻舳说姆椒?。但這是一個文本協(xié)議。
另一種選擇是使用Websockets (二進制協(xié)議),它也可以使用雙向通信通過單個連接為客戶端提供實時更新。
由于Websocket是面向連接的,因此在一段時間內(nèi)重新建立連接后,正在進行的通信中的任何間歇性斷開和響應(yīng)數(shù)據(jù)恢復(fù)都很難管理。
同樣,Websockets也存在由于生產(chǎn)商或消費者使用速度相對較快而引起的問題。因此,還需要消息級別的流控制。
添加到列表中的是與使用Websockets時需要管理的應(yīng)用程序級語義相關(guān)的復(fù)雜性。
我們?yōu)槟承﹩栴}提供了解決方案,但仍在與其他問題進行權(quán)衡。需要一種協(xié)議來隱藏其中的所有問題和復(fù)雜性,并提供一種用于服務(wù)間通信的簡單接口,并具有輕松支持所有用例的能力。
RSocket
根據(jù)Reactive Manifesto的說法,為了最佳地利用資源,分布式系統(tǒng)需要完全反應(yīng)。這樣的系統(tǒng)更加健壯,響應(yīng)更快,更具彈性,更加靈活,并且可以更好地滿足現(xiàn)代需求。
使用反應(yīng)式編程開發(fā)的應(yīng)用程序僅使服務(wù)具有反應(yīng)性,并幫助服務(wù)更好地利用CPU,內(nèi)存等可用資源。但是,要成為完全反應(yīng)性的系統(tǒng),則意味著所有相關(guān)的IO也需要也具有反應(yīng)性。通常,IO與DB交互以及服務(wù)到服務(wù)的通信相關(guān)聯(lián)。R2DBC(反應(yīng)性關(guān)系數(shù)據(jù)庫連接)和反應(yīng)性NoSql驅(qū)動程序負責(zé)數(shù)據(jù)庫交互和RSocket是要照顧其他以響應(yīng)方式處理服務(wù)間通信的領(lǐng)域。對于RSocket,沒有像客戶端和服務(wù)器這樣的東西。一旦客戶端與服務(wù)器建立連接,兩者將變得平等,任何人都可以發(fā)起請求,即,通信是雙向的。
二進制協(xié)議
RSocket(或反應(yīng)式套接字)是一種二進制協(xié)議,它將消息分解為幀,這些幀是字節(jié)流。但是,這還允許采用諸如Protobuf,AVRO甚至JSON序列化之類的任何序列化/反序列化機制。
請求多路復(fù)用
它為多個邏輯流使用單個物理連接,以在客戶端和服務(wù)器之間發(fā)送數(shù)據(jù),從而解決了“線路阻塞頭”問題。
多重互動模型
RSocket提供了一個簡單的通信接口,可用于多種交互模型:
Request-Response (stream of 1).
Fire-and-Forget (no response).
Request-Stream (finite stream of many).
Channel (bi-directional streams).
所有這些模型都表示異步通信,并以反應(yīng)性術(shù)語的Mono / Flux形式返回延遲的結(jié)果。
RSocket是一個應(yīng)用程序?qū)訁f(xié)議,可以選擇在不同的基礎(chǔ)傳輸層協(xié)議(例如TCP,Websockets 和 Aeron)之間進行切換。 TCP是服務(wù)器-服務(wù)器變體的典型選擇,Websockets對于服務(wù)器瀏覽器變體將更加有用,而Aeron(基于UDP)可以在吞吐量非常關(guān)鍵的地方使用。
應(yīng)用語義
與HTTP相比,許多不必要的應(yīng)用程序語義受到了限制。此外,與由于缺乏簡單的應(yīng)用程序語義而直接在應(yīng)用程序?qū)与y以使用的TCP和Websockets相比,RSocket具有易于使用的語義。
內(nèi)置流控制
可用的協(xié)議使用僅控制字節(jié)數(shù)的傳輸級流控制,但是RSocket提供了應(yīng)用程序級消息流控制,這是現(xiàn)在所需要的。RSocket為客戶端和服務(wù)器提供流控制:
反應(yīng)性流,由請求者控制。
響應(yīng)者控制的租賃語義。
會話恢復(fù)
此功能允許恢復(fù)長壽命的流,這在網(wǎng)絡(luò)連接頻繁斷開,切換和重新連接時,對于移動到服務(wù)器的通信很有用。
比HTTP快
作為二進制協(xié)議和使用異步通信使得方法RSocket高達10倍快比HTTP (來源: https://www.netifi.com/rsocket)。
與gRPC相比,RSocket的性能也更好,它比HTTP / 2本身提供了性能上的改進。
RSocket的機會
這些功能清楚地表明了超越傳統(tǒng)協(xié)議(如HTTP)的重要性,至少對于服務(wù)間通信(通常支持任何分布式系統(tǒng)的主干網(wǎng))而言。
基于反應(yīng)式編程技術(shù)堆棧的微服務(wù)可以使用反應(yīng)式通信協(xié)議(即RSocket)提高性能和基礎(chǔ)架構(gòu)利用率。
當(dāng)前環(huán)境中的RSocket協(xié)議有很多機會,而RSocket協(xié)議主要由HTTP主導(dǎo),但有很多限制。一些示例可能是:
盡管優(yōu)點不僅僅限于特定行業(yè),但更好的流功能增加了RSocket在實時聊天應(yīng)用程序,基于GPS的應(yīng)用程序,帶有多媒體聊天的在線教育和協(xié)作繪圖中的范圍。
通過服務(wù)間通信交換大量數(shù)據(jù)的任何基于云的應(yīng)用程序。
在分布式系統(tǒng)中,希望減少延遲并提高系統(tǒng)速度。
在分布式系統(tǒng)中。希望通過提高CPU利用率并提高內(nèi)存效率來降低運營成本。
在應(yīng)用程序中,服務(wù)器希望查詢一組特定的客戶端以在運行時調(diào)試某些問題。由于雙向行為,可以在現(xiàn)有連接上將請求從服務(wù)器發(fā)送到客戶端。
在 發(fā)射后不管功能可用于非關(guān)鍵跟蹤的目的。
圖4顯示了RSocket協(xié)議的可能用法,其中使用各種語言實現(xiàn)的多個微服務(wù)可以在選擇的不同傳輸層上相互通信。提供應(yīng)用層語義的RSocket使交互更容易?,F(xiàn)在,微服務(wù)尚未與協(xié)議語義緊密結(jié)合,可以使用簡單且一致的RSocket接口。