使用RSocket進行服務通訊的反應性服務簡介 - Rafał Kowalski
在本文中,我們將討論微服務架構中的通訊問題,以及如何使用RSocket解決這些問題。我們介紹了它的API和支援簡單的“hello world”示例和基本背壓機制實現的互動模型。
RSocket是一種新的,訊息驅動的二進位制協議,它標準化了雲中的通訊方法。它有助於以一致的方式解決常見的應用程式問題,並且它支援多種語言(例如java,js,python)和傳輸層(TCP,WebSocket,Aeron)。
RSocket中的互動被分解為幀。每個幀由一個幀頭組成,該幀頭包含流id,幀型別定義和特定於幀型別的其他資料。幀頭之後是後設資料和有效載荷 - 這些部分攜帶使用者指定的資料。
存在多種型別的幀,表示互動模型的不同動作和可用方法。我們不打算涵蓋所有這些內容,因為它們在官方文件(http://rsocket.io/docs/Protocol)中有詳細描述。
應該注意,在連線建立階段之後,RSocket不區分客戶端和伺服器。每一方都可以開始將資料傳送到另一方 - 它使協議幾乎完全對稱。
效能
幀作為位元組流傳送。它使得RSocket方式比典型的基於文字的協議更有效。從開發人員的角度來看,當JSON在網路中來回飛行時,除錯系統會更容易,但是會對效能的影響。RSocket協議沒有強加任何指定的序列化/反序列化機制,它將幀視為可以轉換為任何東西的一個位元包。這使得我們可以使用JSON序列化或更高效的解決方案,如Protobuf或AVRO。
對RSocket效能產生巨大影響的第二個因素是多路複用。該協議在單個物理連線的頂部建立邏輯流(通道)。每個流都有其唯一的ID,在某種程度上,它可以被解釋為訊息傳遞系統的佇列。此外,RSocket本身支援傳輸大型有效負載。在這種情況下,有效載荷幀被分成幾個幀,其中有一個額外的標誌 - 給定片段的序數。
反應性和流量控制
RSocket協議完全符合Reactive Manifesto中所述的原則。它在資源方面的非同步特性和節儉有助於減少終端使用者所經歷的延遲和基礎架構的成本。由於流式傳輸,我們不需要將資料從一個服務提取到另一個服務,而是在資料可用時推送資料。它是一種非常強大的機制,但也可能存在風險。
讓我們考慮一個簡單的場景:在我們的系統中,我們將事件從服務A流式傳輸到服務B.在接收器端執行的操作非常重要,需要一些計算時間。如果服務A推送事件的速度快於B能夠處理它們的速度,最終B將耗盡資源,傳送方將殺死了接收方,由於RSocket使用Reactor,它內建了對流量控制的支援,這有助於避免這種情況。
我們可以輕鬆提供背壓機制實施,根據我們的需求進行調整。接收方可以指定它想要消耗多少資料,並且在通知傳送方已準備好處理更多資料之前不會獲得更多資料。另一方面,為了限制來自請求者的傳入幀的數量,RSocket實現了一種租用機制。響應者可以指定請求者在定義的時間範圍內可以傳送多少請求。
API
如前一節所述,RSocket使用Reactor,因此在API級別上我們主要操作Mono和Flux物件。它也完全支援無功訊號 - 我們可以輕鬆地對不同事件實現“反應” - onNext,onError,onClose等。
以下段落將介紹API和RSocket中可用的每個互動選項。討論將以程式碼片段和所有示例的描述為後盾。在我們進入互動模型之前,值得描述API基礎知識,因為它將出現在多個程式碼示例中。
使用RSocketFactory建立連線
在對等體之間建立RSocket連線相當容易。API提供了(RSocketFactory)工廠和工廠方法receive和connect ,用來分別在客戶端和伺服器端建立RSocket和CloseableChannel例項。
通訊雙方(請求者和響應者)中存在的第二個共同屬性是transport。RSocket可以使用多個解決方案作為transport層(TCP,WebSocket,Aeron)。無論您選擇哪種API,都會提供工廠方法,允許您調整和調整連線。
RSocket socket = RSocketFactory.connect() .transport(TcpClientTransport.create(HOST, PORT)) .start() .block(); RSocketFactory.receive() .acceptor(new HelloWorldSocketAcceptor()) .transport(TcpServerTransport.create(HOST, PORT)) .start() .subscribe(); |
在響應接收端者,我們必須建立一個套接字接受器例項。SocketAcceptor是一個提供對等體之間契約的介面。它有一個accept接受RSocket傳送請求的方法,並返回一個RSocket例項,用於處理來自對等體的請求。除了提供契約外,SocketAcceptor還允許我們訪問設定框架內容。在API級別,它與ConnectionSetupPayload物件有關。
public interface SocketAcceptor { Mono<RSocket> accept(ConnectionSetupPayload setup, RSocket sendingSocket); } |
如上所示,在對等體之間建立連線相對容易,特別是對於之前使用過WebSockets的人來說 - 就API而言,兩種解決方案都非常相似。
互動模型
設定連線後,我們可以繼續進行互動模型。RSocket支援以下操作:
- fire-forget
- request-resonse 傳統請求響應模型
- request-stream
- channel
在fire-forget模型中,還包括後設資料推送,傳送方都不關心操作的結果 , 它在返回型別(Mono)。在發生fire-forget時,完全成熟的幀被髮送到接收器,而對於後設資料推送動作,幀則不包含有效載荷 - 它僅包括頭部和後設資料,這種輕量級訊息可用於向IoT裝置的移動或對等通訊傳送通知。
RSocket還能夠模仿HTTP行為。它支援請求 - 響應語義,並且可能是您將與RSocket一起使用的主要互動型別。在流上下文中,這種操作可以表示為由單個物件組成的流。在這種情況下,客戶端正在等待響應幀,但它以完全非阻塞的方式執行。
雲應用程式中更有趣的是請求流request-stream和請求通道channel互動,它們對資料流進行操作,通常是無限的。在請求流操作的情況下,請求者將單個幀傳送給響應者並獲回資料流。這種互動方法使服務能夠將策略切換pull data到push data,而不是向響應者傳送定期請求查詢請求者,而是訂閱流並對傳入資料做出反應 - 將在可用時自動到達時發生反應。
由於多路複用和雙向資料傳輸支援,我們可以使用請求通道方法更進一步。RSocket能夠將資料從請求者流式傳輸到響應者,反之則使用單個物理連線。當請求者更新訂閱時,這種互動可能很有用 - 例如,更改訂閱標準。如果沒有雙向通道,客戶端將不得不取消流並使用新引數重新請求它。
在API中,互動模型的所有操作都由下面顯示的RSocket介面的方法表示。
public interface RSocket extends Availability, Closeable { Mono<Void> fireAndForget(Payload payload); Mono<Payload> requestResponse(Payload payload); Flux<Payload> requestStream(Payload payload); Flux<Payload> requestChannel(Publisher<Payload> payloads); Mono<Void> metadataPush(Payload payload); } |
在這個例子中,我們正在請求資料流,但是為了確保傳入的幀不會殺死請求者,我們將背壓機制放在適當的位置。為了實現這種機制,我們使用request_n框架.在訂閱[ onSubscribe(Subscription s)] 的開始時,我們正在請求5個物件,然後我們在onNext(Payload payload)中計算收到的專案。當所有預期的幀到達請求者時,我們正在請求接下來的5個物件 - 再次使用subscription.request(n)方法。
本節介紹的背壓機制的實施是非常基礎的。在生產中,我們應該基於更準確的度量提供更復雜的解決方案,例如預測/平均計算時間。畢竟,背壓機制不會使過度生產響應者的問題消失。它將問題轉移到響應方,在那裡可以更好地處理。關於背壓的進一步閱讀GitHub上
相關文章
- 使用RSocket進行服務通訊的反應性服務 - 負載平衡和可恢復性 | Rafał Kowalski負載
- 微服務的服務間通訊與服務治理微服務
- 使用systemctl進行服務管理
- 阿里雲簡訊服務使用代理的坑阿里
- Spring RSocket:基於服務註冊發現的 RSocket 負載均衡Spring負載
- 阿里雲簡訊服務阿里
- LAMP平臺服務簡介、部署及應用LAMP
- 2020最新 使用阿里雲的簡訊服務傳送簡訊阿里
- SpringCloud系列使用Eureka進行服務治理SpringGCCloud
- 使用JavaScript和網路資訊API進行自適應網路服務JavaScriptAPI
- 通過 Laravel 訊息通知使用 EasySms 簡訊服務,讓你的程式碼更簡潔Laravel
- JMS訊息服務介紹
- Linux中如何使用systemctl進行服務的管理?Linux
- 阿里雲簡訊服務的使用-----獲取簡訊驗證碼阿里
- SpringCloud系列之使用Feign進行服務呼叫SpringGCCloud
- skynet.newservice簡介:服務的啟動
- 如何管理企業通訊服務?
- SpringCloud-服務間通訊方式SpringGCCloud
- java socket 通訊socketServer 服務端多執行緒JavaServer服務端執行緒
- Laravel 阿里雲簡訊服務包Laravel阿里
- Spring Cloud Alibaba 使用RestTemplate進行服務消費SpringCloudREST
- Spring Cloud Alibaba 使用Feign進行服務消費SpringCloud
- Socket最簡單的客戶端與服務端通訊-Java客戶端服務端Java
- HarmonyOS:使用本地真機執行應用/服務
- Service Mesh大咖訪談:使用服務網格的微服務通訊與治理微服務
- SpringCloud進行nacos的服務註冊和服務管理案例SpringGCCloud
- 比較服務間通訊的技術 - ardalis
- Ofcom報告:負擔通訊服務的能力
- Asp.Net Core使用SignalR進行服務間呼叫ASP.NETSignalR
- Spring Cloud Alibaba系列(三)使用feign進行服務呼叫SpringCloud
- 使用科大訊飛語音轉文字的服務進行電話錄音分析
- SpringCloud微服務系列- 服務間通訊之負載均衡SpringGCCloud微服務負載
- 簡要介紹Linux網路服務的種類Linux
- springboot+kurento+coturn+contos的視訊通訊服務搭建Spring Boot
- silky微服務框架的服務治理介紹微服務框架
- 使用騰訊雲函式服務執行 laravel 9函式Laravel
- 阿里雲訊息服務使用教程阿里
- Python 服務端整合 騰訊雲 IM 服務Python服務端