spring cloud stream 區域性異常和全域性異常混亂
阿新 • • 發佈:2021-02-02
緣由:保證訊息不丟失(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
最終,用稀爛的英語在github上“網路問政”,
得知,在spring cloud stream 3.1.0版本修復了這個問題(負載均衡策略是區域性handler,但是所有錯誤都會橋接到全域性handler上)
解決辦法:
- 升級spring cloud stream 版本(>=3.1.0)
- 用原生mq寫
- 像spring cloud stream貢獻者所說的,具體檢視
github issues
裡的操作
完畢!