場景
消費者接受消息,進行一系列處理,但是由於某些原因處理過程中該消費者的拋出了異常,並且不捕獲(直接 throws IOException 拋出去);
由於拋出了IOException,那么這條消息就會再次被發送到該隊列,消費者就再次收到,而消費者拋出異常,該消息又會入隊……所以就形成了一個死循環(除非不再有類似IO的異常),那么控制台日志就一直打印該消費者的拋出異常。
所以,如果不需要消費者拋出異常后消息重新入隊,就需要將異常捕獲。
下面模擬消費者收到一條消息,拋出IOException 沒有捕獲
控制台一直拋出異常,打印堆棧
就算把這個消費者停了,然后再啟動這個消費者依然后報錯,因為這個隊列的消息一直沒有被該消費者消費。
解決辦法:(推薦)當消費者把該異常內部捕獲了,不再拋出去
保險起見,可以把整個方法體的內容進行try,然后捕獲異常,具體操作如下:
public void consumerMethod(Param param){ try{ // 比如解析body,業務操作 } catch(IOException e){ // 比如打印日志,異常堆棧 } catch(NullPointerException e){ // 比如打印日志,異常堆棧 } catch(Exception e){ // 比如打印日志,異常堆棧 } }
就只會進入catch打印一次堆棧,該隊列的消息就被該消費者消費了。
拋出AmqpRejectAndDontRequeueException異常
拋出這個異常后,表示該消費者監聽的隊列不要因為拋出AmqpRejectAndDontRequeueException異常而消息重復入隊;
控制台也只打印了該錯誤日志,該隊列剛收到的消息已被該消費者消費。