Webhooks、WebSockets 與 gRPC 比較
作者 Uttam Singh

每個讀取區塊鏈資料的應用程式都會遇到同樣的架構問題:資料該如何送達你的系統?每隔幾秒輪詢一次 API,會浪費運算資源、錯過事件,還會增加延遲。改用推送資料的方式,就得選定一種傳遞模型。
即時資料傳遞主要由三種協定主導:webhooks、WebSockets 和 gRPC。它們並不能互相替代。Webhooks 在事情發生時通知你的後端。WebSockets 將即時資料串流至瀏覽器。gRPC 則在後端服務之間以高吞吐量傳輸資料。選錯協定,代價會在之後才顯現:漏接的事件、浪費的運算資源,或是一場你原本沒打算進行的系統重新設計。
Webhooks、WebSockets 和 gRPC 是什麼?
這三者都能將資料從伺服器傳送到你的應用程式,而不需要輪詢。相似之處僅止於此。
webhook 顛覆了一般的 API 方向。你的程式不去呼叫伺服器,而是伺服器在關注的事情發生時,呼叫你註冊的 URL,並附上 JSON 資料。Webhooks 設定起來簡單;代價是你無法控制資料抵達的時機或格式。
WebSocket 是客戶端與伺服器之間持久的 TCP 連線。任一方都能在任何時間傳送小型二進位資料訊框,而不需要重新建立連線。這個協定一開始是 HTTP 請求,一旦雙方同意升級,就會轉換成原始 socket。
gRPC 是一種遠端程序呼叫(RPC)框架:讓一個服務能像呼叫本地函式一樣呼叫另一個服務中的函式的系統。它是 Google 內部 RPC 系統 Stubby 的公開後繼者,運行於 HTTP/2 之上,以 Protocol Buffers 序列化資料,並支援四種串流模式,包括完整的雙向串流。它是為了讓後端服務快速在機器之間傳輸結構化資料而打造的,內建重試機制、期限(deadline)傳播和型別化的合約。
Webhooks 是如何運作的?
Webhooks 顛覆了 API 模型。不是你去呼叫伺服器,而是伺服器來呼叫你。你向提供者註冊一個 URL,告知哪些事件是你關注的,然後等待。事情發生時,提供者會將 JSON POST 至你的端點,並預期收到 2xx 回應。
app.post('/webhook', (req, res) => {
const sig = req.headers['x-alchemy-signature'];
if (!verify(sig, req.rawBody, SECRET)) return res.status(401).end();
queue.enqueue(req.body);
res.status(200).end();
});上面的程式碼片段是一個 webhook 處理常式:它驗證簽章、將 payload 排入佇列,然後回傳 200。上面這個簡易版本,也正是大多數正式環境 webhook 中斷事故的根源。真正將玩具等級的處理常式和正式環境等級的處理常式區分開來的,是三件事的處理方式:簽章驗證、重試行為、以及突發過載。
第一種失效模式是脆弱的簽章處理。提供者會用共享密鑰對每次傳遞進行 HMAC 簽章(Alchemy 使用 X-Alchemy-Signature,Stripe 使用 Stripe-Signature),而你的處理常式必須重新計算 HMAC,以固定時間比較的方式來避免計時攻擊,並拒絕任何時間戳記超過五分鐘的請求。呼叫 verify() 只是一行程式碼;但要正確地做到這件事,得花上好幾行。任何一個步驟被省略,你等於是在信任任何知道你端點 URL 的程序。
第二種失效模式是在重試機制下的非冪等(non-idempotent)處理。當傳遞失敗時(逾時、部分中斷、5xx 回應),提供者會以指數退避的方式重試(通常從一秒開始加倍、加上抖動、上限為一小時),持續數小時或數天,最終才會把 payload 送進死信佇列。Webhooks 保證至少一次傳遞,而非恰好一次(恰好一次在分散式系統中是不可能達成的),所以重複傳遞是常態。你的處理常式必須具備冪等性:處理同一個事件兩次,應該和只處理一次得到相同的結果。用去重儲存體追蹤事件 ID,遇到重複時回傳 200。
第三種失效模式是突發過載,這也是在規模擴大後最容易讓 webhook 系統崩潰的一種。單一鏈上事件就可能觸發數百萬次同時發生的傳遞。如果你的端點成為瓶頸,提供者的重試佇列就會變成攻擊你的 DoS 來源。
在區塊鏈基礎設施中,webhooks 是事件驅動工作流程的核心。我們的 Custom Webhooks 支援地址活動監控、NFT 轉移提醒,以及跨越 30 多條 EVM 鏈加上 Solana 的 GraphQL 過濾智能合約事件,全部以 HTTP POST 回呼的方式傳送到你的端點。
WebSockets 是如何運作的?
WebSocket 一開始是一個帶有 Upgrade: websocket 標頭的普通 HTTP 請求。伺服器回覆 HTTP 101(Switching Protocols),從那一刻起,這個連線就不再使用 HTTP。這個協商過程就是 WebSocket 交握(handshake)。之後留下的是一條原始 TCP socket,上面覆蓋了一層薄薄的訊框機制:每則訊息不需要標頭,也沒有請求—回應循環。
移除 HTTP 讓 WebSockets 每則訊息的成本大幅降低。每則 WebSocket 訊息只帶有 2-6 位元組的額外負擔(一個 FIN 位元、opcode,以及 payload 長度)。相比之下,HTTP 的每個請求都包含數百位元組的標頭。以每秒 100 則訊息計算,WebSocket 的額外負擔約為每秒 600 位元組,而等量的 HTTP 流量則是每秒 60,000 位元組。
const ws = new WebSocket('wss://eth-mainnet.g.alchemy.com/v2/KEY');
ws.send(JSON.stringify({
jsonrpc: '2.0', id: 1, method: 'eth_subscribe',
params: ['newHeads']
}));
ws.on('message', (data) => handleBlock(JSON.parse(data)));WebSocket 連線是有狀態且長時間存在的。任一方都可以在任何時間傳送資料,不需要等待對方。伺服器會定期傳送 ping 訊框;客戶端則以 pong 訊框回應,證明連線仍然存活。少了這些心跳訊號,失效的連線(「殭屍連線」)會白白佔用伺服器資源,反向代理伺服器也會在閒置 30-120 秒後將連線關閉。
代價是:連線的生命週期由你自己負責管理,而這個生命週期裡涉及的細節比表面看起來更多。連線斷線時,客戶端必須重新連線,而且必須以指數退避方式重連(每次重試間隔逐漸拉長),否則數千個客戶端同時重連會壓垮伺服器。當你在負載平衡器後面運行多台 WebSocket 伺服器時,負載平衡器必須將特定客戶端的每次重連都導回同一台機器,因為只有那台機器持有該客戶端的訂閱狀態。這條路由規則有個名稱:session affinity(連線親和性)。而如果一則訊息源自某台伺服器,卻需要傳給連線在另一台伺服器上的客戶端,這些伺服器之間就必須跨節點共享狀態。WebSockets 提供的只是傳輸協定;建構在它之上的一切都得靠你自己完成。
對於區塊鏈應用程式而言,WebSockets 是即時事件訂閱的標準介面。Ethereum 的 eth_subscribe 端點 透過持久的 WebSocket 連線推送新的區塊標頭、日誌事件和待處理交易。我們的 Smart WebSockets 在基礎協定之上,加入了過濾訂閱與自動重連功能。
將即時資料串流至瀏覽器,正是 WebSockets 被設計來解決的問題。在 WebSockets 出現之前,可用的替代方案(長輪詢、伺服器發送事件)不是每則訊息都要付出完整的 HTTP 額外負擔,就是只能單向運作。WebSockets 在原本原始 TCP socket 通常無法存在的地方——瀏覽器——提供了持久、低額外負擔、雙向的連線。
這種清晰的定位,同時也是它的侷限。當消費端不是瀏覽器、資料是結構化的、流量很大,而你又需要 WebSockets 從未承諾過的東西:型別化的架構定義、多工串流、期限傳播、背壓機制——這時 WebSockets 就會顯得力不從心。而這正是 gRPC 被設計來解決的問題。
gRPC 是如何運作的?
gRPC 從設計空間的另一端出發。Webhooks 是 HTTP 回呼、WebSockets 是 TCP 之上的一層薄薄訊框機制,而 gRPC 則是一個以型別化合約為核心的完整 RPC 框架。在撰寫任何業務邏輯之前,你要先寫一個 .proto 檔案,定義服務以及它所收發的訊息。protobuf 編譯器會將這個檔案轉換成你所用語言的客戶端與伺服器端產生碼(稱為 stub),因此在程式碼中呼叫遠端方法,看起來就像呼叫本地函式一樣。
service Geyser {
rpc Subscribe(stream SubscribeRequest)
returns (stream SubscribeUpdate);
}傳輸層是 HTTP/2,搭配 Protocol Buffers 做序列化。兩者結合,讓 gRPC 相較於典型的 REST + HTTP/1.1 + JSON 技術堆疊,具備三項優勢:
- 多工機制消除了 head-of-line blocking(隊頭阻塞)問題——這是 HTTP/1.1 的問題,指單一緩慢的回應會拖住同一連線上後續的每個請求。在 gRPC 中,每次呼叫都以獨立的 HTTP/2 串流運行,共享同一條 TCP 連線。Square 就是眾多將內部服務對服務流量遷移到 gRPC 以降低連線額外負擔的工程團隊之一。
- 標頭壓縮(HPACK)以精簡的參照取代重複的標頭。在 RPC 流量中,同樣的方法、內容類型和驗證標頭會在每次呼叫中重複出現,這項機制將標頭額外負擔降低了 85-90%。
- Protocol Buffers 將訊息序列化為緊湊的二進位格式,而非文字格式。在未壓縮的環境中,payload 比 JSON 小 34%,反序列化速度則最多快上 6 倍,視所用語言而定。代價是:二進位 payload 無法直接以人眼閱讀,因此需要 grpcurl 或 Postman 之類的工具來檢視流量。
gRPC 支援四種串流模式。Unary(一個請求、一個回應)的運作方式類似標準 API 呼叫。Server streaming(一個請求、多個回應)適合資訊流與資料推送。Client streaming(多個請求、一個回應)用於處理批次上傳。Bidirectional streaming(雙方各自獨立傳送)則為即時、有狀態的互動提供支援。
gRPC 並不是一個通用協定。它是為了在你完全掌控兩端的機器之間,以高速率傳輸結構化資料的後端服務而窄向優化的,而正是這個聚焦的利基場景,讓撰寫架構定義與執行程式碼產生所付出的前期成本能夠得到回報。讓 gRPC 佔據這個位置的,不只是二進位編碼,更是內建於協定中的正式環境級基礎機制。期限傳播 將每個逾時設定轉換成一個絕對的時間點,並貫穿整個呼叫鏈。如果服務 A 設定了 5 秒的期限並呼叫服務 B,而服務 B 又呼叫服務 C,每一跳都能確切知道還剩多少時間。期限一到,所有下游工作都會取消並釋放資源。流量控制 繼承自 HTTP/2:當消費端速度跟不上時,傳送端會自動放慢速度來配合。這是內建的背壓機制,而 webhooks 和 WebSockets 都沒有原生提供這種功能。
在 Solana 上,gRPC 支撐著目前可用的最高效能資料串流。Yellowstone gRPC 插件(Geyser)直接載入驗證節點的記憶體空間,在帳戶與交易更新寫入磁碟之前就先擷取它們,將其序列化為 protobuf,再透過持久的 HTTP/2 串流推送出去。
這三種協定在效能上如何比較?
吞吐量與延遲基準測試為服務對服務通訊劃出了清晰的界線。二進位 protobuf 編碼加上 HTTP/2 多工,讓 gRPC 相較於 REST over HTTP/1.1 具有可衡量的更高吞吐量與更低延遲,在 payload 小且並行呼叫數量多的工作負載中尤其明顯。
WebSockets 則在另一項比拚中勝出:瀏覽器與伺服器之間串流的每則訊息額外負擔最低。初次交握完成後,每則訊息只帶有 2-6 位元組的訊框額外負擔,且瀏覽器原生的 WebSocket API 就能處理連線,不需要 proxy 或建置工具。
Webhooks 並不是為了效能而設計的。每次傳遞都是一個獨立的 HTTP 請求,帶有完整的連線建立額外負擔。它們解決的是另一種問題:可靠的、非同步的事件通知,在這種場景中,簡單性和相容性比吞吐量更重要。
區塊鏈相關的具體數字也印證了這個模式。Solana 的 Yellowstone gRPC 串流資料的 slot 延遲約為 5 毫秒;原生 WebSockets 傳遞延遲約為 10 毫秒;RPC 輪詢則落後至約 150 毫秒。協定複雜度每提升一個層級,都能換來可衡量的速度提升。
每種協定在什麼情況下會出問題?
Webhooks 在高頻事件下會出現問題。在每秒數百次傳遞的規模下,每次回呼的 HTTP 額外負擔就會成為瓶頸。突發事件會造成驚群效應(thundering-herd)問題:一個重大的鏈上事件會同時觸發數百萬次 webhook 傳遞,讓提供者的重試佇列和消費端端點都不堪負荷。Webhooks 也是嚴格單向的。任何需要雙向通訊的使用案例都需要另一種協定。正如一位打造過 webhooks 基礎設施的工程師所描述的:「webhooks 運行起來很痛苦。」
WebSockets 在規模擴大時會遇到問題。每條連線都佔用伺服器資源(閒置時 2-10 KB,活躍時更多)。經過調校的伺服器可以處理超過 50 萬條閒置連線,但真正的瓶頸在於連線流動:TLS 交握每個 CPU 核心每秒只能處理 1,000-3,000 次。當伺服器重啟時,所有已連線的客戶端會同時重連,形成重連風暴,甚至可能演變成完全中斷。在 Solana 上,標準 WebSocket 實作「在負載下變得不可靠」,效能下降且經常斷線,這也促使 Solana 團隊轉向 gRPC。
gRPC 在瀏覽器端會遇到問題。瀏覽器無法原生使用 gRPC。gRPC-Web 協定 透過 proxy(通常是 Envoy)來彌合這道差距,但在過程中會失去 client streaming 和 bidirectional streaming 的能力。二進位 protobuf payload 無法用 curl 或瀏覽器開發者工具檢視,這讓 gRPC 不太適合注重開發者體驗的公開 API。protobuf 工具鏈(架構定義、程式碼產生、建置整合)也為簡單的整合增加了不小的建置成本。
該如何在 webhooks、WebSockets 和 gRPC 之間做選擇?
先從你的使用案例所需要的通訊模式著手判斷。
Webhooks 是預設選項。如果你的後端只需要在單一事件發生時得知(交易確認、NFT 轉移、付款完成),且事件頻率維持在每秒數百次以下,webhooks 就是成本最低的整合方式,能相容於任何語言、任何框架、任何防火牆。不需要持久連線、不需要串流基礎設施、也不需要客戶端 SDK。
當事件頻率上升,或你需要雙向的資料流動時,就輪到 WebSockets 出場。想想即時價格報價器、訂單簿更新、mempool 監控、協作式儀表板——任何情境只要持久連線到瀏覽器能讓你免於不斷敲打 API,就適合用 WebSockets。原生瀏覽器支援、不需要 proxy,訊框額外負擔以位元組計算。
當你需要後端服務之間的最大吞吐量時,選擇 gRPC。Indexer 資料管線、驗證節點資料串流、微服務對微服務的通訊,以及任何你能掌控連線兩端的工作負載,都能從二進位序列化、多工串流、型別化合約和內建背壓機制中受益。代價在於工具鏈:protobuf 架構定義、程式碼產生、不支援原生瀏覽器。當效能與可靠性的重要性超過建置複雜度時,這樣的投入是值得的。
當架構需要時,可以將它們組合使用。許多正式環境系統會同時使用這三種協定:gRPC 將資料從驗證節點串流到 indexer,WebSockets 將處理後的資料推送到瀏覽器儀表板,而 webhooks 則將離散事件通知外部系統。沒有理由非得全押在單一協定上不可。
在 Alchemy 上打造即時區塊鏈資料應用
我們在超過 100 條鏈上支援這三種協定。
我們的 Custom Webhooks 以 HTTP POST 回呼的方式傳遞交易確認、地址活動和 NFT 事件,並附帶 HMAC 簽章驗證與自動重試機制。GraphQL 過濾器讓你能精準訂閱應用程式所需的合約事件。
Smart WebSockets 提供經過過濾的 eth_subscribe 串流,並具備自動重連功能,為即時前端應用程式降低延遲。
對於處理大量資料的 Solana 團隊,我們的 Yellowstone gRPC streaming 能直接從驗證節點記憶體傳遞帳戶更新與交易資料,延遲低於 10 毫秒。
這三項服務都在我們的免費方案中提供。無需合約、無需候補名單。立即註冊,幾分鐘內就能開始串流資料。
常見問題
Webhooks、WebSockets 和 gRPC 之間的主要差異是什麼?
Webhooks 是用於伺服器對伺服器事件通知的單向 HTTP 回呼;WebSockets 提供客戶端與伺服器之間持久、雙向的連線;gRPC 則是建構在 HTTP/2 之上的 RPC 框架,專為具有型別化合約的高吞吐量服務對服務通訊而設計。
什麼時候該用 webhooks 而不是 WebSockets 或 gRPC?
當你需要離散事件通知(例如交易確認或 NFT 轉移),事件頻率在每秒數百次以下,且不需要持久連線時,就該使用 webhooks。它們是最簡單的整合方式,不需要專用的客戶端 SDK 或基礎設施。
什麼時候 WebSockets 是更好的選擇?
WebSockets 最適合用於持續、即時地將資料串流至瀏覽器客戶端,例如即時價格報價器、訂單簿更新或儀表板。它們提供原生瀏覽器支援,初次交握後每則訊息的額外負擔很低(2-6 位元組)。
gRPC 是為了解決什麼問題而設計的?
gRPC 是為了讓後端服務以高速率傳輸結構化資料而優化的,例如 indexer 資料管線或驗證節點資料串流。它提供二進位序列化、多工串流、透過 Protocol Buffers 實現的型別化合約、內建背壓機制以及期限傳播。
我能否在同一個系統中同時使用 webhooks、WebSockets 和 gRPC?
可以,許多正式環境系統會同時結合這三者:gRPC 用於後端服務對服務通訊,WebSockets 用於即時瀏覽器更新,webhooks 則用於通知外部系統離散事件。每種協定解決的是不同的架構層面。
這些協定之間的效能差異是什麼?
gRPC 透過二進位編碼與 HTTP/2 多工,提供最低的延遲與最高的吞吐量;WebSockets 為瀏覽器串流提供低額外負擔(每則訊息 2-6 位元組);webhooks 由於完整的 HTTP 往返額外負擔,每則訊息的成本最高,但更重視簡單性而非效能。
每種協定的主要缺點是什麼?
Webhooks 在高頻事件與突發流量下容易出問題;WebSockets 在規模擴大時面臨連線流動與驚群式重連風暴的挑戰;gRPC 需要建置 protobuf 工具鏈、不支援原生瀏覽器,且需要 proxy(gRPC-Web)才能供 Web 客戶端使用。
Alchemy 如何為區塊鏈應用程式支援這些協定?
Alchemy 提供 Custom Webhooks,可在 100 多條鏈上進行事件通知;提供 Smart WebSockets,實現具備自動重連功能的過濾 eth_subscribe 串流;並在 Solana 上提供 Yellowstone gRPC streaming,直接從驗證節點記憶體傳遞帳戶更新,延遲低於 10 毫秒。
相關總覽

打造區塊鏈魔法
Alchemy 結合最強大的 Web3 開發者產品與工具,並提供資源、社群與卓越的支援。


