Khối xây dựng Trung bình 5 phút đọc

Phong cách API trong .NET: REST vs gRPC vs GraphQL

Cách chọn giữa REST, gRPC, GraphQL trong .NET, khi nào BFF giúp, và mỗi style thực sự tốn gì về latency và thời gian dev.

Mục lục
  1. Khi nào API style thực sự quan trọng?
  2. Ngân sách số nào cho lựa chọn này?
  3. Kiến trúc tối thiểu trông thế nào?
  4. Cấu hình .NET 10 trông ra sao?
  5. Tránh sai lầm cổ điển về API style ra sao?
  6. Mỗi style tạo failure mode nào?
  7. Khi nào nên bỏ qua tranh luận API style?
  8. Đi tiếp đâu từ đây?

Lựa chọn API style được quyết định trong cuộc họp design đầu tiên và sống trong từng dòng code client về sau. Chọn sai, team sẽ xoay xở quanh nó nhiều năm. Chương này chia lựa chọn thành ba loại quan trọng cho .NET - REST, gRPC, GraphQL - cộng pattern BFF giải quyết nỗi đau tổng hợp riêng.

Khi nào API style thực sự quan trọng?

Ba tín hiệu.

Nhiều client, hình dạng khác nhau. Web muốn display name của user và mobile muốn cùng đó cộng ảnh profile và partner muốn view chỉ ID, REST endpoint nhân lên. GraphQL gộp lại.

Budget latency nội bộ chặt. Service A gọi Service B 50 lần để render một request. Mỗi lần thêm parse JSON và overhead HTTP. Protobuf nhị phân của gRPC cắt chi phí mỗi lần ~3-5x và HTTP/2 multiplex chúng trên một connection.

Trải nghiệm dev ngoài quan trọng. API public cho partner được con người đọc bằng curl. JSON thắng; Protobuf khó đọc nếu không có tooling.

Nếu không cái nào trội, REST + JSON là mặc định đúng. 80% service .NET còn lại không bao giờ cần gì khác.

Ngân sách số nào cho lựa chọn này?

Style       Kích thước payload    Encode/decode      Thân thiện browser
REST+JSON   1x baseline           ~50 µs             có
gRPC        ~0.3-0.6x             ~10-20 µs          không (cần grpc-web)
GraphQL     thay đổi (tuỳ)        ~50-100 µs         có

Cho latency mỗi call, mạng lấn át mọi thứ với hop bất kỳ > 1 ms. Đổi REST sang gRPC tiết kiệm ~30 µs CPU; nếu service xuyên internet ở RTT 50 ms, nó vô hình. Lợi ích gRPC hiện ra trong data centre ở RTT <1 ms, nơi tiết kiệm CPU có ý nghĩa.

Kiến trúc tối thiểu trông thế nào?

flowchart LR
    Web[Web client] -->|REST+JSON| Edge[ASP.NET Core API]
    Mobile[Mobile client] -->|REST+JSON| Edge
    Edge -->|gRPC| SvcA[Service inventory]
    Edge -->|gRPC| SvcB[Service pricing]
    Edge -->|gRPC| SvcC[Service user]
    Edge --> DB[(Postgres)]

Client ngoài nói REST+JSON; service nội nói gRPC. Service edge dịch

Cấu hình .NET 10 trông ra sao?

REST có sẵn trong ASP.NET Core - không setup. gRPC cần file .proto cộng package:

// inventory.proto - contract chia sẻ
service Inventory {
  rpc GetStock (StockRequest) returns (StockReply);
}
message StockRequest { string sku = 1; }
message StockReply   { int32 quantity = 1; bool available = 2; }
// Phía server
builder.Services.AddGrpc();
app.MapGrpcService<InventoryGrpcService>();

public class InventoryGrpcService(IStockRepo repo) : Inventory.InventoryBase
{
    public override async Task<StockReply> GetStock(StockRequest req, ServerCallContext ctx)
    {
        var qty = await repo.GetQuantityAsync(req.Sku, ctx.CancellationToken);
        return new StockReply { Quantity = qty, Available = qty > 0 };
    }
}

// Phía client - client sinh tự động, dùng như service bình thường
builder.Services.AddGrpcClient<Inventory.InventoryClient>(o =>
{
    o.Address = new Uri("https://inventory:5001");
});

public class CheckoutService(Inventory.InventoryClient inv)
{
    public async Task<bool> CanFulfill(string sku)
    {
        var reply = await inv.GetStockAsync(new StockRequest { Sku = sku });
        return reply.Available;
    }
}

GraphQL với Hot Chocolate trông tương tự - schema-first hoặc code-first, map sang type domain, với DataLoader sẵn để giải bài N+1. Ví dụ đầy đủ vừa khít trong bất kỳ Hot Chocolate quickstart và quá dài để inline ở đây.

Tránh sai lầm cổ điển về API style ra sao?

Bốn sai lầm tôi liên tục gặp khi review:

Mỗi style tạo failure mode nào?

Chương 13 instrument cả ba đồng đều qua hỗ trợ HTTP/gRPC của OpenTelemetry.

Khi nào nên bỏ qua tranh luận API style?

Khi traffic thấp và team nhỏ. Một REST API trên ASP.NET Core lo được 10K QPS thoải mái. Lợi gRPC quan trọng ở quy mô service mesh; lợi GraphQL quan trọng ở quy mô đa nền tảng. Startup với một API và một mobile app không nhận được gì từ cả hai ngoài phức tạp. Ở lại REST + JSON cho đến khi ước lượng QPS hoặc nỗi đau đa client ép thay đổi thật sự.

Đi tiếp đâu từ đây?

Chương kế tiếp: Elasticsearch trong app .NET - khi query LIKE trên Postgres không còn đáp ứng nổi và bạn cần search engine thật. Sau đó, phong cách auth khép lại nhóm building blocks.

Câu hỏi thường gặp

Vì sao REST vẫn mặc định?
Ba lý do: mọi browser, SDK mobile, nền tảng tích hợp đều nói HTTP+JSON natively; HTTP caching (CDN, reverse proxy, browser) miễn phí; debug được với curl, Postman, devtools. gRPC và GraphQL đều bắt team từ bỏ một thứ đó để đổi lợi ích cụ thể. Lợi ích phải có thật - và cho API ngoại thường không.
Khi nào gRPC bù được phức tạp?
Traffic service-to-service nội bộ nơi budget latency chặt (dưới 10 ms p99) và schema chia sẻ giữa các team. Contract Protobuf đóng vai tài liệu, client sinh tự động cắt boilerplate, streaming HTTP/2 xử lý việc dài. Ngoài đó - API ngoại, browser, tích hợp thi thoảng - REST tốt hơn.
GraphQL có đáng cho backend .NET?
Đáng nếu (1) bạn có nhiều loại client (web, mobile, partner) muốn hình dạng khác nhau của cùng data, (2) team đầu tư được vào quản lý schema và phòng N+1, và (3) backend đã nói graph quan hệ tốt. Hot Chocolate là cài đặt .NET kinh điển và thực sự tốt. Cho app một client, REST đơn giản hơn.
BFF là gì và khi nào thêm?
Backend-for-frontend - tầng tổng hợp giữa một client cụ thể và nhiều service backend. Thêm BFF khi client (thường là mobile) gọi 10 lần để render một màn hình. BFF gọi server-side, trả một payload may đo, giảm pin + băng thông. Mỗi client lớn có BFF riêng; chia sẻ BFF cho iOS và Web phá vỡ mục đích.