# Gặp SOAP, gRPC hay GraphQL ở khách: gọi được lệnh đầu tiên trong một ngày

> Ngày đầu ở khách hiếm khi có một REST API gọn gàng: thường là một service XML từ thời trước, một file .proto hoặc một endpoint GraphQL duy nhất. Muốn gọi được, hãy xin đúng bản hợp đồng thay vì đọc hết tài liệu.

Bản gốc: https://fdetimes.net/vi/bach-khoa/soap-grpc-graphql-goi-duoc-trong-mot-ngay/

Chín giờ sáng ngày đầu ở khách, bạn hỏi xin API của hệ thống đơn hàng. Câu trả lời có thể là "bên em dùng SOAP", "có service gRPC nội bộ" hoặc "cứ gọi vào /graphql".

Nếu bạn chỉ quen REST, một phong cách kiến trúc stateless mà mỗi request tự mang đủ thông tin để server hiểu và xử lý, thì cả ba nghe như ba tuần đọc tài liệu.

Thực tế không đến mức ấy. Cả ba giao thức đều dựa trên một bản hợp đồng có cấu trúc chặt, và chính bản hợp đồng đó là đường tắt. Ai xin đúng file và gọi đúng lệnh dễ nhất thì có thể gọi thành công ngay trong ngày.

Với một FDE, đây là kỹ năng nên luyện trước khi ra khách. Gọi được hệ thống của khách càng sớm, bạn càng sớm có dữ liệu thật để làm việc thay vì ngồi chờ.

## Cuối ngày bạn cần cầm được gì?

Mục tiêu là một "thẻ tích hợp" dài một trang cho mỗi hệ thống. Thẻ ghi giao thức, file hợp đồng, một lời gọi mẫu chạy được, timeout đã chọn và lỗi trông như thế nào. Kèm theo là một hàm nhỏ trong code của bạn để cả đội gọi lại.

Chuẩn bị trước không nhiều: quyền truy cập mạng tới môi trường test của khách, thông tin xác thực, và một ngôn ngữ bạn viết nhanh. Riêng gRPC cho phép client và server viết bằng các ngôn ngữ khác nhau, miễn là ngôn ngữ đó được gRPC hỗ trợ. Server của khách viết bằng gì cũng không bắt bạn đổi stack.

Bảng dưới gom lại những gì cần làm với từng giao thức. Cột cuối là gợi ý thực hành: với giao thức nào cũng vậy, hãy cố tình gọi sai một lần để tận mắt thấy lỗi trả về trông thế nào trước khi viết code xử lý.

| Giao thức | Hợp đồng cần xin | Lời gọi đầu tiên nên chọn | Cần quan sát khi thử lỗi |
|---|---|---|---|
| SOAP | File WSDL | Một operation chỉ đọc, ít tham số | Phần tử Fault trong body |
| gRPC | File .proto | Một unary RPC | Gọi sai một lần, ghi lại lỗi client trả về |
| GraphQL | Schema (hệ thống type) | Một query lấy hai, ba field | Gửi query sai, ghi lại response nhận được |

## Bước 1: đừng hỏi "API ở đâu", hãy hỏi "hợp đồng ở đâu"

Câu hỏi đầu tiên quyết định cả ngày. Với SOAP, theo SmartBear, service phải có một file WSDL định nghĩa mọi operation cùng input và output. Với gRPC, Protocol Buffers vừa là định dạng tuần tự hóa vừa là ngôn ngữ mô tả giao diện (IDL), nên file .proto chính là hợp đồng.

GraphQL hơi khác: API được tổ chức quanh type và field chứ không quanh endpoint. Mọi service GraphQL đều định nghĩa một hệ thống type, và công cụ có thể dùng nó để kiểm tra cú pháp query trước khi chạy. Thứ bạn cần xin là schema, cộng với địa chỉ endpoint.

Kiểm tra sau bước này: bạn có file hợp đồng trong tay và tìm được trong đó ít nhất một thao tác chỉ đọc. Nếu khách gửi một file PDF hướng dẫn thay vì WSDL hay .proto, hãy hỏi lại. PDF dễ bị cũ, còn file hợp đồng là thứ hệ thống thật đang dùng.

