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連接,出現消息積壓的情況 。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM