資料同步慢半拍?Webhook vs. Polling 深度比較:如何讓 WordPress 不再空轉
☰ 目錄 table-of-contents.md
排程每隔幾分鐘就去問一次 API「有新資料嗎」,一天問上幾百次,絕大多數的回應都是「沒有」——這就是 Polling 讓 WordPress 空轉的日常。Webhook 則反過來,有事件才主動敲門,即時又省資源,但也有它要處理的失敗情境。這篇就把兩種同步策略的取捨一次講清楚,幫你選對架構。
你是否遇過這種情況?客戶抱怨:「為什麼我在 CRM 改了資料,WordPress 網站上的會員狀態過了 10 分鐘才更新?」或者你的伺服器 CPU 長期維持在 80% 以上,查了半天才發現原來是有個排程每分鐘都在瘋狂敲外部 API 查詢訂單狀態。
這就是典型的「同步策略」選錯了。在 API 串接的世界裡,即時性(Real-time)與伺服器效能(Performance)往往像魚與熊掌。選對了 Webhook 或 Polling,你的系統如絲般滑順;選錯了,不是資料延遲,就是 API Rate Limit 被鎖到懷疑人生。
這篇文章,我將以資深工程師的角度,深入剖析這兩種機制的底層邏輯,並教你在 WordPress 中如何優雅地實作它們。
什麼是 Polling (輪詢)?那個「一直問」的討厭鬼
我們先來講講最直觀的 Polling。想像一下,你是一個坐在後座的小孩,每隔 30 秒就問前座的爸媽:「我們到了沒?」。
這就是 Polling (輪詢)。你的 WordPress 網站(客戶端)主動向外部系統(伺服器端)發送請求,檢查有沒有新資料。
Polling 的運作原理
- Short Polling: 設定一個固定的時間間隔(例如每 5 分鐘),不管有沒有新資料,時間到就發送 Request。
- Long Polling: 發送 Request 後,伺服器會「扣住」這個連線,直到有新資料才回傳,或者連線逾時(Timeout)。這比短輪詢即時,但對伺服器連線數消耗很大。
在 WordPress 中,我們通常使用 WP-Cron 來實現 Short Polling。以下是一個典型的 Polling 程式碼片段:
// 設定排程事件 (通常在啟用外掛時設定)
if ( ! wp_next_scheduled( 'roamer_check_external_orders' ) ) {
wp_schedule_event( time(), 'hourly', 'roamer_check_external_orders' );
}
// 綁定執行的函式
add_action( 'roamer_check_external_orders', 'eric_poll_external_api' );
function eric_poll_external_api() {
// 這是 Polling:主動去問 API
$response = wp_remote_get( 'https://api.external-system.com/orders/updates' );
if ( is_wp_error( $response ) ) {
return;
}
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
// 如果有資料才處理
if ( ! empty( $data['new_orders'] ) ) {
foreach ( $data['new_orders'] as $order ) {
// 更新 WordPress 資料庫
eric_update_order_status( $order );
}
}
}
Polling 的致命缺點
這段程式碼看起來很無害,對吧?但在高流量或即時性要求高的場景下,它有幾個大問題:
- 資源浪費 (Resource Waste): 假設你設定每分鐘檢查一次,但對方整天都沒有新訂單。你等於發送了 1440 次請求,其中 1439 次都是浪費頻寬和 CPU 的「空包彈」。
- 即時性差 (Latency): 如果你設定每 10 分鐘檢查一次,那麼資料最長可能會有 10 分鐘的延遲。這對於庫存同步或金流狀態來說,是不可接受的。
- API Rate Limit 殺手: 許多 API 都有請求限制(例如每小時 1000 次)。Polling 很容易在不知不覺中耗盡這些額度,導致你的 IP 被封鎖。
什麼是 Webhook?「別打給我,我會打給你」
相較於 Polling 的主動詢問,Webhook 採用的是「事件驅動」(Event-Driven) 的模式。這就像是你跟快遞說:「不用我一直打電話查包裹,包裹到了你直接傳簡訊通知我。」
當外部系統發生特定事件(例如:訂單成立、庫存變更)時,它會主動發送一個 HTTP POST 請求到你預先設定好的 WordPress URL(Endpoint),並帶著資料過來。
Webhook 的優勢
- 即時性 (Real-time): 事件發生當下,你的 WordPress 幾乎同時收到通知。延遲通常在毫秒級。
- 效能極佳 (Efficiency): 沒有「空包彈」。每一次連線都代表有實際的資料更新,伺服器不用做白工。
- 節省 API 額度: 因為你是被動接收,不會消耗主動呼叫 API 的 Rate Limit。
在 WordPress 中實作 Webhook 接收端
要在 WordPress 接收 Webhook,我們通常會使用 REST API 來建立一個自訂端點 (Endpoint)。這是我最推薦的作法:
add_action( 'rest_api_init', function () {
register_rest_route( 'roamer/v1', '/webhook-receiver', array(
'methods' => 'POST',
'callback' => 'eric_handle_incoming_webhook',
'permission_callback' => '__return_true', // 注意:這裡需要做安全驗證,下面會講
) );
} );
function eric_handle_incoming_webhook( WP_REST_Request $request ) {
// 獲取傳過來的 JSON 資料
$params = $request->get_json_params();
// 1. 驗證安全性 (非常重要!)
$signature = $request->get_header( 'x-signature' );
if ( ! eric_verify_webhook_signature( $params, $signature ) ) {
return new WP_Error( 'invalid_signature', '簽章驗證失敗', array( 'status' => 403 ) );
}
// 2. 處理業務邏輯
if ( isset( $params['event'] ) && $params['event'] === 'order.updated' ) {
$order_id = $params['data']['id'];
$status = $params['data']['status'];
// 更新 WordPress 訂單
eric_sync_order_status( $order_id, $status );
// 記錄 Log (工程師的好習慣)
error_log( "Webhook received for Order ID: $order_id" );
}
return new WP_REST_Response( array( 'success' => true ), 200 );
}
Polling vs. Webhook:我該選哪一個?
身為工程師,我們不做盲目的選擇。以下是我的決策判斷矩陣:
| 比較項目 | Polling (輪詢) | Webhook (回調) |
|---|---|---|
| 資料即時性 | 有延遲 (取決於輪詢間隔) | 極高 (接近即時) |
| 伺服器負載 | 高 (無效請求多) | 低 (只在有事時觸發) |
| 實作難度 | 低 (只要會寫 Loop) | 中 (需處理安全性與除錯) |
| 適用場景 | 舊系統不支援 Webhook、資料變動頻率極低 | 金流回調、庫存同步、CRM 資料更新 |
我的建議是:只要對方系統支援 Webhook,請無條件優先選擇 Webhook。 只有在對方是老舊系統,完全沒有 Event 機制時,才不得已使用 Polling,並且要配合 Exponential Backoff (指數退避) 機制來減少伺服器負擔。
資安警示:Webhook 不能「裸奔」
這點我必須要囉嗦一下。很多新手工程師接 Webhook 時,只開了一個 API 端點就覺得沒事了。這超級危險!
因為 Webhook 的 URL 通常是公開的,如果沒有驗證機制,駭客可以用 Postman 偽造一個請求打給你的 WordPress,竄改你的訂單狀態或會員資料。這就是典型的 CSRF 變體攻擊。
如何防護?
- 驗證簽章 (Signature Verification): 大多數正規的服務 (如 Stripe, LINE, GitHub) 發送 Webhook 時,都會用一個 Secret Key 對內容進行 HMAC 加密,放在 Header 裡。你必須在接收端用同樣的 Key 算一次,確保 Header 裡的簽章跟算出來的一樣。
- IP 白名單: 如果對方有提供固定的發送 IP,可以在 Nginx 或 Cloudflare 層級直接擋掉非白名單的請求。
實戰案例:WooCommerce 訂單同步到外部 CRM
假設你想把 WooCommerce 的新訂單即時傳送到外部 CRM。
錯誤示範 (Polling):
在 CRM 端寫一個 Script,每 60 秒呼叫一次 WooCommerce API GET /wp-json/wc/v3/orders。結果:如果你的商店一天只有 10 張單,CRM 還是會發送 1440 次請求,WooCommerce 網站被拖慢,主機商寄信警告資源使用過量。
正確示範 (Webhook):
1. 在 WooCommerce 後台 -> 設定 -> 進階 -> Webhook,新增一個 Webhook。
2. 主題選「訂單已建立 (Order Created)」。
3. 傳送網址填入 CRM 的接收端點 (例如 n8n 的 Webhook URL)。
4. 結果:只有在客戶下單的那一秒,WooCommerce 才會發送一次請求。省資源、零延遲。
結論
在 2025 年的現在,「即時性」已經是使用者體驗的標配。Webhook 不僅讓你的資料同步更即時,更是展現系統架構師功力的分水嶺。別再讓你的伺服器當個焦慮的家長,每分鐘都在問「到了沒?」,改用 Webhook,讓資料自己找上門吧!
希望這篇技術筆記對你的開發之路有幫助。如果你在串接 API 或處理 Webhook 驗證上遇到瓶頸,或者你的網站因為錯誤的同步策略而慢到不行,歡迎來找我們聊聊。
遇到 API 串接難題?立即聯繫浪花科技,讓我們幫你打造高效能架構!
延伸閱讀
常見問題
Webhook 和 Polling 有什麼差別?
資料同步該選 Webhook 還是 Polling?
Polling 輪詢有哪些缺點?
在 WordPress 中如何實作 Webhook 接收端?
Webhook 端點為什麼一定要做簽章驗證?
訂閱免費電子報
把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。