TL;DR
Sử dụng REST cho các API công khai và các thao tác CRUD đơn giản. Sử dụng GraphQL khi các client cần lấy dữ liệu linh hoạt và bạn muốn giảm thiểu tình trạng lấy quá nhiều dữ liệu (over-fetching). Sử dụng gRPC cho giao tiếp giữa các microservice hiệu suất cao. PetstoreAPI hiện đại triển khai cả ba giao thức, cho phép bạn chọn công cụ phù hợp cho từng trường hợp sử dụng.
Giới thiệu
Bạn đang xây dựng một API. Bạn nên sử dụng REST, GraphQL hay gRPC? Mỗi giao thức đều có những người ủng hộ nhiệt tình khẳng định giao thức của họ là tốt nhất. Sự thật là: tất cả chúng đều giỏi ở những việc khác nhau.
REST phổ biến và đơn giản. GraphQL cho phép client kiểm soát việc lấy dữ liệu. gRPC nhanh và hiệu quả cho các dịch vụ nội bộ. Lựa chọn tốt nhất phụ thuộc vào trường hợp sử dụng của bạn, chứ không phải giao thức nào "tốt hơn".
Hầu hết các API chọn một giao thức và gắn bó với nó. Modern PetstoreAPI có một cách tiếp cận khác: nó triển khai cả REST, GraphQL và gRPC, cho thấy cách cùng một API cửa hàng thú cưng hoạt động trên cả ba giao thức này.
Trong hướng dẫn này, bạn sẽ tìm hiểu điểm mạnh và điểm yếu của từng giao thức, xem các ví dụ thực tế từ Modern PetstoreAPI và khám phá cách chọn giao thức phù hợp với nhu cầu của mình.
REST: Tiêu chuẩn phổ quát
REST (Representational State Transfer) là giao thức API phổ biến nhất.
Cách REST hoạt động
Các tài nguyên được truy cập thông qua URL với các phương thức HTTP:
GET /pets - List pets
POST /pets - Create pet
GET /pets/{id} - Get pet
PUT /pets/{id} - Update pet
DELETE /pets/{id} - Delete pet
Ví dụ về yêu cầu:
GET https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24
Ví dụ về phản hồi:
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT",
"status": "AVAILABLE",
"price": 299.99
}
Điểm mạnh của REST
1. Khả năng tương thích phổ quát
Mọi ngôn ngữ lập trình đều có các thư viện HTTP. Trình duyệt, curl, Postman—mọi thứ đều hoạt động với REST.
2. Dễ hiểu
URL đại diện cho tài nguyên. Các phương thức HTTP đại diện cho các hành động. Mô hình tư duy rất đơn giản.
3. Có thể bộ nhớ đệm (Cacheable)
Bộ nhớ đệm HTTP hoạt động ngay lập tức. Các yêu cầu GET có thể được lưu vào bộ nhớ đệm bởi trình duyệt, CDN và proxy.
4. Không trạng thái (Stateless)
Mỗi yêu cầu là độc lập. Không có trạng thái phiên trên máy chủ.
5. Bộ công cụ tuyệt vời
Thông số kỹ thuật OpenAPI, Swagger UI, các công cụ kiểm thử API—REST có hệ sinh thái tốt nhất.
Điểm yếu của REST
1. Lấy quá nhiều dữ liệu (Over-fetching)
Bạn nhận được tất cả các trường ngay cả khi bạn chỉ cần một trường:
// Bạn chỉ cần tên, nhưng bạn nhận được mọi thứ
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT",
"status": "AVAILABLE",
"price": 299.99,
"description": "...",
"images": [...],
"vaccinations": [...]
}
2. Lấy thiếu dữ liệu (Under-fetching) (vấn đề N+1)
Để lấy thông tin về một thú cưng và các đơn đặt hàng của nó, bạn cần nhiều yêu cầu:
GET /pets/123 # Get pet
GET /pets/123/orders # Get orders
GET /orders/456/items # Get order items
3. Phức tạp trong việc quản lý phiên bản
Các thay đổi gây lỗi yêu cầu các phiên bản API mới (/v1, /v2).
4. Không có cập nhật theo thời gian thực
REST là kiểu yêu cầu-phản hồi. Đối với dữ liệu thời gian thực, bạn cần polling hoặc WebSockets.
Khi nào nên sử dụng REST
- API công khai (khả năng tương thích tối đa)
- Các thao tác CRUD đơn giản
- Khi bộ nhớ đệm quan trọng
- Khi bạn cần hỗ trợ công cụ rộng rãi
- Ứng dụng di động với nhu cầu dữ liệu có thể dự đoán được
Triển khai REST của Modern PetstoreAPI
GraphQL: Lấy dữ liệu linh hoạt
GraphQL cho phép client chỉ định chính xác dữ liệu họ cần.
Cách GraphQL hoạt động
Một điểm cuối duy nhất với ngôn ngữ truy vấn:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
species
orders {
id
total
items {
product
quantity
}
}
}
}
Phản hồi:
{
"data": {
"pet": {
"name": "Fluffy",
"species": "CAT",
"orders": [
{
"id": "order-123",
"total": 49.99,
"items": [
{"product": "Cat food", "quantity": 2}
]
}
]
}
}
}
Điểm mạnh của GraphQL
1. Không lấy quá nhiều dữ liệu
Client chỉ yêu cầu các trường họ cần:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name # Chỉ lấy tên
}
}
2. Không lấy thiếu dữ liệu
Lấy dữ liệu liên quan trong một yêu cầu duy nhất:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
name
orders {
items {
product
}
}
}
}
Không có vấn đề N+1.
3. Định kiểu chặt chẽ
Các schema của GraphQL được định kiểu chặt chẽ. Client biết chính xác những gì có sẵn.
4. Tự kiểm tra (Introspection)
Client có thể truy vấn schema để khám phá các thao tác có sẵn:
query {
__schema {
types {
name
fields {
name
type
}
}
}
}
5. Một điểm cuối duy nhất
Tất cả các thao tác đều thông qua một URL: /graphql
Điểm yếu của GraphQL
1. Độ phức tạp
GraphQL khó học hơn REST. Queries, mutations, subscriptions, resolvers—có nhiều thứ cần hiểu hơn.
2. Bộ nhớ đệm khó hơn
Bộ nhớ đệm HTTP không hoạt động tốt. Bạn cần các chiến lược bộ nhớ đệm tùy chỉnh.
3. Rủi ro truy vấn quá mức
Client có thể viết các truy vấn tốn kém:
query {
pets {
orders {
items {
product {
reviews {
author {
pets {
# Độ sâu vô hạn!
}
}
}
}
}
}
}
}
Bạn cần giới hạn độ sâu truy vấn và phân tích độ phức tạp.
4. Tải file lên khó khăn
GraphQL không được thiết kế cho việc tải file lên. Bạn cần các giải pháp thay thế.
5. Giám sát khó hơn
Tất cả các yêu cầu đều đến /graphql. Bạn không thể giám sát bằng URL.
Khi nào nên sử dụng GraphQL
- Ứng dụng di động (giảm băng thông)
- Yêu cầu dữ liệu phức tạp
- Khi client cần sự linh hoạt
- API nội bộ với client đã biết
- Khi bạn muốn tránh quản lý phiên bản
Triển khai GraphQL của Modern PetstoreAPI
gRPC: RPC hiệu suất cao
gRPC sử dụng Protocol Buffers để giao tiếp nhị phân hiệu quả.
Cách gRPC hoạt động
Định nghĩa dịch vụ trong các file .proto:
service PetService {
rpc GetPet(GetPetRequest) returns (Pet);
rpc ListPets(ListPetsRequest) returns (ListPetsResponse);
rpc CreatePet(CreatePetRequest) returns (Pet);
}
message Pet {
string id = 1;
string name = 2;
string species = 3;
PetStatus status = 4;
}
Mã client (được tạo tự động):
client := pb.NewPetServiceClient(conn)
pet, err := client.GetPet(ctx, &pb.GetPetRequest{
Id: "019b4132-70aa-764f-b315-e2803d882a24",
})
Điểm mạnh của gRPC
1. Hiệu suất
Protocol Buffers nhỏ hơn và nhanh hơn JSON:
- Payload nhỏ hơn 3-10 lần
- Serialize nhanh hơn 20-100 lần
2. Truyền tải (Streaming)
Hỗ trợ tích hợp cho truyền tải từ máy chủ (server streaming), truyền tải từ client (client streaming) và truyền tải hai chiều (bidirectional streaming):
rpc WatchPets(WatchPetsRequest) returns (stream Pet);
3. Định kiểu chặt chẽ
Protocol Buffers áp dụng các kiểu tại thời điểm biên dịch.
4. Sinh mã tự động
Tạo mã client và server bằng hơn 10 ngôn ngữ từ các file .proto.
5. HTTP/2
Multiplexing, nén tiêu đề và server push.
Điểm yếu của gRPC
1. Không thân thiện với trình duyệt
Trình duyệt không hỗ trợ truyền tải hai chiều HTTP/2. Bạn cần grpc-web (một giải pháp thay thế).
2. Không dễ đọc đối với con người
Protocol Buffers là nhị phân. Bạn không thể curl một điểm cuối gRPC và đọc phản hồi.
3. Khó debug hơn
Các giao thức nhị phân khó kiểm tra hơn JSON.
4. Ít công cụ hơn
Ít công cụ hơn so với REST. Không có công cụ tương đương Swagger UI.
5. Đường cong học tập dốc hơn
Protocol Buffers, sinh mã tự động và các khái niệm gRPC cần thời gian để học.
Khi nào nên sử dụng gRPC
- Giao tiếp giữa các microservice
- Yêu cầu hiệu suất cao
- Truyền tải thời gian thực
- API nội bộ (không công khai)
- Môi trường đa ngôn ngữ (nhiều ngôn ngữ)
Triển khai gRPC của Modern PetstoreAPI
So sánh song song
| Tính năng | REST | GraphQL | gRPC |
|---|---|---|---|
| Giao thức | HTTP/1.1 hoặc HTTP/2 | HTTP/1.1 hoặc HTTP/2 | Chỉ HTTP/2 |
| Định dạng dữ liệu | JSON (thường) | JSON | Protocol Buffers (nhị phân) |
| Điểm cuối | Nhiều (/pets, /orders) |
Một (/graphql) |
Các phương thức dịch vụ |
| Lấy quá nhiều dữ liệu | Phổ biến | Hiếm | Không áp dụng (bạn định nghĩa message) |
| Lấy thiếu dữ liệu | Phổ biến (N+1) | Hiếm | Không áp dụng |
| Bộ nhớ đệm | Tuyệt vời (HTTP) | Kém | Kém |
| Hỗ trợ trình duyệt | Tuyệt vời | Tuyệt vời | Kém (cần grpc-web) |
| Bộ công cụ | Tuyệt vời | Tốt | Khá |
| Đường cong học tập | Dễ | Trung bình | Khó |
| Hiệu suất | Tốt | Tốt | Tuyệt vời |
| Truyền tải | Không (cần WebSocket) | Có (subscriptions) | Có (nguyên bản) |
| Phiên bản hóa | URL hoặc tiêu đề | Tiến hóa Schema | Tiến hóa Proto |
| Tốt nhất cho | API công khai, CRUD | Client linh hoạt | Microservice |
Cách Modern PetstoreAPI triển khai cả ba
Modern PetstoreAPI là độc đáo: nó triển khai cùng một API cửa hàng thú cưng bằng REST, GraphQL và gRPC.
Dữ liệu giống nhau, ba giao thức
Lấy thông tin thú cưng theo ID:
REST:
GET https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24
GraphQL:
query {
pet(id: "019b4132-70aa-764f-b315-e2803d882a24") {
id
name
species
}
}
gRPC:
pet, err := client.GetPet(ctx, &pb.GetPetRequest{
Id: "019b4132-70aa-764f-b315-e2803d882a24",
})
Cả ba đều trả về cùng một dữ liệu thú cưng.
Tại sao phải triển khai cả ba?
1. Học bằng cách so sánh
Xem cách các thao tác giống nhau hoạt động trong các giao thức khác nhau.
2. Chọn công cụ phù hợp
Sử dụng REST cho các điểm cuối công khai, GraphQL cho ứng dụng di động, gRPC cho các dịch vụ nội bộ.
3. Lộ trình di chuyển
Bắt đầu với REST, sau đó thêm GraphQL hoặc gRPC mà không cần viết lại mọi thứ.
4. Triển khai tham chiếu
Modern PetstoreAPI trình bày các mẫu sẵn sàng sản xuất cho cả ba giao thức.
Kiểm tra hướng dẫn so sánh giao thức để biết các ví dụ chi tiết.
Kiểm thử API đa giao thức với Apidog
Apidog hỗ trợ REST, GraphQL và gRPC trong một công cụ duy nhất.
Kiểm thử REST
Nhập thông số kỹ thuật OpenAPI và chạy các bài kiểm thử tự động:
pm.test("Trạng thái là 200", () => {
pm.response.to.have.status(200);
});
pm.test("Thú cưng có các trường bắt buộc", () => {
const pet = pm.response.json();
pm.expect(pet).to.have.property('id');
pm.expect(pet).to.have.property('name');
});
Kiểm thử GraphQL
Viết các truy vấn GraphQL và xác thực phản hồi:
query GetPet($id: ID!) {
pet(id: $id) {
id
name
species
}
}
Apidog xác thực dựa trên GraphQL schema.
Kiểm thử gRPC
Nhập các file .proto và kiểm thử các dịch vụ gRPC:
service: PetService
method: GetPet
request: { "id": "019b4132-70aa-764f-b315-e2803d882a24" }
Apidog tạo yêu cầu từ các định nghĩa Protocol Buffer.
Kiểm thử đa giao thức
Kiểm tra xem cả ba giao thức có trả về dữ liệu nhất quán không:
- Gọi điểm cuối REST
- Gọi truy vấn GraphQL
- Gọi phương thức gRPC
- So sánh phản hồi
Apidog giúp đảm bảo API đa giao thức của bạn luôn nhất quán.
Chọn giao thức phù hợp
Sử dụng cây quyết định này:
Đây có phải là một API công khai không?→ Có: Sử dụng REST (khả năng tương thích tối đa) → Không: Tiếp tục
Bạn có cần truyền tải theo thời gian thực không?→ Có: Sử dụng gRPC hoặc WebSocket → Không: Tiếp tục
Client có cần lấy dữ liệu linh hoạt không?→ Có: Sử dụng GraphQL → Không: Tiếp tục
Hiệu suất có quan trọng không (microservice)?→ Có: Sử dụng gRPC → Không: Sử dụng REST (tùy chọn đơn giản nhất)
Ví dụ thực tế
- Stripe: REST (API công khai, đơn giản, có thể lưu vào bộ nhớ đệm)
- GitHub: REST + GraphQL (REST cho API công khai, GraphQL cho các truy vấn phức tạp)
- Google Cloud: gRPC + REST (gRPC cho hiệu suất, REST cho khả năng tương thích)
- Netflix: GraphQL (ứng dụng di động cần dữ liệu linh hoạt)
- Uber: gRPC (giao tiếp microservice)
Bạn có thể sử dụng nhiều giao thức không?
Có! Modern PetstoreAPI cho thấy cách thực hiện. Các mẫu phổ biến:
- REST cho API công khai
- GraphQL cho ứng dụng di động
- gRPC cho microservice nội bộ
Mỗi giao thức phục vụ các client khác nhau với các nhu cầu khác nhau.
Kết luận
REST, GraphQL và gRPC không phải là đối thủ cạnh tranh—chúng là những công cụ cho các công việc khác nhau. REST phổ biến và đơn giản. GraphQL cung cấp quyền kiểm soát cho client. gRPC nhanh và hiệu quả.
Modern PetstoreAPI triển khai cả ba, cho thấy cách cùng một API hoạt động trên các giao thức. Bạn có thể khám phá tài liệu REST, schema GraphQL và các file proto gRPC để xem các ví dụ sẵn sàng sản xuất.
Sử dụng Apidog để kiểm thử cả ba giao thức, so sánh các triển khai và đảm bảo tính nhất quán trên API đa giao thức của bạn.
Giao thức tốt nhất là giao thức giải quyết vấn đề cụ thể của bạn. Modern PetstoreAPI cung cấp cho bạn kiến thức để lựa chọn một cách khôn ngoan.
Câu hỏi thường gặp
Tôi có thể sử dụng REST và GraphQL cùng nhau không?
Có. Nhiều API cung cấp cả hai. Sử dụng REST cho các thao tác đơn giản và GraphQL cho các truy vấn phức tạp. GitHub làm điều này.
gRPC có đang thay thế REST không?
Không. gRPC dành cho các microservice nội bộ. REST vẫn là tiêu chuẩn cho các API công khai do khả năng tương thích và bộ công cụ tốt hơn.
Giao thức nào nhanh nhất?
gRPC là nhanh nhất nhờ Protocol Buffers và HTTP/2. Nhưng đối với hầu hết các API, sự khác biệt này không quan trọng—độ trễ mạng chiếm ưu thế.
Tôi có nên chuyển từ REST sang GraphQL không?
Chỉ khi bạn gặp vấn đề về lấy quá nhiều/quá ít dữ liệu (over-fetching/under-fetching). Đừng di chuyển chỉ vì GraphQL đang là xu hướng.
Trình duyệt có thể sử dụng gRPC không?
Không trực tiếp. Bạn cần grpc-web, điều này làm tăng độ phức tạp. Đối với client trình duyệt, hãy sử dụng REST hoặc GraphQL.
Modern PetstoreAPI giữ cả ba giao thức đồng bộ như thế nào?
Lớp logic nghiệp vụ chung. REST, GraphQL và gRPC là các bộ điều hợp giao thức mỏng trên cùng một API cốt lõi.
Các startup nên sử dụng giao thức nào?
Bắt đầu với REST. Nó đơn giản, dễ hiểu và có bộ công cụ tuyệt vời. Thêm GraphQL hoặc gRPC sau này nếu bạn cần chúng.
Apidog có hỗ trợ cả ba giao thức không?
Có. Apidog hỗ trợ REST (OpenAPI), GraphQL và gRPC trong một công cụ, giúp dễ dàng kiểm thử các API đa giao thức như Modern PetstoreAPI.
