1. 程式人生 > 其它 >spring cloud stream 區域性異常和全域性異常混亂

spring cloud stream 區域性異常和全域性異常混亂

技術標籤:網路java分散式bugredis

緣由:保證訊息不丟失(provider端)

可能會因為mq不可用,或者某些情況,導致訊息傳送失敗。

spring cloud stream中,監聽{destination}.errors,可以捕獲訊息傳送異常資訊,虛擬碼如下

/**
 * 接收區域性錯誤
 **/
@ServiceActivator(inputChannel = "repeat-topic.errors")
public void repeatError(ErrorMessage errorMessage) throws Exception {
    logger.error("[handleError][payload:{}]", ExceptionUtils.getRootCauseMessage(errorMessage.getPayload()));
    logger.error("[handleError][originalMessage:{}]", errorMessage.getOriginalMessage());
    logger.error("[handleError][headers:{}]", errorMessage.getHeaders());
    
    // 這裡要記錄下傳送錯誤的訊息
    // 比如,持久化到redis、mysql等等...
}

監聽errorChannel可以捕獲全域性訊息異常資訊,虛擬碼如下

/**
 * 接收全域性錯誤
 **/
@StreamListener(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)
public void handleError(ErrorMessage errorMessage) throws Exception {
    logger.error("[handleError][payload:{}]", ExceptionUtils.getRootCauseMessage(errorMessage.getPayload()));
    logger.error("[handleError][originalMessage:{}]", errorMessage.getOriginalMessage());
    logger.error("[handleError][headers:{}]", errorMessage.getHeaders());
    
    // 這裡要記錄下傳送錯誤的訊息
    // 比如,持久化到redis、mysql等等...
}

以上是理想狀態下,emmmm,實際上

在發生錯誤的時候,由於有預設的負載均衡策略,會將錯誤資訊傳送到n個錯誤處理中的某一個,通過debug原始碼,發現org.springframework.integration.dispatcher.UnicastingDispatcher.getHandlerIterator(Message<?> message)中,參與負載均衡的handler竟然是(全域性+區域性)都參與了,那還定義區域性有啥用,不如全在全域性處理異常得了,但是,我就是需要在處理區域性異常啊...,然後瘋狂找文件,真是全部的文章都是寫著一樣的內容,我都懷疑是不是沒人在線上場景用spring cloud stream

,全是寫Demo?

最終,用稀爛的英語在github上“網路問政”,

得知,在spring cloud stream 3.1.0版本修復了這個問題(負載均衡策略是區域性handler,但是所有錯誤都會橋接到全域性handler上)

解決辦法:

  1. 升級spring cloud stream 版本(>=3.1.0)
  2. 用原生mq寫
  3. 像spring cloud stream貢獻者所說的,具體檢視github issues裡的操作

完畢!