stackoverflow error致使rabbitmq消費端自動斷開

現象:自營的碼單信息是經過mq異步從wms拉取,可是碼單隊列常常會出現消息積壓或者消息未確認的狀況,rabbitmq頁面顯示無消費端,屢次重啓應用消費端才連上mq
分析:
1,一開始覺得是應用沒連上,重啓屢次後暫時問題解決
2,可是基本隔一段時間就會又出現消費端連不上,懷疑是mq配置問題,檢查配置得知,此隊列是自動確認,改成手動確認,可是消息積壓,消費端斷掉的狀況仍是會出現
3,懷疑是mq其餘的配置問題,由於此隊列是生產者和消費者在同一應用裏面,connectionFactory使用的是同一個,將生產者和消費者的connectionFactory區分開來,問題仍是未解決。
4,查看線上日誌:
2017-03-27 14:45:43.070 [SimpleAsyncTaskExecutor-3] ERROR org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer - Consumer thread error, thread abort.
java.lang.StackOverflowError: null
    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:400) ~[gson-2.2.4.jar:na]
    at com.google.gson.stream.JsonWriter.value(JsonWriter.java:417) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:362) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:346) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) ~[gson-2.2.4.jar:na]
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) ~[gson-2.2.4.jar:na]

 

看到是gson解析的時候出現堆棧溢出錯誤
現象:Handler processing failed; nested exception is Java.lang.StackOverflowError
緣由:gson解析的類存在遞歸嵌套
解決辦法:去除嵌套便可
模擬遞歸嵌套gson解析堆棧溢出的代碼以下:
public static class A{
        int d;
        String b;
        A a;
        public int getD() {
            return d;
        }
        public void setD(int d) {
            this.d = d;
        }
        public String getB() {
            return b;
        }
        public void setB(String b) {
            this.b = b;
        }
        public A getA() {
            return a;
        }
        public void setA(A a) {
            this.a = a;
        }
        public static void main(String[] args) {;
        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").enableComplexMapKeySerialization().create();
        A a = new A();
        a.setA(a);
        a.setB("b");
        System.out.println(gson.toJson(a));
    }

 

根據日誌定位到mq源碼SimpleMessageListenerContainer的內部類AsyncMessageProcessingConsumer的run方法:
 
 
 
能夠看到,消費端在處理時產生了stackoverflow錯誤,致使mq消費端斷開鏈接。可是從日誌中也看不到請求參數,很差模擬。
5,查看uat環境mq,也存在這種現象,將uat環境mq上的消息都經過界面取出來,將每一個請求參數進行模擬調用,模擬出了出現問題的狀況,斷點跟蹤得知是查詢數據庫的時候出現異常,捕獲異常後使用公司日誌工具打印warn日誌是出現json解析問題
 
 
content是exception 內容便是:MyBatisSystemException,他的最終基類是Throwable
MyBatisSystemException對象的構造函數以下:
最終會調用到Throwable的構造函數:
 
而Throwable裏面有private Throwable cause = this;私有與域,這就造成了對象嵌套,json解析的時候就會出現stackoverflow error
進行json解析是出現ERROR,ERROR是應用try catch捕獲不到,mq捕獲到了次ERROR,並將aborted設置爲true,mq消費端斷開鏈接。
 
總結:經過上面能夠看出,當rabbitmq消費端拋出 ERROR或者InterruptedException,同時業務邏輯中沒有對其進行捕獲處理,會致使消費端斷開mq鏈接,出現消息積壓的狀況 。
相關文章
相關標籤/搜索