## Bước 2: SOAP, đọc phong bì trước khi đọc thư

SOAP là giao thức có chuẩn và cấu trúc chặt, thông điệp viết bằng XML. Theo bản Primer SOAP 1.2 của W3C, mỗi thông điệp nằm trong một envelope và body là phần bắt buộc trong envelope đó; lỗi được báo qua phần tử Fault. Bộ khung trông như sau (minh họa giản lược, namespace và tên operation phải lấy từ WSDL của khách):

```xml

A-1024

```

Trong WSDL, chọn operation có ít tham số nhất và chỉ đọc dữ liệu. Gửi một mã đơn hàng có thật trên môi trường test để nhận về dữ liệu thật.

Kiểm tra: response có envelope, body chứa dữ liệu. Sau đó cố tình gửi một mã sai để xem Fault trông thế nào và ghi mẫu đó vào thẻ tích hợp. Code xử lý lỗi sau này sẽ cần đúng cấu trúc đó.

## Bước 3: gRPC, bắt đầu từ unary, để streaming lại sau

Theo tài liệu gRPC, client có thể gọi trực tiếp một method trên server ở máy khác như gọi hàm cục bộ. gRPC có bốn kiểu method. Kiểu đơn giản nhất là unary: client gửi một request, nhận lại một response. Đây là lời gọi đầu tiên bạn nên làm.

Mở file .proto, tìm dòng `rpc` có request và response đều không có từ khóa `stream`. Đoạn dưới là ví dụ giả định để bạn nhận dạng:

```proto
// minh họa giản lược, tên service và message là giả định
service OrderService {
rpc GetOrder (GetOrderRequest) returns (Order);              // unary: gọi cái này trước
rpc WatchOrders (stream Filter) returns (stream OrderEvent);  // để sau
}
```

Kiểu bidirectional streaming, khi cả hai bên cùng gửi một chuỗi message qua một stream đọc-ghi, là phần khó. Nó không cần cho ngày đầu tiên.

Từ file .proto, sinh code client cho ngôn ngữ của bạn rồi mở một channel. Theo gRPC, channel là kết nối tới server tại một host và port cụ thể. Thông tin riêng của từng lời gọi, như header xác thực, đi qua metadata.

Kiểm tra: lời gọi unary trả về một object đúng kiểu `Order`. Nếu bị từ chối, hãy xem lại metadata xác thực trước khi nghi ngờ code.

## Bước 4: GraphQL, chỉ xin đúng thứ bạn cần

GraphQL vừa là ngôn ngữ truy vấn cho API vừa là runtime phía server. Vì API xoay quanh type và field, bạn quyết định hình dạng response ngay trong query. Query đầu tiên nên nhỏ (tên field dưới đây là giả định, hãy lấy tên thật trong schema):

```graphql
query {
order(id: "A-1024") {
id
status
}
}
```

Lợi thế lớn khi khám phá schema của khách là kiểm tra trước khi chạy. Hệ thống type cho phép công cụ báo query sai cú pháp trước khi request chạm vào server. Bạn học schema bằng cách để công cụ chỉ ra chỗ sai, nhanh hơn nhiều so với đọc từ đầu đến cuối.

Kiểm tra: response có đúng hai field bạn hỏi, không thừa không thiếu. Sau đó thêm dần từng field theo nhu cầu của use case.

## Bước 5: bọc lại, có timeout, rồi mới gọi là xong

Một lời gọi chạy được trên laptop chưa phải là tích hợp. Service của khách có thể phản hồi chậm hoặc treo, và code của bạn không nên chờ mãi. gRPC cho phép client đặt deadline, tức thời gian tối đa sẵn sàng chờ một RPC hoàn tất. Với SOAP và GraphQL, hãy đặt timeout tương đương ở HTTP client bạn dùng.

Viết một hàm kiểu `get_order(order_id)` che giấu giao thức bên dưới: nhận tham số đơn giản, trả về object của bạn, ném ra một loại lỗi thống nhất dù gốc là Fault của SOAP hay lỗi mà gRPC client trả về.

