序列化引发的问题

2018-12-24  本文已影响0人  lionel880

使用公司RPC中间件,发现一个问题,最终定位到序列化问题,进行记录

1.起因

组内使用内部RPC框架暴露多个服务,其他服务在Provider报错后,Consumer可以立刻响应错误,但唯独使用ElasticSearch的服务不行,怀疑方向为ES自定义的Exception与内部中间件不匹配

在中间件团队的支持下,定位到Netty,isSent为flase,没有发送成功,报错信息为序列化失败。
具体内容为 suppressed Exception (org.elasticsearch.client.Response 不支持序列化)

2.相关联知识点

public static void main(String[] args) {
    try (FileInputStream inputStream = new FileInputStream(new File("test"))) {
        System.out.println(inputStream.read());
    } catch (IOException e) {
        throw new RuntimeException(e.getMessage(), e);
    }
}

try-with-resource并不是JVM虚拟机的新增功能,只是JDK实现了一个语法糖。当你将上面代码反编译后会发现,其实对JVM虚拟机而言,它看到的依然是之前的写法:

public static void main(String[] args) {
    try {
        FileInputStream inputStream = new FileInputStream(new File("test"));
        Throwable var2 = null;

        try {
            System.out.println(inputStream.read());
        } catch (Throwable var12) {
            var2 = var12;
            throw var12;
        } finally {
            if (inputStream != null) {
                if (var2 != null) {
                    try {
                        inputStream.close();
                    } catch (Throwable var11) {
                        var2.addSuppressed(var11);
                    }
                } else {
                    inputStream.close();
                }
            }

        }

    } catch (IOException var14) {
        throw new RuntimeException(var14.getMessage(), var14);
    }
}

Java最终只能抛出一个Exception,但如果try中爆出了错误1,在finally中报错了错误2,这怎么办,在jdk 1.7以前,你只能通过代码自己解决包装。但jdk1.7以后,提供了addSuppressed方法,可以让你将其他错误,放在一个Exception里进行抛出。

问题最终解释

暴露的服务A使用ES服务,ES服务报错,最终报错 ElasticsearchStatusException 支持序列化 ,但是内部的addSuppressed添加的org.elasticsearch.client.Response 不支持序列化,由于公司内部的RPC框架会对整个对象进行序列化,导致Netty发送失败

解决方案

自己在此服务处,catch Exception进行包装后抛出

上一篇 下一篇

猜你喜欢

热点阅读