Tại Riiid, đơn vị đang vận hành Santa TOEIC, chúng tôi sử dụng gRPC/Protobuf rất tích cực.
Không lâu sau khi tôi gia nhập Riiid, tôi được thông báo rằng từ nay mọi API mà đội backend cung cấp cho frontend (mobile/web) sẽ được thống nhất bằng gRPC.
Để dùng stack gRPC/Protobuf ở frontend web, trước đây có thể gắn plugin JS/TS vào protoc để sử dụng hoặc dùng Protobuf.js.
Plugin JS chính thức của protoc có vấn đề là sinh ra mã theo phong cách rất cũ, và các plugin trong hệ sinh thái cũng không đáp ứng được toàn bộ yêu cầu của chúng tôi. Ngoài ra còn có sự bất tiện là phải phụ thuộc vào binary native (protoc). (Dạo gần đây còn có vấn đề khó cài protoc trên thiết bị M1 nữa.)
Chúng tôi đã dùng Protobuf.js để xây dựng nhiều sản phẩm trong thời gian qua, nhưng khi mọi giao diện giao tiếp đa nền tảng của tất cả sản phẩm trong công ty đều dùng Protobuf, chúng tôi nhận ra Protobuf.js chưa đủ trưởng thành đến mức mà chúng tôi cần.
Chúng tôi gặp nhiều vấn đề như: nếu tên message trùng nhau thì bị nhầm sang message trong namespace khác, nếu ở namespace toàn cục có enum rồi ngay sau đó là khai báo message thì không sinh mã kiểu message, hoặc định nghĩa kiểu TypeScript khác với hành vi thực tế của JS được sinh ra.
Trong quá trình này, để xây dựng hệ thống chỉ chọn ra các schema protobuf cần thiết cho từng sản phẩm rồi build, chúng tôi đã tạo ra pollapo, một trình quản lý gói protobuf.
(Khi đó cũng đã có các trình quản lý phụ thuộc protobuf khác, nhưng hoặc là có bug, hoặc không hỗ trợ nested dependency. Ngoài ra, tính năng quản lý gói do buf cung cấp lúc đó mới chỉ có một bài blog nói là đang phát triển, và cho tới khi chúng tôi tạo xong pollapo và hoàn tất migration nội bộ thì nó vẫn chưa hoàn thiện.)
pollapo đã giúp giảm mạnh số lượng schema được build cho mỗi sản phẩm, và các bug phát sinh do cùng tên message cũng giảm bớt, nhưng vẫn còn tồn tại bug và vấn đề build, nên để giải quyết điều đó chúng tôi đã tự tạo một trình biên dịch protobuf sang typescript.
Santa TOEIC hiện đã loại bỏ toàn bộ protobuf.js và hoàn tất thay thế bằng pbkit.
Các ứng dụng được phát triển tại Riiid, bao gồm Santa TOEIC, sử dụng WebView rất tích cực.
WebView giao tiếp với native để lấy thông tin thiết bị/người dùng hoặc thông tin nội dung đang hiển thị, và giao diện ở đây cũng được định nghĩa bằng schema dịch vụ Protobuf.
pbkit cung cấp một interface cho phép thay thế tầng mạng bằng giao thức khác thay vì gRPC khi sinh mã dịch vụ.
Các kỹ sư frontend web dùng trình biên dịch pbkit không cần biết khi giao tiếp với mobile native thì đó là đang gửi yêu cầu qua gRPC hay qua giao thức App Bridge đã thống nhất với các kỹ sư mobile.
Ngoài ra, vì chúng tôi cũng tự phát triển tiện ích mở rộng Chrome, nên nội dung giao tiếp với mobile cũng có thể được kiểm tra thuận tiện trong tab pbkit của Chrome DevTools giống như xem Network tab.
Do tự xây dựng trình biên dịch schema protobuf, chúng tôi nghĩ rằng có thể nhanh chóng làm được các tính năng như Go to Definition trong trình soạn thảo mã, nên cũng đã tạo tiện ích mở rộng VSCode.
Trước đây, các tiện ích mở rộng protobuf dành cho VSCode chỉ cung cấp những tính năng như tô sáng cú pháp, còn tiện ích mở rộng pbkit cho VSCode có tính năng Go to Definition hoạt động đúng nghĩa.
Trong tương lai, chúng tôi có kế hoạch phát triển hỗ trợ cho các ngôn ngữ khác như swift/kotlin/python, hỗ trợ use case phía server, công cụ tạo tài liệu, công cụ linting/formatting, v.v.
Chúng tôi cũng đang tìm kiếm kỹ sư để cùng phát triển các công cụ này: https://riiid.com/ko/career/dx-software-engineer
Rất mong nhận được sự quan tâm của mọi người.
Kho lưu trữ pbkit: https://github.com/pbkit/pbkit
Tiện ích mở rộng vscode: https://marketplace.visualstudio.com/items?itemName=pbkit.vscode-pbkit
Tiện ích mở rộng Chrome: https://chrome.google.com/webstore/detail/pbkit-devtools/fjacmiijeihblfhobghceofniolonhca
10 bình luận
Ở công ty chúng tôi, vài năm trước đã cân nhắc giữa gRPC và rồi chọn Thrift. Thrift cũng có bộ sinh JS chưa hoàn thiện nên chúng tôi đã tự sửa, và rồi nhận ra đó là việc không đáng làm. Vì thế tôi từng nghĩ lẽ ra nên chọn gRPC, nhưng có vẻ bên đó tình hình cũng không hẳn tốt lắm.
Sau đó chúng tôi chọn GraphQL, và tôi khá hài lòng. Thỉnh thoảng tôi cũng lo về overhead giao tiếp, nhưng tôi thực sự không dùng nổi các giao thức dựa trên nhị phân.
Bọn mình đang dùng rất ổn ở Karrot Market!! ( _ _ )
Bọn mình cũng đang cố gắng tận dụng nó thật tốt cho messaging API nội bộ haha
Ồ, thật tuyệt vời!
Mà nếu ở công ty đã dùng được đến mức triển khai production rồi thì có lẽ không cần tiếp tục dùng kiểu phiên bản mang cảm giác pre-alpha như v0.0.44 nữa đâu.
Có vẻ sẽ có người chỉ nhìn số phiên bản rồi quyết định không dùng hu hu
Wow, anh/chị đã tự tay làm cả compiler luôn rồi. Thật tuyệt! (Mình từng thắc mắc code Golang được sinh ra như thế nào, nhưng có vẻ hiện tại mới chỉ hỗ trợ Deno và Node.js thôi nhỉ.) Mình thường dùng kèm
ts-protovớiprotochoặcbuf, nên cũng khá tò mò không biết mã TS được tạo ra khác vớits-protonhư thế nào.Có vẻ như đang đi đường vòng nhỉ https://github.com/trpc/trpc
bichi / Nếu API máy chủ được cung cấp bằng giao thức gRPC, thì có lẽ tRPC không phải là thứ để hỗ trợ việc này, đúng không~?
Tôi đồng ý rằng việc dùng stack gRPC/Protobuf không phải là lựa chọn lý tưởng. (Không phải do tôi muốn dùng mà là vì hoàn cảnh của công ty)
Tuy vậy, vì tRPC định nghĩa interface bằng
zod, nên có vẻ sẽ rất lý tưởng khi dùng TypeScript trên mọi nền tảng.Có lẽ sẽ khó áp dụng trong môi trường của bên tôi, nơi server được viết bằng Kotlin, và cũng có vẻ không phù hợp trong trường hợp giao tiếp với mobile native (Swift, Kotlin).
Các bài viết liên quan đến gRPC lúc nào cũng được hoan nghênh :)
Wow, còn có cả tiện ích mở rộng cho VS/Chrome trong code nữa.. tuyệt vời quá!! Ủng hộ bạn.
Bài giới thiệu được viết rất hay nên có vẻ những người ghé qua nhờ GeekNews sẽ nhận được nhiều thông tin hơn cả những ai chỉ vào Repo ^^;
Nếu những ai hiện đang dùng Protobuf để lại bình luận thì chắc sẽ giúp ích rất nhiều.