Tìm hiểu về RSocket

Tram Ho

RSocket là gì ?

RSocket là giao thức truyền thông mới, nhằm giải quyết các vấn đề mà giao thức HTTP hiện tại gặp phải. RSocket là 1 giao thức nhị phân sử dụng để transport các byte stream như TCP, WebSocket và Aeron.
Vậy những hạn chế của giao thức HTTP là gì ?

Một kiến trúc hiện đại phải support được các mô hình giao tiếp khác như streaming và fire-and-forgot. HTTP (hypertext transfer protocol) là 1 giao thức text-base hữu dụng trong việc fetch các document thông qua internet, nhưng đối với data center thì giao thức này không hiệu quả. Và vấn đề chủ yếu là HTTP is not reactive.
Có thể xem qua phần FAQ của HTTP/2

Rsocket là 1 giao thức message-base và require 1 vài giao thức transport lower-level để có thể mang được message. Rsocket define 4 loại giao tiếp :

Các thuật ngữ trong RSocket:

Frame:

Frame là 1 single message chứa 1 request, response, hoặc protocol processing.

Fragment:

Là 1 phần của message application, đã được part để đưa vào Frame. Xem thêm về Fragmentation và Reassembly ở đây

Transport:

Giao thức để mang giao thức Rscoket, ở đây có thể là Websocket, TCP hoặc Aeron

Stream:

Stream được hiểu như 1 đơn vị tính toán (có thể là request hoặc response hoặc…)

Request:

Là 1 stream request, có thể là 1 trong 4 loại mình đã nêu ở trên

Payload:

A stream message (upstream or downstream). Contains data associated with a stream created by a previous request. In Reactive Streams and Rx this is the ‘onNext’ event.

Complete:

1 event được sent đến stream để thông báo hoàn thành success. Trong Reactive Streams và Rx thì đâu là sự kiện onComplete.

Client:

The side initiating a connection.

Server:

The side accepting connections from clients.

Connection:

The instance of a transport session between client and server.

Requester:

The side sending a request. A connection has at most 2 Requesters. One in each direction.

Responder:

The side receiving a request. A connection has at most 2 Responders. One in each direction.

Data And Metadata

RSocket cung cấp cơ chế để ứng dụng có thể phân biệt được payload là data hay metadata.
Những tính năng của Data và MetaData:

  • Metadata can be encoded differently than Data.
  • Metadata can be “attached” (i.e. correlated) with the following entities:
    • Connection via Metadata Push and Stream ID of 0
    • Individual Request or Payload (upstream or downstream)

Framing

Transport Protocol:

Giao thức RSocket sử dụng giao thức transport lower level để mang các RSocket frames. 1 giao thức transport phải cung cấp các thông tin sau:

  1. Unicast Reliable Delivery.
  2. Connection-Oriented and preservation of frame ordering. Frame A sent before Frame B MUST arrive in source order. i.e. if Frame A is sent by the same source as Frame B, then Frame A will always arrive before Frame B. No assumptions about ordering across sources is assumed.
  3. FCS is assumed to be in use either at the transport protocol or at each MAC layer hop. But no protection against malicious corruption is assumed.

Framing Format:

Khi sử dụng giao thức transport cung cấp framing thì RSocket frame được đóng gói vào trong message của giao thức transport:

Khi sử dụng giao thức truyền tải không cung cấp khung tương thích, Frame LENGTH phải được thêm vào RSocket frame.

  • Frame Length: (24 bits = max value 16,777,215) Unsigned 24-bit integer representing the length of Frame in bytes. Excluding the Frame Length field.

Frame Header:

Tất cả các RSocket Frames đều bắt đầu với frame header, frame header sẽ bao gồm các thông tin Stream ID, Frame Type, và flags. 2 Flag (I)gnore và (M)etadata sẽ luôn luôn có mặt

  • Stream ID: (31 bits = max value 2^31-1 = 2,147,483,647) Unsigned 31-bit integer representing the stream Identifier for this frame or 0 to indicate the entire connection.
    Transport protocols that include demultiplexing, such as HTTP/2, MAY omit the Stream ID field if all parties agree. The means of negotiation and agreement is left to the transport protocol.
  • Frame Type: (6 bits = max value 63) Type of Frame.
  • Flags: (10 bits) Any Flag bit not specifically indicated in the frame type should be set to 0 when sent and not interpreted on reception. Flags generally depend on Frame Type, but all frame types MUST provide space for the following flags:
    (I)gnore: Ignore frame if not understood
    (M)etadata: Metadata present

