Các đội ngũ kỹ sư vẫn dành cả buổi chiều để tranh cãi liệu REST đã "chết" hay gRPC đã khiến mọi thứ khác trở nên lỗi thời. Cuộc tranh luận đó đã đi chệch hướng. Bạn không phải đang chọn giao thức tốt nhất. Bạn đang chọn ranh giới phù hợp. Một giao thức hoạt động mượt mà trong cụm Kubernetes của bạn sẽ trở nên nghẹt thở khi bạn bàn giao nó cho hàng ngàn nhà phát triển bên ngoài. Một giao thức giúp tiết kiệm băng thông quý giá cho ứng dụng di động sẽ làm phá sản hạ tầng của bạn nếu bạn mở nó cho các truy vấn công khai tùy ý. Nếu coi quyết định này như một cuộc thi bình chọn công nghệ, bạn sẽ tạo ra những khoản nợ kiến trúc tồn tại lâu hơn cả tất cả các thành viên hiện tại trong đội ngũ của mình.

Nguyên tắc Ranh giới

Kiến trúc là về sự đánh đổi, không phải về việc tìm ra kẻ chiến thắng. Câu hỏi đúng không bao giờ là "Cái nào nhanh nhất?" hay "Cái nào mới nhất?". Mà là "Ai đang ở phía bên kia đường truyền, và họ kiểm soát những gì?". Các giao thức là những đối tượng ranh giới. Chọn sai không chỉ làm bạn chậm lại. Nó còn khắc sâu những sai lầm vào hệ thống của bạn trong nhiều năm.

Public APIs: REST không hề nhàm chán, nó là sự trách nhiệm

Khi người dùng của bạn là một nhà phát triển bên ngoài mà bạn chưa từng gặp, API của bạn là một sản phẩm, chứ không chỉ đơn thuần là một giao diện. Nhà phát triển đó đang debug vào lúc hai giờ sáng với không có gì ngoài curl và một bộ sưu tập Postman. Nếu họ phải cài đặt một thư viện client tùy chỉnh hoặc học một ngôn ngữ schema trước khi thực hiện được cuộc gọi đầu tiên thành công, bạn đã đánh mất họ rồi.

REST tồn tại được ở đây vì nó chính là bản chất của web. Các phương thức HTTP, mã trạng thái và JSON là ngôn ngữ chung. Caching không phải là một ý tưởng nảy ra sau; nó là hạ tầng đã có sẵn. Trình duyệt, CDN và các edge cache hiểu các header Cache-Control và xác thực ETag một cách tự nhiên. Bạn có thể đặt một REST API đằng sau một CDN tiêu chuẩn và nhận được sự tiết kiệm băng thông ngay lập tức mà không cần viết một dòng logic caching nào. Điều đó rất quan trọng khi lưu lượng truy cập công khai là không thể dự đoán và bạn đang phải trả tiền cho từng gigabyte dữ liệu rời khỏi đám mây của mình.

Ngược lại, GraphQL mang lại một "khoản thuế" nặng nề cho ranh giới công khai. Các endpoint GraphQL công khai cần phải có phân tích chi phí truy vấn, giới hạn độ sâu và chấm điểm độ phức tạp để ngăn chặn một truy vấn bất cẩn hoặc độc hại làm sập cơ sở dữ liệu của bạn. Bạn không chỉ đang cung cấp một API; bạn đang xây dựng một công cụ thực thi truy vấn, một chiến lược giới hạn tốc độ (rate-limiting) và một mô hình tính phí tính toán. Trừ khi bạn có tiềm lực vận hành của các nền tảng lớn nhất, nếu không, chi phí quản lý đó là quá mạo hiểm cho một bề mặt công khai. REST thiết lập các rào chắn mặc định. Mỗi endpoint thực hiện một việc duy nhất. Người dùng chỉ lấy chính xác những gì bạn cung cấp, chứ không phải bất cứ thứ gì họ có thể tưởng tượng ra.

Internal Services: Làm chủ toàn bộ đường truyền

Bên trong tổ chức của bạn, cuộc hội thoại sẽ thay đổi. Bạn kiểm soát cả client và server. Bạn có thể quy định stack công nghệ cho mọi dịch vụ trong chuỗi gọi. Đây là nơi gRPC chứng minh được giá trị của mình.

Đầu tiên, hãy ngừng coi JSON là thứ thiêng liêng. Protocol Buffers tuần tự hóa nhanh hơn JSON khoảng ba lần. Các payload nhỏ hơn vì định dạng là nhị phân. Trên một mạng nội bộ bận rộn, những mili giây và megabyte đó sẽ tích tụ thành tiền bạc thực tế và làm giảm độ trễ đuôi (tail latency). Quan trọng hơn, Protobuf cung cấp cho bạn một hợp đồng (contract) nghiêm ngặt. Khi bạn thay đổi kiểu trường hoặc đổi tên một message, lỗi sẽ xảy ra tại thời điểm biên dịch (compile time), chứ không phải vào lúc ba giờ sáng trên môi trường production khi một dịch vụ hạ nguồn bắt đầu ném ra các ngoại lệ phân tích cú pháp (parse exceptions).

gRPC chạy trên HTTP/2, vì vậy bạn có được nén header, các luồng đa luồng (multiplexed streams) và các ngữ nghĩa streaming thực thụ. Nếu bạn đang truyền các sự kiện có thông lượng cao giữa các dịch vụ hoặc đẩy các cập nhật thời gian thực, thì server-side streaming và bidirectional streaming là các tính năng gốc, chứ không phải là các giải pháp tạm thời kiểu long-polling được "dán băng keo" vào một framework request-response.

Có một trở ngại lớn: đừng trỏ gRPC trực tiếp vào trình duyệt. Các mô hình mạng của trình duyệt không nói chuyện bằng HTTP/2 theo cách mà gRPC mong đợi. Bạn sẽ kết thúc bằng việc phải ghép thêm grpc-web và một proxy như Envoy vào stack của mình chỉ để trình duyệt có thể nói chuyện với backend. Đó không phải là một lỗi; đó là một tín hiệu về ranh giới. Hãy giữ gRPC đằng sau tường lửa của bạn, giữa các dịch vụ tin tưởng lẫn nhau, và hãy coi sự phức tạp khi debug là cái giá của tốc độ. Các payload nhị phân không thể quan sát bằng mắt một cách dễ dàng trong file log như JSON.

UI phức tạp và Mobile: Thị trường ngách của GraphQL

Các màn hình di động hiện đại là một sự chắp vá. Một view có thể cần hồ sơ người dùng,