背景:
上周网关上线后,隔了几小时突然服务不可用,重启后恢复,隔几小时后依然如此;由于此次网关改动的代码较多,一时不好定位。
问题回放:
从系统监控图上看,内存一直在增长,最终到爆;
抓取到服务器宕机时刻的日志如下:
o.netty.util.internal.OutOfDirectMemoryError: failed to allocate
看到以上的日志,大体可以知道是直接内存分配不足导致,与系统监控图上看比较吻合;
从系统监控图可以看出,自从服务上线后已用内存就一直在申请、上升,没有释放,那么接下来就是定位为什么会出现内存不释放的问题了!因为我们应用的网关项目是使用的Spring Cloud Gateway进行搭建的,而Spring Cloud Gateway又是使用的Netty框架进行搭建的,这正好和以上报错io.netty.util.internal.OutOfDirectMemoryError日志恰巧对应上,下面就查阅了好多资料,说Gateway低版本确实存在过该问题,升级版本即可解决此类问题,于是将现有的Spring Cloud版本在Finchley基础上升到了Hoxton,并在仿真环境进行了压测(并发1000),压了半个小时,并没有出现宕机异常,于是当天晚上就将代码进行上线,但是上线之后查看ELK日志,发现还是存在很多的错误日志如下:
LEAK: ByteBuf.release() was not called before it's garbage-collected
竟然是内存泄漏最终导致的内存溢出,按理说像Spring Cloud Gateway这么成熟的框架不应该会出现类似的问题,于是排查我们的项目代码,发现竟然是我们自己网关项目的一个全局过滤XSS攻击的filter,里面有使用Netty的一个databuffer,但是这个databuffer没有进行释放导致,于是将该databuffer进行手工释放DataBufferUtils.release(dataBuffer);修改完该瑕疵之后,线上内存监控趋于平稳。