Connection Setup:

Client phải connect đến server để setup 1 connection, Khi kết nói được thành lập thì nó sẽ gửi SETUP frame.
Giả sử giao thức transport là TCP thì SETUP frame sẽ như bên dưới (nếu không được sử dụng lại):

Request/Response:

Request/Response là model tương tác phổ biến nhất, nhưng đối với RSocket cũng như Reactive Stream thì đây là 1 trường hợp đặc biệt của Request/Stream – trong đó response stream chỉ có 1 element hoặc 1 frame. Requester send 1 request frame và responder reply lại 1 stream of one frame

Request frame mang Stream ID và frame type (trường hợp này là REQUEST_RESPONSE). Nếu client khơi tạo stream ID, nó là số lẻ và bắt đầu bằng 1 cho first stream, Server sử dụng stream IDs chẵn bắt đầu bằng 2.
Dưới đây là ví dụ về request/response sử dụng TCP. Client là requester gửi message “Hello World!” cho server và server gửi lại message đó.

và đây là response từ server:

Demo

Phần lý thuyết ở trên có vẻ khá khó hiểu và đau đầu. Ok giờ mình thử demo Request/Response (Dùng Spring boot)

Tạo Project:

Tạo project Spring boot thông thường như bao project khác thôi, chú ý 1 số thông bên dưới :

Dependency

Ở đây mình dùng lombok cho nhanh, và dependency phải có là rsocket

application.properties:

Define port cho rsocket để connet vào

Controller:

Ở đây mình tạo 1 controller RsocketController, endpoint là request-response nhận 1 String request và return về 1 String Hello + request đó

Result:

OK, chỉ thế thôi, để demo request response thì mình start project lên :
./mvnw clean package spring-boot:run -DskipTests
=> Result:

=> Ok, Port 7000 đã start, giờ mình cần gửi 1 command đến port 7000 sử dụng Rsocket CLI:
Để dùng Rsocket CLI thì bạn clone file jar ở đây về nhá :

Sau đó cd đến folder vừa download file jar đó về và call đến endpoint request-response với data request là rsocket client :

=> kết quả sẽ như thế này :

Nhìn vào phần request bạn sẽ thấy Frame => Stream ID: 1 Type: REQUEST_RESPONSE Flags: 0b100000000 Length: 40, type ở đây là REQUEST_RESPONSE
Và data request là 1 string rsocket client được mã hóa :

Nhận được response có type là Type: NEXT_COMPLETE, và data là Hello rsocket client:

Giải thích

OK, giờ mình giải thích qua 1 chút ở chỗ này:
Rsocket client (rsc.jar download ở trên) sẽ send 1 request message đến RsocketController sử dụng RSocket message protocol. Message được sent thông qua giao thức TCP đến địa chỉ localhost:7000 nơi mà server đã deploy.
Một mesasge routing instruction sẽ được gửi trong message frame đầu tiên (tương ứng với option –route) nó sẽ gửi thông tin request-response

Spring sẽ dùng thông tin routing này để select đúng @MessageMapping endpoint để gọi, trong trường hợp này là method requestResponse(String request). Method này sẽ response về 1 chuỗi String, và CLI client in ra toàn bộ tương tác trong terminal, một series message frame

Tổng kết:

OK, ở đây mình chỉ muốn giới thiệu về RSocket, và 1 demo nhỏ để hiểu được, Có 1 số thuật ngữ cũng như định nghĩa ko biết dịch thế nào cho dễ hiểu nên mình để nguyên bản luôn 🙇. Các bạn nên tìm đến các trang nguồn để đọc cho dễ hiểu
Ở bài sau mình sẽ demo các type connect của RSocket trên tầng application thay vì đi sâu vào như thế này

Tham khảo:

https://rsocket.io/docs/Protocol.html
https://dzone.com/articles/an-introduction-to-rsocket

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo