Giao tiếp
Hypertext transfer protocol (HTTP)
HTTP là một phương thức mã hóa và truyền dữ liệu giữa client và server. Đây là giao thức request/response: client gửi request, server gửi response kèm nội dung liên quan và thông tin trạng thái hoàn tất của request. HTTP có tính tự chứa (self-contained), nên request và response có thể đi qua nhiều router và server trung gian thực hiện load balancing, caching, mã hóa và nén.
Một HTTP request cơ bản gồm một verb (method) và một resource (endpoint). Dưới đây là các HTTP verb thông dụng:
| Verb | Mô tả | Idempotent* | An toàn | Cacheable |
|---|---|---|---|---|
| GET | Đọc một resource | Có | Có | Có |
| POST | Tạo một resource hoặc kích hoạt một process xử lý dữ liệu | Không | Không | Có nếu response chứa thông tin freshness |
| PUT | Tạo hoặc thay thế một resource | Có | Không | Không |
| PATCH | Cập nhật một phần resource | Không | Không | Có nếu response chứa thông tin freshness |
| DELETE | Xóa một resource | Có | Không | Không |
*Có thể gọi nhiều lần mà kết quả không khác nhau.
HTTP là giao thức tầng application, dựa trên các giao thức tầng thấp hơn như TCP và UDP.
Nguồn và đọc thêm: HTTP
Transmission control protocol (TCP)

Nguồn: How to make a multiplayer game
TCP là giao thức hướng kết nối (connection-oriented) chạy trên mạng IP. Kết nối được thiết lập và kết thúc bằng handshake. Mọi packet được gửi đều được đảm bảo tới đích đúng thứ tự ban đầu và không bị hỏng, nhờ:
- Số thứ tự (sequence number) và trường checksum cho từng packet
- Packet acknowledgement và tự động truyền lại
Nếu bên gửi không nhận được response đúng, nó sẽ gửi lại các packet. Nếu timeout nhiều lần, kết nối sẽ bị hủy. TCP cũng triển khai flow control và congestion control. Những đảm bảo này gây ra độ trễ và thường khiến việc truyền kém hiệu quả hơn UDP.
Để đạt throughput cao, web server có thể giữ mở một số lượng lớn kết nối TCP, dẫn tới tốn nhiều bộ nhớ. Việc có số lượng lớn kết nối mở giữa các thread của web server và, ví dụ, một server memcached có thể rất tốn kém. Connection pooling có thể giúp ích, bên cạnh việc chuyển sang UDP khi phù hợp.
TCP hữu ích cho các ứng dụng cần độ tin cậy cao nhưng ít nhạy cảm về thời gian. Một số ví dụ gồm web server, dữ liệu database, SMTP, FTP và SSH.
Dùng TCP thay vì UDP khi:
- Bạn cần toàn bộ dữ liệu đến nơi nguyên vẹn
- Bạn muốn tự động tận dụng throughput của mạng ở mức ước lượng tốt nhất
User datagram protocol (UDP)

Nguồn: How to make a multiplayer game
UDP là giao thức không kết nối (connectionless). Datagram (tương tự packet) chỉ được đảm bảo ở mức từng datagram. Datagram có thể đến đích không đúng thứ tự hoặc không đến. UDP không hỗ trợ congestion control. Vì không có các đảm bảo như TCP, UDP thường hiệu quả hơn.
UDP có thể broadcast, gửi datagram tới mọi thiết bị trong subnet. Điều này hữu ích với DHCP, vì client chưa nhận được địa chỉ IP nên TCP không có cách nào để stream khi chưa có địa chỉ IP.
UDP kém tin cậy hơn nhưng hoạt động tốt trong các use case thời gian thực như VoIP, video chat, streaming và game nhiều người chơi realtime.
Dùng UDP thay vì TCP khi:
- Bạn cần latency thấp nhất
- Dữ liệu đến trễ còn tệ hơn việc mất dữ liệu
- Bạn muốn tự triển khai cơ chế sửa lỗi
Nguồn và đọc thêm: TCP và UDP
- Networking for game programming
- Key differences between TCP and UDP protocols
- Difference between TCP and UDP
- Transmission control protocol
- User datagram protocol
- Scaling memcache at Facebook
Remote procedure call (RPC)

