簡體   English   中英

Spring 雲 Stream - 如何處理下游塊?

[英]Spring Cloud Stream - how to handle downstream blocks?

在我們的 Kafka 集群計划停機期間,我們基本上遇到了以下問題如何使用 Spring Cloud Stream 指定向 RabbitMQ 發送消息的超時時間? (顯然,使用 Kafka 而不是 RabbitMQ)。

@GaryRussell 的回答:

通道sendTimeout僅適用於通道本身可以阻塞的情況,例如當前已滿的有界隊列的QueueChannel 調用者將阻塞,直到隊列中有可用空間,或者發生超時。

在這種情況下,塊位於通道的下游,因此 sendTimeout 是無關緊要的(無論如何,它是一個 DirectChannel,無論如何都不能阻塞,訂閱的處理程序直接在調用線程上調用)。

您看到的實際阻塞很可能在 rabbitmq 客戶端中的socket.write()中,它沒有超時且不可中斷; 調用線程無法執行任何操作來“超時”寫入。

我知道的唯一可能的解決方案是通過在連接工廠上調用resetConnection()來強制關閉兔子連接。

很好地解釋了為什么有問題的方法( org.springframework.integration.channel.AbstractSubscribableChannel#doSend )沒有考慮timeout 但是,這對我來說仍然有點奇怪。

spring-integration-kafka-3.2.1.RELEASE-sources.jar./org/springframework/integration/kafka/outbound/KafkaProducerMessageHandler:java:566中,我們可以看到,如果需要sync行為:

565    if (this.sync) {
566        Long sendTimeout = this.sendTimeoutExpression.getValue(this.evaluationContext, message, Long.class);
567        if (sendTimeout == null || sendTimeout < 0) {
568            future.get();
569        }
570        else {
571            try {
572                future.get(sendTimeout, TimeUnit.MILLISECONDS);
573            }
574            catch (TimeoutException te) {
575                throw new MessageTimeoutException(message, "Timeout waiting for response from KafkaProducer", te);
576            }
577        }
578    }

被調用,其中考慮了超時。 sendTimeoutExpression被分配給一個默認值:

    private static final long DEFAULT_SEND_TIMEOUT = 10000;
    private Expression sendTimeoutExpression = new ValueExpression<>(DEFAULT_SEND_TIMEOUT);

然而,我們的堆棧跟蹤揭示了一些不同的東西:

"pool-1-thread-3" - Thread t@108
   java.lang.Thread.State: TIMED_WAITING
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for <4ebda621> (a org.springframework.util.concurrent.SettableListenableFuture$SettableTask)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:426)
    at java.util.concurrent.FutureTask.get(FutureTask.java:204)
    at org.springframework.util.concurrent.SettableListenableFuture.get(SettableListenableFuture.java:134)
*   at org.springframework.integration.kafka.outbound.KafkaProducerMessageHandler.processSendResult(KafkaProducerMessageHandler.java:572)
    at org.springframework.integration.kafka.outbound.KafkaProducerMessageHandler.handleRequestMessage(KafkaProducerMessageHandler.java:414)
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:134)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:69)
    at org.springframework.cloud.stream.binder.AbstractMessageChannelBinder$SendingHandler.handleMessageInternal(AbstractMessageChannelBinder.java:1035)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:69)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106)
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:570)

標有*的調用對應於future.get(sendTimeout, TimeUnit.MILLISECONDS); 稱呼。

看到底層客戶端似乎如何支持它(鑒於future.get()調用支持超時這一事實),如何設置? 我可以在活頁夾參考資料中找到的唯一兩個屬性(參見此處)是spring.cloud.stream.kafka.binder.healthTimeoutbatchTimeout ,據我所知,這不會影響此設置。

看看org.springframework.cloud.stream.binder.kafka.KafkaMessageChannelBinder.ProducerConfigurationMessageHandlerKafkaProducerMessageHandler是如何構建的,一個私有的 class,bean 覆蓋似乎不是推薦的方式。

它似乎沒有記錄,但類似於偵聽器容器定制器 https://docs.spring.io/spring-cloud-stream/docs/3.1.2/reference/html/spring-cloud-stream.html# _advanced_consumer_configuration你可以添加一個ProducerMessageHandlerCustomizer @Bean來設置消息處理程序的任意屬性。

在較新版本的處理程序中,超時始終配置為至少與ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG一樣多,以避免誤報(在處理程序超時后發布成功)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM