Hiểu về gRPC, OpenAPI, REST và khi nào dùng trong thiết kế API (2020)
(cloud.google.com)- Điểm khởi đầu của thiết kế API là sự khác biệt giữa RPC và REST; cả ba cách đều có thể gắn với HTTP, nhưng khác nhau ở mô hình tạo lời gọi và tổ chức client
- REST là mô hình hypertext trong đó client đi theo các URL do server cung cấp, nên khác với kiểu API theo OpenAPI nơi client tự ghép định dạng URL
- OpenAPI định nghĩa thao tác bằng mẫu đường dẫn URL và phương thức HTTP, thực dụng và được dùng rộng rãi, nhưng gần với mô hình RPC ánh xạ lên HTTP hơn là REST
- gRPC trực tiếp định nghĩa RPC API thông qua IDL, sinh mã, payload nhị phân và quản lý kết nối HTTP/2, đồng thời ẩn các chi tiết HTTP
- gRPC cần phần mềm chuyên biệt ở cả hai phía và có những ràng buộc về tăng cường qua proxy, tránh cập nhật đồng thời và cập nhật từng phần, nên đặc biệt phù hợp cho API nội bộ hoặc khi có thể dùng lớp chuyển đổi như Cloud Endpoints
Ba mô hình để nhìn API dựa trên HTTP
- Các cách tiêu biểu dùng HTTP làm tầng truyền cho API được chia thành REST, OpenAPI và gRPC
- Một trong những lý do nhiều API công khai và API phân tán nội bộ dùng HTTP là vì các tổ chức đã quen với các vấn đề bảo mật của lưu lượng HTTP trên cổng 80 và 443
- Cả ba cách đều có thể gắn với HTTP, nhưng khác nhau ở chỗ lấy gì làm địa chỉ và client tạo lời gọi như thế nào
REST: đi theo URL thay vì tự ghép URL
- Trong REST, client dùng nguyên vẹn URL do server cung cấp, không hiểu hay tự ghép định dạng URL như một phần của đặc tả API
- Trình duyệt đi theo trang hiện tại, bookmark hoặc URL do người dùng nhập vào, và chỉ thực hiện những việc như trích thông tin yêu cầu HTTP từ URL hoặc chuyển URL tương đối thành URL tuyệt đối
- Cốt lõi của REST API là dùng hypertext/hypermedia để biểu diễn tham chiếu giữa các tài nguyên bằng URL của tài nguyên khác
- Trong cách REST, mọi định danh đều được trao đổi dưới dạng URL
POST /accounts→account_URL- truyền
account_URLvàoPOST /subscriptions→subscription_URL GET {account_URL}→ trả về cây dữ liệu tài khoản
- Ưu điểm của REST là gần với tính ổn định, nhất quán và tính phổ quát của chính web; mô hình hướng thực thể của HTTP/REST có thể khiến API đơn giản và quy củ hơn
OpenAPI: gần với RPC ánh xạ trực tiếp lên HTTP
- OpenAPI định nghĩa các mẫu đường dẫn URL dưới
paths, và gọi tổ hợp giữa đường dẫn và phương thức HTTP là một operation - Đường dẫn như
/pets/{petId}yêu cầu client biết giá trị{petId}và chèn nó vào mẫu URL để tạo yêu cầu HTTP - Theo cách này, client phải biết chi tiết định dạng URL, nên trái ngược với mô hình hypertext của REST
- Lý do OpenAPI được dùng rộng rãi là khá rõ ràng
- Nó giống mô hình RPC truyền thống nên quen thuộc với lập trình viên
- Có thể ánh xạ trực tiếp khái niệm RPC vào yêu cầu HTTP
- Với API công khai, ưu điểm lớn là có thể truy cập từ gần như mọi ngôn ngữ và môi trường chỉ bằng công nghệ HTTP tiêu chuẩn
- Đổi lại, phải thiết kế đường dẫn URL, phương thức HTTP và ánh xạ tham số, nên cả bên cung cấp lẫn bên sử dụng API đều có thêm nhiều chi tiết phải học
gRPC: công nghệ triển khai RPC ẩn HTTP/2
- gRPC dùng HTTP/2 làm tầng truyền, nhưng không phơi bày các chi tiết HTTP cho người thiết kế API hay mã client và server
- Luồng gọi của gRPC client khá đơn giản
- Xác định thủ tục cần gọi
- Tính các giá trị tham số sẽ dùng
- Truyền tham số vào stub được sinh mã để thực hiện lời gọi
- gRPC định nghĩa thủ tục từ xa dựa trên interface description language, nên không cần đồng thời biểu diễn đường dẫn URL, tham số và ánh xạ phương thức HTTP như OpenAPI
- Thông qua sinh mã, framework và thư viện, việc tạo thư viện client và triển khai server có thể trở nên dễ dàng hơn
- Nó cũng có lợi thế hiệu năng nhờ payload nhị phân và quản lý kết nối HTTP/2; có thể tự dùng các kỹ thuật này mà không cần gRPC, nhưng sẽ phải học thêm nhiều thứ hơn
Khi cân nhắc gRPC thay cho OpenAPI
- Khi thiết kế API bằng OpenAPI, bạn phải biểu diễn operation và tham số bằng tổ hợp đường dẫn URL và phương thức HTTP, điều này có thể khó vì có quá nhiều lựa chọn
- Nếu vẫn tiếp tục dùng mô hình kiểu RPC, gRPC giúp giảm gánh nặng phải tự thiết kế ánh xạ tùy chỉnh sang HTTP
- gRPC và OpenAPI có mô hình API nền tảng khá giống nhau, nhưng khác ở cách phơi bày HTTP
- OpenAPI phơi bày chi tiết truyền tải HTTP cho client và cho phép người thiết kế kiểm soát việc ánh xạ
- gRPC ẩn các chi tiết HTTP thông qua ánh xạ được định nghĩa sẵn và mã sinh tự động
- Ưu điểm lớn của OpenAPI là client có thể dùng nguyên các công cụ và kỹ thuật HTTP tiêu chuẩn; với nhiều người thiết kế API, lợi ích này đủ để biện minh cho chi phí thiết kế bổ sung
Kết hợp mô hình hướng thực thể với RPC
- Dù dùng gRPC hay OpenAPI, nếu giới hạn các phương thức RPC theo hướng thực thể, bạn vẫn có thể nhận được một phần lợi ích của REST
- Cách làm là không bắt đầu từ định nghĩa thủ tục, mà định nghĩa loại tài nguyên trước rồi ánh xạ các thao tác thực thể tiêu chuẩn cho từng loại
- Các thao tác cơ bản là Create, Retrieve, Update, Delete, List, thường có thể xem là CRUD plus List
- Khi cần vẫn có thể thêm thao tác khác, nhưng nếu trộn khái niệm hướng thực thể và hướng thủ tục thì một số ưu điểm có thể bị suy giảm
- Cách nhóm các thủ tục theo từng loại thực thể cũng là một trong những ý tưởng cốt lõi của ngôn ngữ hướng đối tượng
Ràng buộc và điểm cần lưu ý của gRPC
- gRPC cần phần mềm chuyên biệt ở cả client lẫn server, và phải tích hợp mã sinh vào quy trình build ở cả hai phía
- Với người dùng ngôn ngữ động như JavaScript hay Python, nơi môi trường phát triển có thể gần như không có quy trình build, yêu cầu này có thể là gánh nặng
- Google Cloud Endpoints cho phép truy cập API gRPC qua HTTP và JSON, khôi phục thêm lựa chọn cho client, nhưng không phải ai cũng dùng được nó hoặc tự xây được tính năng tương đương
- Với REST API, khá dễ tạo bot crawl toàn bộ mà không cần metadata, nhưng với API kiểu RPC như gRPC hay OpenAPI thì thường cần API và metadata riêng cho từng loại thực thể hoặc phần mềm tùy biến
- API HTTP thường được bổ sung qua proxy và công cụ quản lý API như Apigee Edge để thêm tính năng bảo mật, kiểm tra đầu vào, ánh xạ định dạng dữ liệu, chỉnh sửa header và body, nhưng trong gRPC việc tăng cường qua proxy như vậy có thể khó hơn nhiều
- gRPC không định nghĩa cơ chế tiêu chuẩn để ngăn mất dữ liệu do cập nhật đồng thời
- HTTP cung cấp header
EtagvàIf-Matchcho việc này
- HTTP cung cấp header
- gRPC cũng không định nghĩa cơ chế cập nhật từng phần
- HTTP có
PATCH, và với JSON có các chuẩn JSON merge patch và JSON patch - JSON merge patch đơn giản hơn nhưng không xử lý được mọi trường hợp như cập nhật mảng
- JSON patch xử lý được nhiều trường hợp hơn nhưng phức tạp hơn khi sử dụng
- HTTP có
Tiêu chí lựa chọn
- Nếu bạn đã biết cách thiết kế theo mô hình hypertext của REST hoặc sẵn sàng học nó, đây có thể là một lựa chọn tốt để hướng tới tính ổn định, nhất quán và phổ quát
- OpenAPI cho phép tạo API có thể truy cập chỉ bằng công nghệ HTTP tiêu chuẩn, nhưng số lựa chọn khi ánh xạ khái niệm RPC sang HTTP nhiều hơn nên việc thiết kế, triển khai và học sử dụng có thể khó hơn
- Nếu đang cân nhắc OpenAPI cho API của mình, cũng đáng xem xét gRPC. Mô hình API nền tảng của hai cách này khá tương đồng, và gRPC giúp giảm nhu cầu phải tự tạo ánh xạ HTTP
- gRPC đặc biệt hấp dẫn trong các điều kiện sau
- Khi dùng sản phẩm như Cloud Endpoints để client không nhất thiết phải áp dụng công nghệ gRPC
- Khi đó là API nội bộ và bạn có thể kiểm soát lựa chọn công nghệ của server cùng mọi client
- Khi chọn gRPC thay cho OpenAPI hoặc REST, cần lưu ý rằng cơ hội tăng cường hoặc điều chỉnh hành vi API thông qua proxy dựa trên các công cụ quản lý API như Apigee Edge có thể bị hạn chế hơn nhiều
1 bình luận
Các ý kiến trên Hacker News
Nếu có thể quay ngược thời gian, tôi muốn ngăn mình học gRPC ngay từ đầu
Ban đầu tôi bị cuốn hút bởi tầm nhìn của nó, nhưng sau vài năm thì thấy có quá nhiều thứ gây đau đầu. Chuyện nó che giấu phần bên trong cũng gần như là nói đùa; để tìm nguyên nhân một request cứ 10 lần thì lỗi 1 lần, tôi phải xả debug log và chỉnh 10–20 thiết lập timeout/retry với tên gọi cũng mơ hồ
Từ Maven plugin, lỗi
deadline exceededkỳ lạ, load balancer ghét HTTP/2, tình huống rốt cuộc vẫn phải dùng API chuẩn vì firewall, tài liệu nghèo nàn, cho tới việc lấy được thông báo lỗi hữu ích cho observability — tất cả đều ngốn thời gianDeveloper experience của code được generate rất kém; client stub là concrete class
finalnên khó mock trong test, còn implementation phía server cũng phải kế thừa concrete class chứ không phải interfaceServer method có async signature nên làm hỏng các hành vi dựa trên AOP như
@Transactional, cũng không hỗ trợ exception; immutable value class thì tốt, nhưng tất cả đều phải tạo bằng builderCuối cùng, để dùng gRPC trong SOA, bạn phải viết rất nhiều mã “đường ống” nhằm che đi nhiễu của gRPC và có được code sạch, dễ test; RPC compiler của Thrift cũng có vấn đề tương tự, cộng thêm vài vấn đề khác
Trải nghiệm gRPC trên .NET và C# hiện đại khá tốt, đến mức Microsoft cũng đã kết thúc các công nghệ RPC cũ như WCF và tập trung vào gRPC
protocgenerate còn dài dòng và dễ lỗi hơn cả tự serializeWire protocol không type-safe; tuy có type tag nhưng lại tái sử dụng cùng một tag cho nhiều kiểu dữ liệu. Mã hóa số nguyên zig-zag cũng chậm
Với tư cách một thư viện RPC thì nó rất tệ; thứ duy nhất tôi từng trực tiếp trải nghiệm còn tệ hơn là FlatBuffers
Tôi tò mò không biết khác biệt này là do Java hay do chính công nghệ gRPC
Không biết đây có phải là vấn đề đặc thù của Java+gRPC không
Tôi đã xây dựng API trong thời gian dài, đã dùng cả gRPC lẫn HTTP/REST, và cũng đã công bố thư viện https://github.com/oapi-codegen/oapi-codegen để tạo client và server Go từ đặc tả OpenAPI
Tôi khó đồng ý với cách bài viết phân biệt OpenAPI và REST. OpenAPI là một cách ghi lại hoạt động của HTTP API, và có thể biểu diễn cả API RESTful lẫn một API hoàn toàn tùy ý. Xét ở điểm là một ngôn ngữ schema mô tả API để công cụ có thể diễn giải, về mặt khái niệm nó tương tự tệp Protocol Buffer dùng để chỉ định giao thức gRPC
gRPC là một cơ chế RPC trao đổi proto; khi Google công bố protobuf, họ không công bố tầng RPC nội bộ là Stubby, và gRPC thì không tuyệt vời bằng Stubby. Dù vậy, hiệu quả truyền tải của nó cao và cũng tương đối dễ mở rộng
Tuy nhiên, gRPC không có một hệ sinh thái vững chắc như các thư viện HTTP chủ đạo, nên thường phải tự triển khai middleware như logging hay xác thực; điều này đặc biệt đúng với RPC giữa các dịch vụ được triển khai bằng các ngôn ngữ khác nhau
Theo tôi, vấn đề thật sự của gRPC là các tệp proto. Vì mọi client đều phải được build với tệp
.prototương thích với server, nên nó không phải là một giao thức có thể khám phá. HTTP API có thể được gọi bằngcurlhoặc code tự viết ngay cả khi không có mô tả OpenAPI, nên mức độ ghép nối lỏng hơn, và vì thế làm việc cũng như debug dễ hơnREST như được định nghĩa trong luận án tiến sĩ năm 2000 của Roy Fielding là: khi
GETvào URL gốc, trong phản hồi200 OKphải có các liên kết, và người dùng phải có thể lần theo các liên kết đó để duyệt qua mọi tài nguyên mà API cung cấp. Cấu trúc phân cấp được cho phép, nhưng mọi thứ phải có thể truy cập được ở đâu đó trong cây liên kết; mục đích là mang lại khả năng khám pháTrong gần như tất cả những nơi tôi đã làm việc suốt 20 năm qua, người ta dùng
POST resource_name/resource_id/sub_resource/sub_resource_id/mutation_typehoặc, tùy theo cách công ty xử lý tính lũy đẳng, dùngPUT resource_name/resource_id/sub_resource/sub_resource_id; client thì lắp ghép các URL “ma thuật” dựa trên kiến thức về cấu trúc kiểu Swagger/OpenAPIVì vậy, những người nghiêm ngặt thường gọi cách làm trong thực tế là “RESTful” thay vì “REST”, với ý rằng nó không triển khai định nghĩa REST của Fielding
Từ góc độ quản lý những API khá lớn có cả client nội bộ và bên ngoài, tôi cũng khó hiểu luồng tạo code từ đặc tả OpenAPI. Sau khi điền các stub được tạo rồi lặp lại việc cải tiến đặc tả API, công cụ lại tạo thêm stub mới, cần merge thủ công, và API càng lớn thì càng khó tìm các thay đổi liên quan
Vì vậy tôi đã tạo ra một “quái vật” dùng
go/astvà các thứ tương tự để sinh đặc tả OpenAPI từ code. Nó không hoàn hảo, nhưng là giải pháp 95% hoạt động được với cả Echo lẫn Gin; khi cần endpoint mới, có thể tạo struct request/response và handler rỗng, rồi sinh tài liệu gửi cho lập trình viên frontend, nhờ đó tiến triển nhanhPhần lớn lập trình viên không cần suy nghĩ về cách biểu diễn API bằng OpenAPI, và tài liệu cũng luôn khớp với code
Apipe.new(GitHun) |> from("search/repositories") |> eq(:language, "elixir") |> order_by(:updated) |> limit(1) |> execute()Không cần biết các hàm gRPC khả dụng hay những điểm đặc thù RESTful của API bên thứ ba, đồng thời vẫn giữ được tài liệu tích hợp sẵn và khả năng truy cập kiểu
https://github.com/cpursley/apipe
Tôi cũng đang cân nhắc một lớp adapter TypeScript để có thể đưa vào các dự án JS/TS theo kiểu Supabase
const { data, error } = await apipe.from('search/repositories').eq('language', 'elixir').order_by('updated').limit(1)Lời gọi này có thể đi qua proxy Elixir để giao các việc nặng như xử lý bất đồng bộ hoặc giới hạn tốc độ
Có thể tạo mô tả OpenAPI dựa trên tuần tự hóa JSON của Protobuf và cung cấp qua Swagger; bản thân gRPC cũng cung cấp reflection tích hợp cùng tiện ích
grpcurlsử dụng nóTừ góc nhìn của người từng làm ở vài công ty FAANG, Thrift/gRPC thực sự hữu ích cho định tuyến dịch vụ nội bộ
Tuy nhiên, phần lớn độ phức tạp đó được các nhóm xây dựng thư viện, tầng khám phá dịch vụ, định tuyến, v.v. quản lý giúp. Dùng giao thức RPC cho phép làm những việc này ở quy mô và tốc độ mà các dịch vụ JSON/REST thông thường khó đạt được
Tôi chưa từng thấy REST API nào không để “động từ bị rò rỉ” ra ngoài, và nếu phải xây dựng service mesh cho backend hoặc nối hai dịch vụ cục bộ bằng network stream thì tôi luôn chọn gRPC
Nhưng tôi tuyệt đối sẽ không dùng gRPC cho các mục đích hướng tới khách hàng hoặc phơi ra web. RPC mạnh vì nó cố định nhiều quyết định và ép buộc “một cách làm”. Ngược lại, nếu nhiều client đa dạng từ nhiều stack công nghệ cần dùng dịch vụ thì REST tốt hơn nhiều
POST /api/doThingyĐây là RPC dễ dùng, chỉ cần HTTP client cơ bản nhất là ai cũng có thể tham gia, và hoạt động tốt trên mọi OS và trình duyệt. Cũng không cần vật lộn xem nên đặt trong URL path, query parameter hay body
Nếu dùng các dòng server cố làm mọi thứ bớt khó chịu hơn như Buf hay Connect, gRPC cũng sẵn sàng nhận JSON qua HTTP
Tôi nghĩ đến các trường hợp cần giao tiếp thời gian thực hơn REST rất nhiều, như game online hay MMO, nhưng không rõ ngày nay người ta có đặt thứ gì đó lên trên kết nối socket hay không
Tôi cũng muốn biết mọi người đã thử những thứ gì khác
Nếu không làm streaming hai chiều thì tôi cho rằng gRPC phần lớn là lãng phí thời gian
Có địa ngục phụ thuộc bắc cầu lúc runtime, địa ngục toolchain, và dường như ngay cả các nhóm quản lý từng implementation trong nội bộ Google cũng không thống nhất được về mặt triết lý rằng các chức năng cơ bản nên hoạt động ra sao
Thử phơi gRPC API cho một nhóm không dùng ngôn ngữ của bạn, đặc biệt là không phải Go/Python/Java hoặc thậm chí dùng phiên bản cũ của chúng; hoặc thử tích hợp với sản phẩm thương mại có sẵn; hoặc phơi ra trình duyệt, tất cả đều sẽ cần tầng trung gian
gRPC nhìn chung khá suôn sẻ
Dùng REST để các dịch vụ backend giao tiếp với nhau cũng không có nhiều ý nghĩa nếu có yêu cầu về hiệu năng; trừ khi chỉ là những lời gọi thỉnh thoảng lấy dữ liệu nhỏ, còn không thì lý do dùng giao thức/API đọc được bởi con người là khá yếu
Khi trả về một subtype
oneofmà kiểu đó hiện không có field nào, kết quả tự động chuyển đổi trông như{ "id": "id", "sub_type_two": { } }Về chức năng thì vẫn chạy, và sau này nếu có field thì đoạn code đó vẫn tiếp tục chạy. Nhưng trong thế giới web, dùng object rỗng để biểu thị kiểu phản hồi là kỳ lạ, và khi viết protobuf thì vấn đề này có thể không dễ thấy
So với gần như mọi giao thức nhị phân có thể tưởng tượng, nó gần như là phản streaming
Trải nghiệm duy nhất của tôi khi dùng gRPC ở công ty là một dự án do một senior developer khác thúc đẩy với lý do “cần hiệu năng”
Cuối cùng vẫn phải tạo JSON API để frontend có thể tiêu thụ, và ngoài developer đó ra thì không ai có kinh nghiệm gRPC. Bản thân developer đó cũng không đi xa hơn hướng dẫn quick start gRPC Python, và cũng không giúp sửa bug
Dự án rối tung vì vô số lý do, và hoàn toàn không đạt đến quy mô đủ để biện minh cho gRPC
Dù vậy, chút gRPC tôi tự dùng thử thì tôi khá thích, và có cảm giác nó đòi hỏi nhiều công sức và suy nghĩ hơn rất nhiều. Cũng có thể vì tôi đã làm JSON API nhiều hơn hẳn
Tôi đang dùng ConnectRPC https://connectrpc.com/ khá thú vị
Nó sửa được nhiều phần có vấn đề của gRPC, và tôi kỳ vọng khi Safari chấp nhận WebTransport, ConnectRPC sẽ có thể phát triển streaming tốt hơn
Ban đầu tôi nghĩ https://buf.build là quá mức cần thiết, nhưng khả năng lấy các file proto của bên thứ ba mà không phải tải từng cái một là yếu tố quyết định
deps:- buf.build/landeed/protopatch- buf.build/googleapis/googleapisViệc tự động tạo SDK cũng rất lớn. Trước đây tôi định khen là nó tự động tạo SDK cho khoảng 9 ngôn ngữ, nhưng trong một hai ngày gần đây nó đã được cập nhật và giờ tôi thấy 16 ngôn ngữ, cùng OpenAPI và các tính năng mới khác
Tôi cũng từng bị lay động bởi lời hứa hão về streaming của gRPC, và tài liệu này khớp chính xác với trải nghiệm của tôi: https://connectrpc.com/docs/go/streaming/
Nhờ vậy cũng có thể dùng streaming hai chiều trên trình duyệt
Có cảm giác như Google đã khiến cả ngành phải dùng gRPC cho giao tiếp dịch vụ nội bộ, như thể họ đã tiến hành một cuộc chiến tâm lý vậy
Trải nghiệm lập trình viên của gRPC tệ hơn REST khá nhiều
Không thể đưa cho ai đó một lệnh đơn giản để gọi một endpoint, mà cần thêm công cụ không được chuẩn hóa. Hơn nữa, mã phía client được sinh ra là một đống xấu xí hiếm thấy trong bất kỳ ngôn ngữ nào
Chỉ với một thay đổi protocol, có thể biết tĩnh được những consumer hạ nguồn nào cần cập nhật và redeploy, biến công việc kéo dài vài tuần thành một thay đổi trong một giờ
Cũng biết rằng các message nhận vào và xuất ra được kiểm chứng ngay lập tức, và có thể lưu trữ với chi phí thấp để khôi phục sau này
Với proto, có được tài liệu API rất dễ đọc, không bị lẫn vào code hay business logic. Quản lý phiên bản và ngữ nghĩa deprecation cũng được tích hợp sẵn, và ngoài map ra thì còn hỗ trợ cấu trúc dữ liệu phong phú hơn
So sánh thì JSON trông cồng kềnh và lỗi thời ở backend
Chỉ cần ghi các kiểu dữ liệu và chữ ký hàm, ta có được thứ có thể gọi như hàm thật, và có thể tập trung vào business logic thay vì boilerplate serialization/deserialization
Thrift cũng tốt hơn rất nhiều so với cách tự làm mọi thứ, và tôi cho rằng GraphQL còn tốt hơn nữa
Ngay cả với Go, việc nắm được cách tái sinh mã và quản lý phiên bản proto dùng chung cũng phiền phức, và càng thêm từng ngôn ngữ thì càng tệ hơn
Dù vậy, có vẻ startup nào cũng nghĩ mình cần 100 microservice và gRPC
Câu “Nếu API là REST API thì client không cần hiểu định dạng URL, và định dạng đó không phải là một phần của đặc tả API cung cấp cho client” gắn với định nghĩa REST của Roy Fielding
Fielding viết rằng REST API phải được đi vào mà không có kiến thức trước, ngoài URI ban đầu và một tập các media type đã chuẩn hóa; sau đó mọi chuyển tiếp trạng thái ứng dụng phải diễn ra bằng cách client chọn các lựa chọn do server cung cấp
https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...
Đây là chuyện đã được bàn nhiều, nhưng vẫn thú vị ở chỗ trong một hệ thống thật sự RESTful, “đặc tả API” đưa cho client lẽ ra chỉ nên là URI/URL điểm vào ban đầu
Cá nhân tôi thấy nó cồng kềnh và không giải quyết vấn đề thực tế
https://en.m.wikipedia.org/wiki/HATEOAS
Đặc biệt là không biết client phải khám phá các resource có thể thao tác hoặc model request/response bằng cách nào
Phần cấu hình có thể là như vậy, nhưng đặc tả API phải nhiều hơn URL rất nhiều và phải mô tả chi tiết media type mà hệ thống dùng. Tức là phần lớn cần mô tả body của HTTP request/response
Ngay trong liên kết cũng nói rằng “REST API nên dành gần như toàn bộ nỗ lực mô tả cho việc định nghĩa media type dùng để biểu diễn resource và điều khiển trạng thái ứng dụng”
Rốt cuộc không phải chỉ trả về
application/json, mà là trả về một thứ cụ thể kiểu+json; phần lớn không phải JSON chung chung mà chứa dữ liệu nghiệp vụ mà ứng dụng phải hiểuTrong các thảo luận phổ biến, người ta chỉ tập trung vào URL ban đầu và bỏ qua phần lớn công việc “hãy mô tả media type” mà Fielding nói. Vì vậy người nghe câu “một URL là đủ” hỏi “phần đặc tả còn lại ở đâu?” là điều hiển nhiên
Tôi cũng bấm vào bài vì tưởng lại là một blogger không hiểu REST, nhưng có vẻ tác giả ít nhất cũng biết các khái niệm cơ bản
Tôi cũng thích gRPC và trong dự án thương mại thì nó khá hấp dẫn, nhưng nếu là dự án cá nhân hoặc mang tính lý tưởng thì tôi nghĩ REST tốt hơn
Tôi không thích dùng gRPC trong nội bộ datacenter
Người ta chọn vì lý do hiệu năng, nhưng khó có thể xem gRPC là hiệu năng cao; chất lượng client công khai cũng rất thấp, đặc biệt là ngoài các triển khai lõi C++/Java. Ví dụ như triển khai Node.js
Tôi không phản đối việc dùng protobuf làm đặc tả API, nhưng nó nên có thể dùng cùng một framing protocol trên TCP. Tuy nhiên trong kiểu RPC đó chưa có lựa chọn thống trị rõ ràng
Với API nền web, tôi thích payload đọc được hơn, nhưng thường khi dùng JSON thì tính cụ thể của kiểu bị lỏng lẻo, gây vấn đề tương tác giữa các ngôn ngữ backend. Đặc biệt trong Node.js,
JSON.parsebị dùng như một cách triển khai mapping schemaMuốn làm đúng thì phải sinh encoder và decoder một cách tường minh từ schema, và như vậy lợi thế của việc dùng JSON trong ngữ cảnh JS phần nào giảm đi
Tôi cũng đang theo dõi dự án TypeSpec của Microsoft: typespec.io
Nếu là stack công nghệ đơn ngôn ngữ thì tầm quan trọng giảm đi. Và nếu dùng ngoài các ngôn ngữ chính của Google, trải nghiệm nhiều khả năng sẽ không tốt bằng
gRPC từng tạo cảm giác khó tiếp cận một cách không cần thiết với những người bên ngoài Google
gRPC JS client nặng một cách không cần thiết và khá khó nhìn thấu. Ý tưởng thì hay, nhưng việc triển khai còn đáng tiếc so với những người đã quen với “sự đơn giản” của REST
RPC dễ bảo trì hơn về mặt ngữ nghĩa, vì không cần ép cardinality hay quan hệ của mô hình dữ liệu vào một mẫu mang tính quy chuẩn duy nhất. Trong một thế giới API thay đổi nhanh, rất khó khớp với các entity RESTful đẹp đẽ; với đội ngũ lớn và yêu cầu/quyền sở hữu thay đổi, thiết kế hướng dịch vụ sẽ tốt hơn
Phía frontend không bảo trì hệ thống backend. Họ muốn một API dễ hiểu, và muốn các entity có thể được trừu tượng hóa bằng REST. Họ là bên hưởng lợi cuối cùng của kiểu thiết kế đó
Công sức bỏ vào REST có ý nghĩa với những công ty bán API và có khách hàng chính là nhà phát triển bên thứ ba
Với phát triển backend, protobuf và mã hóa wire dạng nhị phân dễ hơn. Có thể định nghĩa API và chia sẻ giữa các dịch vụ theo kiểu static type, đồng thời giảm thời gian mã hóa/giải mã message. JSON vừa không có ngữ nghĩa, vừa không được định kiểu, lại có overhead lớn
Ngược lại, frontend xử lý text và JSON một cách native. Họ không muốn tải định nghĩa protobuf xuống hay đối xử với dữ liệu nhị phân như công dân hạng hai, và nó cũng không khớp gọn gàng với tooling
gRPC có routing, retry, kênh phụ, streaming và ngữ nghĩa hủy bỏ protocol được đưa vào rất tốt, nhưng gần như không lộ ra ở frontend. Tất cả đều dành cho consumer phía backend
Rốt cuộc, đây 100% là khoảng cách tooling giữa frontend/backend, và là sự lệch pha giữa interface và usability
Về cơ bản, có thể xem source, con người đọc được và dễ kiểm tra
gRPC là để máy móc trò chuyện hiệu quả với nhau; khi con người chen vào, dù là coding hay kiểm tra request/response, thì hơi bất tiện
Vì bối cảnh và mục tiêu khác nhau nên có thể hiểu được sự khác biệt về usability này
Theo tôi, bản triển khai của buf.build tốt hơn
https://buf.build/blog/protobuf-es-the-protocol-buffers-type...
Có vẻ nhiều thứ đã chọn nó vì cần một protocol kiểu RPC nhị phân có contract, nhưng càng rời xa GoLang thì càng tệ hơn
Nếu chỉ là dịch vụ CRUD đơn giản thì REST cũng đã đủ