生产gateway内存泄漏排查

在上线日志新功能后,生产环境某个网关2台服务器平均每天内存警报一次,在运维扩容了网关服务器的内存后,警报还是存在,于是乎这个问题便给了开发。。。。。。 因为刚入职公司没多久,各种日志和监控权限不足,运维还爱答不理,所以并没有很多的一手信息,平白给定位问题带来困难;

因为是最新上线了打印gateway的全局出入参日志功能出现的网关内存异常,所以果断关闭了该功能,内存正常; 根据内存异常现象推测如下: 1. gateway使用logback打印出入参数,需要打印日志量太大,异步打印是会用到堆内内存,导致内存溢出? 分析: a: 使用别人账号查看到当时网关服务器的gc,堆内内存,cpu,线程都是正常; b: 根据logback配置查看对应的源码,发现网关日志是同步打印; —> 证伪;

2. 堆内内存正常,网关是1-2天出现一次内存异常,应该是堆外内存泄漏? 分析: a:本地使用jmeter模拟请求网关中某一个接口,实时打印堆外内存使用情况;具体打印堆外内存的代码如下(也是从网上找的): 结果如下:

—> 堆外内存泄漏证实;

3.解决问题的方式,手动释放掉优先级高的Filter产生的DataBuffer;如果你的写法类似于上图源码,可以手动释放,只不过这样太草率

return bodyInserter.insert(outputMessage, new BodyInserterContext())
                        .then(Mono.defer(() -> {
                            Flux<DataBuffer> messageBody = outputMessage.getBody();
                            return getDelegate().writeWith(messageBody);
                        })).doFinally(e -> {
                        // 因为多次使用该方式,手动释放堆外堆内引用
                        if (outputMessage.isCached()) {
                             outputMessage.getBody().map(DataBufferUtils::release);
                        }
                    });

4.在解决问题过程中发现另外一种导致堆外内存泄漏的原因,当前版本是gateway2.2.0,在body.insert()发生异常的时候是不会主动释放已分配的内存,需要升级到最新版本即可!

经验分享 程序员 微信小程序 职场和发展