作为一名Java开发者,我们都知道Java进程是运行在Java虚拟机上的,而Java进程要想正常运行则需要向计算机申请内存,其中主要为Java对象实例所占用的堆(heap)内存(当然还有其他的也会占用内存,比如栈等),这些内存一般划分为Java虚拟机所占内存。
在当今网络通信过程中,不可避免地需要用到高性能IO通信框架Netty,Spring Cloud Gateway也不例外用到了Netty进行网络通信,当然还有很多框架也都应用到了Netty,比如:Dubbo、RocketMQ等等。而Netty为了减少网络通信过程中数据的复制,也就是用户态,内核态之间数据的复制,会大量地分配直接内存,相对于Java虚拟机的堆内存而言,相当于是堆外内存。
而我们本次出现的线上事故也和Netty的直接内存相关。
场景再现
上周四中午,睡得正香,突然线上出现了大量接口502(Http 502错误表示的是网关错误,这个问题是由后端服务器之间不良的IP通讯造成的,可能包括正在尝试访问的网站的 Web 服务器)报警,同时运维监控到我们组刚上线的内网网关发生宕机,情急之下马上先重启了网关服务(万能的重启)重启之后,服务接口可用,不在报警,然后开始排查具体产生宕机的原因,首先跟踪的具体日志如下:
错误日志