本文提供 Pub/Sub 提取訂閱項目的常見疑難排解提示。如要進一步瞭解提取訂閱項目,請參閱提取訂閱者指南。
如要有效監控 Pub/Sub 訂閱項目,建議先查看傳遞延遲時間健康狀態分數 (subscription/delivery_latency_health_score),瞭解哪些因素可能導致延遲時間超出預期或增加。
最舊未確認訊息的存在時間持續增加
oldest_unacked_message_age
是監控 Pub/Sub 訂閱項目運作狀態的重要指標。這項指標會測量訂閱項目待處理訊息中,最舊訊息的存在時間 (以秒為單位),且訂閱者尚未確認該訊息。這項指標可提供寶貴的洞察資料,協助您瞭解潛在的處理延遲或瓶頸。
監控訊息待處理項目可確保訊息及時有效處理。追蹤最舊未確認訊息的存在時間,有助於主動找出消費者落後的情況。這樣一來,您就能及早介入,解決可能導致效能降低的問題。
您可以調查一些常見的待辦事項問題,包括:
用戶端設定問題
如果 oldest_unacked_message_age
和 num_undelivered_messages
指標同時增加,可能表示訂閱者跟不上訊息量。在這種情況下,請著重調查訂閱者元件:
用戶端健康狀態:分析主機上訂閱端用戶端的資源用量,例如 CPU、記憶體和網路頻寬。找出可能阻礙處理效率的壓力點。
用戶端程式碼:查看近期程式碼變更並檢查錯誤記錄。訂閱者程式碼中的錯誤或效率不彰之處,可能會大幅影響訊息處理率。請注意,特定訊息可能會有問題。舉例來說,多則訊息可能需要同時存取資料庫中的同一列。這種行為可能會導致爭用和高延遲。
配額限制:確認您未超出主機服務設定的任何 Pub/Sub 配額或限制。如果訂閱者託管於 Trusted Cloud by S3NS,請查看 Compute Engine 或 GKE 資源配額,避免發生潛在瓶頸。
訂閱者對訊息表示負面確認
訂閱者對訊息發出否定確認 (nack) 時,會向 Pub/Sub 發出信號,表示訊息無法順利處理。Pub/Sub 接著會嘗試重新傳送同一則訊息。如果系統對郵件重複傳送 NACK,就會導致郵件重複,且可能大幅延遲郵件傳送時間。
請注意,對訊息執行 NACK 作業,不保證下一次提取作業會擷取不同訊息。Pub/Sub 的重新傳送政策可能會繼續重新傳送 NACK 訊息,然後才傳送新訊息。因此,請勿將 nack 做為篩選或略過特定訊息的方法。請改為設定重試政策 (最好是指數輪詢),針對稍後可能可以處理但需要較長時間才能重新傳送的個別訊息,採取輪詢方式。
如果需要刻意略過特定訊息,建議您確認這些訊息,即使不會處理也一樣。這樣一來,系統就會將他們從訂閱項目中移除,避免不必要的重新傳送作業,並減少資源耗用。無論是否刻意,將訊息保持在未確認狀態都會造成待處理工作問題,並導致重複傳送。
傳送延遲時間長
Pub/Sub 的傳送延遲時間是指訊息從發布者傳送至訂閱者所需的時間。接下來的章節將說明高傳送延遲的可能原因。
訂閱人數不足
如果用戶端使用 StreamingPull,請維持多個 StreamingPull 開放連線至訂閱項目,以確保延遲時間一律很短。如果沒有有效的訂閱者連線,Pub/Sub 就無法及時傳送訊息。單一串流可能會成為單點故障,增加延遲風險。subscription/open_streaming_pulls
指標可顯示有效串流連線的數量。請使用這項功能,確保您有足夠的串流來處理傳入的訊息。
如果用戶端使用一元提取,請對訂閱項目保留多個未完成的提取要求,以確保延遲時間一律很短。如果要求不頻繁,可能會導致待處理工作累積大量訊息,進而增加延遲時間。這個方法有助於盡量減少連線中斷,並縮短傳送延遲時間。
如果需要高處理量和低延遲,且作業負擔和處理成本盡量要低,建議使用高階用戶端程式庫。根據預設,高階用戶端程式庫會使用 StreamingPull API,因為這個 API 通常是減少延遲的最佳選擇。高階用戶端程式庫包含預先建構的函式和類別,可處理驗證、輸送量和延遲最佳化、訊息格式化等功能的基礎 API 呼叫。
用戶端設定問題
請參閱「用戶端設定問題」。
待處理項目過多
請注意,Pub/Sub 訂閱項目中未確認的訊息積壓,本質上會增加端對端延遲時間,因為訂閱者不會立即處理訊息。
排序鍵和僅傳送一次
排序鍵和「只傳送一次」是實用功能,但需要 Pub/Sub 內額外協調,才能確保正確傳送。這項協調作業可能會降低可用性並增加延遲時間。雖然穩定狀態下的差異極小,但任何必要的協調步驟都可能導致延遲時間暫時增加或錯誤率提高。如果啟用排序功能,系統必須先確認含有相同排序鍵的訊息,才能傳送含有排序鍵的訊息。
請考慮應用程式是否絕對需要訊息排序或僅傳送一次。如果延遲時間是您的首要考量,盡量減少使用這些功能有助於縮短訊息處理延遲時間。
訊息大小增加
訊息大小突然增加可能會延長 Pub/Sub 與用戶端之間的傳輸時間,並導致用戶端處理訊息的時間變慢。
如果發現傳送延遲時間變長,可以使用 topic/message_sizes
指標 (依 topic_id
分組) 檢查訊息大小。將訊息大小的任何尖峰與觀察到的效能問題相互關聯。
缺少訊息
如果懷疑系統無法順利將訊息傳送給訂閱者,可能的原因如下。
在有多個取用者的 Pub/Sub 訂閱項目中分配訊息
在 Pub/Sub 中,訊息可能會不平均地分配給消費者。這是因為 Pub/Sub 會在有效消費者之間分配訊息,以提高效率。有時,單一消費者收到的訊息可能會比預期少,或是與其他消費者收到的訊息不同。
請注意,客戶可能已有未處理的訊息,而未確認的訊息積壓不一定代表您會在下一個提取要求中收到這些訊息。請注意,消費者可能是使用 Trusted Cloud 控制台或 Google Cloud CLI 提取訊息的人,也可能是在本機執行自訂訂閱者來檢查訊息的人。
對於一元 Pull 用戶端,您可能會發現某些提取要求傳回零則訊息。如「訂閱者人數不足」一節所述,建議您保留多個未完成的提取要求,因為部分要求可能會傳回少於設定訊息數上限的訊息,甚至沒有訊息。
如果懷疑有上述行為,請調查是否有消費者同時連結至訂閱項目,並檢查這些消費者。
篩選訂閱項目
檢查訂閱項目是否已附加篩選器。這樣一來,您就只會收到符合篩選條件的訊息。Pub/Sub 服務會自動確認不符合篩選條件的訊息。請考量篩選器對待辦事項指標的影響。
使用 returnImmediately
選項
如果用戶端使用一元 Pull,請檢查 returnImmediately
欄位是否設為 true。這個欄位已淘汰,可讓 Pub/Sub 服務立即回應提取要求,即使傳回的訊息為空也一樣。即使有待處理的訊息,這也可能導致提取要求傳回 0 則訊息。
用戶端設定問題
如果您使用 Java 用戶端程式庫,並透過 setChannelProvider()
方法以自訂 gRPC 管道初始化訂閱者,請務必在建構 TransportChannelProvider
時,確保 maxInboundMessageSize
設定至少為 20 MB (與程式庫的預設值相符)。如果這個值小於 10 MB,系統就無法正常接收大於 maxInboundMessageSize
的訊息。設定這項設定的常見方法是 InstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize()
和 ManagedChannelBuilder.maxInboundMetadataSize()
。
處理重複項目
如果訂閱者無法在確認期限內確認訊息,Pub/Sub 就會傳送重複訊息。這會導致系統重新傳送訊息,造成重複的印象。你可以使用 subscription/expired_ack_deadlines_count
指標,評估訂閱者錯過確認期限的頻率。進一步瞭解如何監控確認期限到期日。
為了減少重複比率,請延長訊息期限。
- 用戶端程式庫會自動處理期限延長,但您可設定最大延長期限的預設限制。
- 如果您正建構自己的用戶端程式庫,請使用
modifyAckDeadline
方法延長確認期限。
如果訂閱者提取訊息的速度快於處理和確認的速度,部分訊息可能會過期,因此需要延長期限。不過,如果訂閱者仍感到壓力過大,一再延長期限最終會失敗。最糟糕的情況下,這可能會導致訂閱者收到大量重複項目,加劇待處理事項。過期重複項目,然後產生新的重複項目。
為避免訂閱者負擔過重,請減少訂閱者一次提取的訊息數量。這樣一來,訂閱者就能在期限內處理較少的訊息。減少訊息過期和重新傳送的次數。
如要減少訂閱者一次提取的訊息數量,請在訂閱者的流量控制設定中,減少未處理訊息的上限數量。沒有適用於所有情況的值,因此您必須根據處理量和訂閱者容量調整未處理訊息上限。請注意,每項應用程式處理訊息的方式不同,確認訊息所需的時間也不同。
強制重試
如要強制 Pub/Sub 重試訊息,請傳送 nack
要求。如果沒有使用高階用戶端程式庫,請傳送 modifyAckDeadline
要求,並將 ackDeadlineSeconds
設為 0。
排序鍵
當 Pub/Sub 重新傳送含有排序鍵的訊息時,也會重新傳送所有後續含有相同排序鍵的訊息,即使這些訊息先前已確認過也一樣。這是為了保留序列的順序。不過,我們無法嚴格保證系統只會在序列中先前的訊息成功確認後,才傳送相依訊息。
訂閱者正在否定確認訊息
請參閱訂閱者正在 NACK 訊息。
排解 StreamingPull 訂閱項目問題
要求延遲指標與端對端傳送延遲時間之間的關係
如果是 StreamingPull,指標 serviceruntime.googleapis.com/api/request_latencies 代表串流開啟的時間。這項指標無法協助判斷端對端傳送延遲時間。
請改用傳遞延遲時間健康狀態分數,而非要求延遲時間指標,藉此檢查哪些因素導致端對端傳遞延遲時間增加。
StreamingPull 連線關閉,但狀態不是 OK
StreamingPull 串流一律會以非 OK 狀態關閉。與一元 RPC 的錯誤狀態不同,StreamingPull 的這個狀態僅表示串流已中斷。要求並未失敗。因此,雖然 StreamingPull API 的錯誤率可能高達 100%,但這是設計上的行為。
由於 StreamingPull 串流一律會因錯誤而關閉,因此診斷錯誤時,檢查串流終止指標並無助益。請改為關注 StreamingPull 回應指標 subscription/streaming_pull_response_count
,並依 response_code
或 response_class
分組。
請找出下列錯誤:
如果訂閱項目待處理的訊息是以已停用的 Cloud KMS 金鑰加密,就可能發生前提條件失敗錯誤。如要繼續提取,請還原金鑰存取權。
如果 Pub/Sub 無法處理要求,可能會發生「無法使用」錯誤。這很可能是暫時性問題,用戶端程式庫會重試要求。如果您使用用戶端程式庫,則無須採取任何行動。
如果訂閱項目遭刪除,或從未存在,就可能發生找不到錯誤。如果您提供的訂閱路徑無效,就會發生後者情況。