API timeline: RPC vs GRPC - Tản mạn ngày xa xưa

Nội dung bài viết

Video học lập trình mỗi ngày

Lập trình viên đều biết chính xác rằng hai services riêng biệt nếu muốn liên lạc với nhau thì cần có một bên thứ ba để làm cầu nối giao tiếp, chính vì vậy nhiệm vụ phải xây dựng những cầu nối như thế nào có thể phù hợp để nói chuyện hoặc để cho phép ứng dụng này truy cập các chức năng or lấy thông tin từ những ứng dụng khác.

Đừng phàn nàn về môi trường, hãy phàn nàn về bản thân mình? Tại sao không lớn lên chút nữa?

API timeline

Cầu nối ở đây chính là API. Chính xác là vậy. API là nói chung. API có nhiều cách để triển khai, trước khi đi vào chi tiết, tôi cung cấp cho bạn hình ảnh (internet) này.

Theo timeline thì mỗi thời gian đều có những phong cách được công bố và sử dụng. Mỗi api có một văn hoá, tín ngưỡng, chuẩn hoá dữ liệu riêng nên không tránh khỏi những cuộc cãi vã ẩu đả của các DEV trên social về việc AI hiệu quả hơn AI?

Và AI là có phong cách oách nhất? Nhưng vỗn dĩ cãi nhau đó là chuyện thường ở huyện, dùng JAVA khen JAVA, dùng GO khen GO... Tương tự như vậy...

Riêng cá nhân tôi thì từ những năm 2000 trở đi thì tôi đã có dịp sử dụng chúng đó là SOAP, RPC, REST API, gRPC, và GRAPHQL. Sử dụng khác với hiểu sâu.

Tôi chỉ sử dụng chúng mà thôi. Tôi còn nhớ rằng, khi GRAPHQL được công bố thì có một làn sóng nói rằng REST -> R.I.P khà khà. Tôi cũng ùa theo là vậy, nhưng sự thật không phải vậy khi lớn lên từng chút tôi đã hiểu khác.

Tôi cũng có một vài ý kiền về chuyện Sau 6 năm tôi từ bỏ GraphQL, cuộc cãi vã nảy lửa.. các bạn có thể đọc nó. Tôi cũng đồng ý với quan điểm đó, hãy để để front-end là FE. Cố gắng làm tốt công việc của họ.

Nhưng quay lại thời gian một chút nữa, khi khi REST được công bố, thì 99% những ai đã từng sử dụng SOAP đã phải thở dài và công nhận rằng REST là kẻ chiến thắng, vì vậy hãy sử dụng REST cho những dự án mới tiếp theo, còn cũ thì có thể giữ lại SOAP.

RPC: XML-RPC, JSON-RPC, SOAP

Vì sao tôi không đề cập tới gRPC ở đây. Nó có nguyên nhân đó là tôi đã phân tích về gRPC vs Rest API dùng khi nào? Ở đâu? Xem đồng nghiệp tôi giải thích do đó tôi không nhắc lại ở đây. Tôi nghĩ bạn nên đọc nó, vì chính xác là hệ thống của bạn có thực sự sử dụng hay không?

Ngoài ra, yêu tố performance trong gRPC được thực hành ở bài viết: Cách sử dụng gRPC: Triển khai Order Service Go, Java! Độ trễ gần như KHÔNG CÓ | Từng bước... ở đó bạn sẽ thấy rằng, latency gần như = 0.

Vì vậy chúng ta sẽ thảo luận về RPC, có nhiều phiên bản RPC truyền thống như XML-RPC, JSON-RPC, SOAP... và định dạng dữ liệu chủ yếu là XML hoặc JSON. Đúng ta là tôi sẽ nói về JSON-RPC vì tôi đã trải qua nhiều hơn so với XML-RPC, SOAP.

JSON-RPC

API - JSON-RPC thì những sinh viên mới ra trường or là những backend mới gần đây có lẽ chưa quen thuộc nhiều. Nếu quen thuộc, thì khả năng bạn đang bảo trì những dự án cách đây hơn 10 năm.

Mức độ hiểu biết về các nguyên tắc phát triển dịch vụ RPC cũng là một trong những tiêu chuẩn tham chiếu quan trọng để phân biệt các lập trình viên back-end cao cấp với các lập trình viên thông thường.

Mặc dù hơi thô nhưng nó đúng là vậy, muốn hiểu về nguyên lý bom ba càng thì hay hỏi các CỰU CHIẾN BINH là có thể hiểu rõ nhất, có đúng không?

Để trực quan hơn thì tôi lấy một ví dụ như sau triển khai RPC:

{
  "jsonrpc": "2.0.1",
  "method": "getTicketItemById",
  "params": {
    "userId": 123,
    "ticketId": 111,
    "includeDetails": true
  },
  "id": 1
}

Hoặc gọi mua bán một ticket như sau:

{
  "jsonrpc": "2.0.2",
  "method": "placeOrderTicket",
  "params": {
    "userId": 123,
    "ticketId": 111,
    "quantity": 3,
    ...
  },
  "id": 1
}

Hãy nhìn chúng lâu một chút bạn có cảm nhận rằng có gì hay không? Nó hay đúng không? Tôi phân tích cái hay của nó trước, rồi mới đến cái dở sau. Châm ngôn: Ngon ăn trước, dở ăn sau :D

Ở đó có hai nhiệm vụ getTicketItemByIdplaceOrderTicket được triển khai trong dự án Bán hàng lượng đồng thời cao với JAVA GO NESTJS - Github thì nếu như các bạn viết bằng REST API thì sẽ có mấy router được viết bởi BE? Là 2 hay 4?

Nếu không để ý về version thì là 2, nhưng để ý thì là 4 đôi lúc sự khác biệt cũng là tinh tế quan sát đúng không?

Ví dụ cho cả hai chức năng này bằng REST, sử dụng phương pháp versioning phổ biến nhất là qua URL path:

// Lấy thông tin ticket:
version 2.0.1: GET /v1/users/{userId}/tickets/{ticketId}
version 2.0.2: GET /v2/users/{userId}/tickets/{ticketId}
// Đặt vé:
version 2.0.1: POST /v1/orders (hoặc POST /v1/users/{userId}/orders)
version 2.0.2: POST /v2/orders (hoặc POST /v2/users/{userId}/orders)

Nó là 4. Nhưng khi triển khi RPC thì nó là mấy? Là 1 đúng không? Đó là cái hay trong nhiều cái hay. Giờ quay lại với ví dụ RPC trên ka. Cái "hay" đầu tiên đập vào mắt chính là khả năng gom nhiều chức năng vào một endpoint duy nhất. Ví dụ tôi khai báo đơn giản là (/rpc hoặc /api).

Lúc này backend chỉ cần nhìn vào trường "method" trong JSON để biết cần gọi hàm logic nghiệp vụ nào (getTicketItemById hay placeOrderTicket). Ví dụ trong code go:

// Gọi hàm xử lý dựa trên method
switch req.Method {
case "getTicketItemById":
    result, rpcErr = handleGetTicketItemById(req.Params)
default:
    rpcErr = &JsonRpcError{Code: -32601, Message: "Method not found"}
}

// Tạo và gửi phản hồi
if rpcErr != nil {
    writeErrorResponse(w, req.Id, rpcErr.Code, rpcErr.Message, rpcErr.Data)

Cứ như vậy... NHƯNG chú ý tiếp ở đây có KHÓ gì mà ngày nay dần lãng quên bởi các dự án vừa và nhỏ? ...

Có thể bạn đã bị missing