Đoạn dưới là khung minh họa giản lược bằng Python; hàm `_goi_he_thong_khach` là chỗ bạn đặt lời gọi SOAP, gRPC hoặc GraphQL thật từ bước 2, 3 hoặc 4, còn 5 giây chỉ là giá trị ví dụ:

```python
# minh họa giản lược: thay _goi_he_thong_khach bằng lời gọi thật của bạn
class IntegrationError(Exception):
pass

def get_order(order_id: str, timeout_s: float = 5.0) -> dict:
try:
raw = _goi_he_thong_khach(order_id, timeout=timeout_s)
except Exception as e:  # Fault SOAP, lỗi gRPC, lỗi HTTP, hết thời gian chờ...
raise IntegrationError(f"get_order({order_id}) thất bại: {e}") from e
return {"id": raw["id"], "status": raw["status"]}
```

Kiểm tra: gọi `get_order` với một mã đúng và một mã sai. Lần đầu phải trả về dict gọn hai field, lần sau phải ra `IntegrationError` kèm thông báo đọc được, không phải một stack trace XML dài cả trang. Đội của bạn không cần biết bên dưới là XML hay Protocol Buffers.

**Điểm mấu chốt:** Đừng đọc hết tài liệu: xin đúng bản hợp đồng, gọi lệnh dễ nhất, rồi bọc nó lại.

## Ba lỗi khiến một ngày thành một tuần

Lỗi phổ biến nhất là bắt đầu từ thứ khó nhất. Khách nhắc đến "stream sự kiện realtime" và bạn lao vào bidirectional streaming, trong khi một unary RPC đã đủ để chứng minh kết nối và lấy dữ liệu cho demo.

Kế đến là bỏ qua lỗi. Nhiều người chỉ thử đường đi thành công, rồi đến ngày demo gặp một Fault SOAP lạ mà code không xử lý được. Gửi cố ý một request sai ngay trong ngày đầu tốn năm phút và có thể cứu cả một buổi demo.

Cuối cùng là gọi không có giới hạn thời gian. Không có deadline hay timeout, một service treo sẽ kéo cả pipeline treo theo, và bạn sẽ mất cả buổi chiều tìm lỗi ở sai chỗ.

## Đưa kỹ năng này vào CV thế nào?

Khi JD FDE nhắc đến "tích hợp với hệ thống legacy" hay "API nội bộ của khách", đừng chỉ đáp lại bằng dòng "SOAP, gRPC, GraphQL" ở mục kỹ năng.

Hãy viết một dòng kết quả, ví dụ "tích hợp service SOAP qua WSDL, bọc thành client có timeout và xử lý Fault", hoặc dẫn link một repo nhỏ có client cho cả ba giao thức gọi vào server bạn tự dựng.

Ở khách, người được tin tưởng không phải là người thuộc lòng đặc tả SOAP 1.2. Đó là người trước bữa trưa ngày đầu đã gửi lên kênh chung một dòng: "Đã gọi được GetOrder, đây là dữ liệu mẫu."

**Thử ngay tuần này:**

- Viết một file .proto giả có một unary RPC, dựng server bằng một ngôn ngữ và gọi bằng client viết ở ngôn ngữ khác
- Tìm một API GraphQL công khai, đọc schema và viết một query chỉ lấy hai field
- Soạn sẵn một mẫu 'thẻ tích hợp' dài một trang: giao thức, hợp đồng, lời gọi mẫu, timeout, mẫu lỗi

## Nguồn

- [Introduction to gRPC](https://grpc.io/docs/what-is-grpc/introduction/)

- [Core concepts, architecture and lifecycle | gRPC](https://grpc.io/docs/what-is-grpc/core-concepts/)

- [GraphQL | The API language for humans and agents](https://graphql.org/)

- [SOAP vs. REST: What API Testers and Developers Need to Know | SmartBear Learn](https://smartbear.com/learn/api-design/soap-vs-rest-apis/)

- [SOAP Version 1.2 Part 0: Primer (Second Edition)](https://www.w3.org/TR/soap12-part0/)

- [What is REST?: REST API Tutorial](https://restfulapi.net/)