Nguồn: Crack the system design interview
Trong RPC, client khiến một procedure được thực thi ở một address space khác, thường là một server từ xa. Procedure được viết như thể là một lời gọi procedure cục bộ, che giấu khỏi chương trình client các chi tiết về cách giao tiếp với server. Lời gọi từ xa thường chậm và kém tin cậy hơn lời gọi cục bộ, nên cần phân biệt RPC call với local call. Các framework RPC phổ biến gồm Protobuf, Thrift và Avro.
RPC là giao thức request-response:
- Client program: Gọi client stub procedure. Các tham số được đẩy vào stack như một lời gọi procedure cục bộ.
- Client stub procedure: Marshal (đóng gói) procedure id và các đối số vào một request message.
- Client communication module: Hệ điều hành gửi message từ client tới server.
- Server communication module: Hệ điều hành chuyển các packet đến cho server stub procedure.
- Server stub procedure: Unmarshal kết quả, gọi server procedure khớp với procedure id và truyền vào các đối số đã cho.
- Response của server lặp lại các bước trên theo thứ tự ngược lại.
Ví dụ các RPC call:
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}RPC tập trung vào việc phơi bày hành vi (behavior). RPC thường được dùng vì lý do hiệu năng cho giao tiếp nội bộ, vì bạn có thể tự viết các native call cho khớp hơn với use case của mình.
Chọn native library (hay SDK) khi:
- Bạn biết rõ nền tảng đích.
- Bạn muốn kiểm soát cách "logic" của mình được truy cập.
- Bạn muốn kiểm soát cách xử lý lỗi diễn ra bên ngoài library của mình.
- Hiệu năng và trải nghiệm người dùng cuối là mối quan tâm hàng đầu.
Các HTTP API theo REST thường được dùng nhiều hơn cho public API.
Nhược điểm: RPC
- RPC client trở nên gắn chặt (tightly coupled) với cách triển khai của service.
- Phải định nghĩa một API mới cho mỗi thao tác hoặc use case mới.
- RPC có thể khó debug.
- Bạn có thể không tận dụng được ngay các công nghệ sẵn có. Ví dụ, có thể cần thêm công sức để đảm bảo các RPC call được cache đúng cách trên các caching server như Squid.
Representational state transfer (REST)
REST là một phong cách kiến trúc áp đặt mô hình client/server, trong đó client tác động lên một tập resource do server quản lý. Server cung cấp biểu diễn (representation) của các resource cùng các hành động có thể thao tác hoặc lấy về một biểu diễn mới của resource. Mọi giao tiếp phải stateless và cacheable.
Một giao diện RESTful có bốn tính chất:
- Định danh resource (URI trong HTTP): dùng cùng một URI bất kể thao tác nào.
- Thay đổi thông qua biểu diễn (Verb trong HTTP): dùng verb, header và body.
- Thông báo lỗi tự mô tả (status response trong HTTP): dùng status code, đừng phát minh lại bánh xe.
- HATEOAS (giao diện HTML cho HTTP): web service của bạn nên truy cập được đầy đủ trong browser.
Ví dụ các REST call:
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}REST tập trung vào việc phơi bày dữ liệu. REST giảm thiểu coupling giữa client/server và thường được dùng cho các public HTTP API. REST dùng cách tổng quát và đồng nhất hơn để phơi bày resource qua URI, biểu diễn qua header, và hành động qua các verb như GET, POST, PUT, DELETE và PATCH. Nhờ stateless, REST rất phù hợp cho horizontal scaling và partitioning.
Nhược điểm: REST
- Vì REST tập trung vào việc phơi bày dữ liệu, nó có thể không phù hợp nếu các resource không được tổ chức tự nhiên hoặc không truy cập theo một cấu trúc phân cấp đơn giản. Ví dụ, việc trả về mọi bản ghi được cập nhật trong một giờ qua khớp với một tập sự kiện nào đó không dễ diễn đạt thành một path. Với REST, nhiều khả năng sẽ phải triển khai bằng sự kết hợp giữa URI path, query parameter và có thể cả request body.
- REST thường dựa vào một vài verb (GET, POST, PUT, DELETE và PATCH), đôi khi không khớp với use case của bạn. Ví dụ, việc chuyển các tài liệu hết hạn vào thư mục lưu trữ có thể không nằm gọn trong các verb này.
- Lấy các resource phức tạp có phân cấp lồng nhau đòi hỏi nhiều round trip giữa client và server để render một view, ví dụ lấy nội dung một bài blog và các bình luận của bài đó. Với ứng dụng mobile hoạt động trong điều kiện mạng thay đổi, nhiều round trip như vậy rất không mong muốn.
- Theo thời gian, có thể có thêm nhiều field được thêm vào response của API, và các client cũ sẽ nhận tất cả field mới này, kể cả những field họ không cần, do đó payload phình to và latency tăng.
So sánh RPC và REST call
| Thao tác | RPC | REST |
|---|---|---|
| Đăng ký | POST /signup | POST /persons |
| Huỷ đăng ký | POST /resign { "personid": "1234" } | DELETE /persons/1234 |
| Đọc thông tin một người | GET /readPerson?personid=1234 | GET /persons/1234 |
| Đọc danh sách item của một người | GET /readUsersItemsList?personid=1234 | GET /persons/1234/items |
| Thêm một item vào danh sách item của một người | POST /addItemToUsersItemsList { "personid": "1234"; "itemid": "456" } | POST /persons/1234/items { "itemid": "456" } |
| Cập nhật một item | POST /modifyItem { "itemid": "456"; "key": "value" } | PUT /items/456 { "key": "value" } |
| Xóa một item | POST /removeItem { "itemid": "456" } | DELETE /items/456 |
Nguồn: Do you really know why you prefer REST over RPC
