[英]Azure Functions - Kafka Trigger and Output Binding - Consume exactly-once
[英]How to avoid "failed to send operations" errors after switching to the "exactly-once" delivery strategy?
我最近嘗試將我在 GCP Pub/Sub 中的訂閱切換為“exactly-once”交付策略。 但是,我開始在我的應用程序日志中每 30 分鍾看到約 10 次以下警告:
com.google.api.gax.rpc.InvalidArgumentException: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Some acknowledgement ids in the request were invalid. This could be because the acknowledgement ids have expired or the acknowledgement ids were malformed.
at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:92)
at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:98)
at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:66)
at com.google.api.gax.grpc.GrpcExceptionCallable$ExceptionTransformingFuture.onFailure(GrpcExceptionCallable.java:97)
at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:67)
at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1041)
at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:30)
at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1215)
at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:983)
at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:771)
at io.grpc.stub.ClientCalls$GrpcFuture.setException(ClientCalls.java:574)
at io.grpc.stub.ClientCalls$UnaryStreamToFuture.onClose(ClientCalls.java:544)
at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
at com.google.api.gax.grpc.ChannelPool$ReleasingClientCall$1.onClose(ChannelPool.java:535)
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:563)
at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:70)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:744)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:723)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Some acknowledgement ids in the request were invalid. This could be because the acknowledgement ids have expired or the acknowledgement ids were malformed.
at io.grpc.Status.asRuntimeException(Status.java:535)
... 17 more
在同一線程中,緊跟在它們之后的是以下INFO
日志消息:
Permanent error invalid ack id message, will not resend
我沒有看到這些警告引起的任何問題,但有點難以判斷,因為我的應用程序正在處理相當數量的消息(~1000 條/小時)。 我最初認為這些警告只是切換到“exactly-once”策略后的短期“余震”。 然而,我等了大約2個小時,它們一直以相同的頻率出現,沒有消失的跡象。 然后我禁用了“exactly-once”策略,之后它們立即消失了。 任何人都可以告訴我這些警告是否危險、我可以預期的副作用以及最重要的是我如何擺脫它們?
我正在使用spring-cloud-gcp-dependencies
和spring-cloud-gcp-starter-pubsub
3.4.0
版。 我還使用 Spring Cloud Stream 來處理傳入的消息,我依靠它來自動確認消息。
我的application.yaml
文件中設置了以下配置:
spring:
cloud:
gcp:
pubsub:
subscriber:
executor-threads: 15
max-ack-extension-period: 23400 # 6 hours and 30 minutes
acknowledgement-deadline: 600 # Maximum value
對於上下文:我的應用程序中的消息代表要執行的作業,它們可能需要很長時間才能完成——因此最長確認延長期為 6 小時 30 分鍾。
我還看到了以下 StackOverflow 問題: How to handle errors during message acknowledgement using google pubsub java library?
據我了解,這些警告的結果是消息將重新傳送到我的應用程序,但這正是我想要避免的。
謝謝你的問題,亞歷山大。
當對服務的 modifyAckDeadline 或 Acknowledgment 請求失敗時,您看到的錯誤會發生,因為確認 ID 已過期。 在這種情況下,服務會將過期的確認 ID 視為無效,因為更新的交付可能已經在進行中。 這是根據一次交付的保證。 可能有以下幾個原因:
我建議將min-duration-per-ack-extension設置為較大的數字以減少上述問題。 這將有助於減少確認 ID 租約過期的情況。 您可以為此字段設置的最大值為 600 秒。
此外,如其他堆棧溢出問題中所述,您應該考慮檢查確認操作的響應。 這可以用來指導您的應用程序,如果它可以期待重新交付。 樣品。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.