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链接,出现消息积压的状况 。
相关文章
相关标签/搜索