?這個分析的思路來源於前同事的提問,前同事線上環境阿裏雲Ons日誌顯示broker busy異常,異常信息如下:
拿到異常信息,第壹時間根據異常提示信息 broker busy, start flow 去源碼中進行搜索,定位打印異常信息位置。
可以看到這裏是broker端os pageCache busy,rocketMq消息持久化是先寫入page cache中後由操作系統進行刷盤操作。所以這裏是消息寫入到cache中時就報錯了,總結說,就是broker在處理消息寫入page cache持久化的時候系統寫繁忙異常。
操作系統判斷是否頁寫入繁忙邏輯:
在broker端出現異常的時候,給到客戶端的都是對應的錯誤碼,而不是把異常往外拋,這裏指的借鑒。在這裏broker給到client端的是ResponseCode.SYSTEM_ERROR。 很重要壹點,rocketMq中沒有把具體業務異常往client端拋,而是都封裝起來通過錯誤碼作為結果給到客戶端,除了發生了Netty網絡通信的異常。
接著看下client端對broker page cache是怎麽處理的:
可以看到Client端對broker返回的system error是包裝成MQBrokerException拋出去的,最後回到producer send message的地方:
可以看到,在client端發送消息的時候,如果發生了MQBrokerException的時候,獲取到broker端返回的response,response code = system_error的時候就continue,同步消息會進行重試兩次,異步消息和oneway消息不會進行重試,所以這兩種模式在這種情況下就會丟消息。
註意:
broker 在處理消息寫入的時候出現page cache busy的時候,因為是在等待broker CommitLog的鎖的,還沒有獲取鎖成功,是還沒有寫入到PageCache的,所以更沒有寫入到磁盤中。
出現這個問題的解決辦法:
出現這個問題就是broker處理message發送處理不過來,所以可以通過提升當前機器的性能或者再添加壹個broker分走當前broker相應的message queue走。