Backend Engineering·2026年6月4日·10 分鐘閱讀
為什麼我在服務之間選 gRPC,以及它真實的坑
L
Louis Wu
後端工程師,在多個 Go 微服務專案用 gRPC 串接服務間通訊。
當服務開始拆分,第一個要決定的就是:服務之間怎麼溝通。多數人預設用 REST/JSON,這沒錯,但在內部服務之間,我越來越常選 gRPC。這篇講我選它的理由,以及實際用下來真實的坑——因為它不是沒有代價的。
為什麼是 gRPC
在「服務對服務」這種機器跟機器的溝通場景,gRPC 有幾個對我很實際的好處:
- 強型別的契約:用 protobuf 定義介面與訊息,產生各語言的程式碼。欄位型別、必填與否都寫死在契約裡,不會有「這個欄位到底是字串還是數字」的模糊
- 效能:protobuf 是二進位、體積小,又走 HTTP/2,比文字的 JSON over HTTP/1.1 省頻寬、延遲低
- 串流:HTTP/2 原生支援雙向串流,做即時推送、大量資料分批傳很自然
- 跨語言:同一份 proto 可以產 Go、Java、各種語言的 client,多語言團隊很受用
對外公開的 API 我還是會用 REST(瀏覽器友善、好除錯、生態成熟),但內部服務之間,gRPC 的型別安全與效能很值得。
契約優先,這是最大的價值
gRPC 逼你「契約優先」:先寫好 proto,再產生程式碼。這個流程本身就是好習慣——服務的介面被明確定義、版本化、可追蹤,而不是散在各個 handler 裡靠口頭約定。
改了 proto,所有用到的服務在編譯期就會知道對不對得上,不會等到正式環境才發現欄位接錯。這種「錯誤提前到編譯期」的安全感,是我最看重的。
真實的坑
講完優點,講代價,這才是實戰文該有的部分。
不好用瀏覽器和 curl 直接打 REST 你可以用瀏覽器、curl、Postman 隨手戳。gRPC 是二進位,沒有對應工具就很難手動測。雖然有 grpcurl 之類的工具,但「隨手 curl 一下」的便利性確實沒了。這也是我把對外 API 留給 REST 的原因之一。
錯誤處理要重新適應 gRPC 有自己的一套狀態碼,跟 HTTP 狀態碼不完全對得上。團隊要約定好「什麼情況回什麼 gRPC 狀態碼」,否則各服務各自亂回,呼叫端很難統一處理。
版本相容要小心 protobuf 對欄位的增刪有它的相容規則(欄位編號不能亂改、不能重用已刪除的編號)。一旦不照規則改,舊的 client 解析新的訊息就會出怪事。團隊要建立「proto 怎麼演進」的紀律。
負載平衡比想像複雜 gRPC 走 HTTP/2 長連線,傳統那種「每個請求各自連線」的負載平衡器沒辦法好好把請求分散到後端。要嘛用支援 gRPC 的 L7 負載平衡、要嘛在 client 端做負載平衡。這是很多人上正式環境才踩到的坑。
我的取捨原則
- 對外、給瀏覽器、要好除錯:REST/JSON
- 內部服務之間、重型別與效能、要串流:gRPC
- 不要為了用而用。如果你只有兩三個服務、流量也不大,REST 可能就夠了,硬上 gRPC 只是多扛一套工具鏈
小結
gRPC 在「服務對服務」的場景,用契約優先、強型別、二進位高效,解決了 REST 在內部通訊的一些痛點。但它的代價也很真實:不好手動測、錯誤處理要重學、版本與負載平衡要小心。
工具沒有絕對好壞,只有適不適合。想清楚你是在解決「對外開放」還是「內部高效通訊」的問題,答案通常就出來了。
#gRPC#Go#微服務#API#Protobuf