记录一次因为InetAddress.getLocalHost()缓慢导致系统Websocket连接慢的坑

问题描述
系统在本地开发测试时Websocket连接很正常,都是秒连。但打包完部署到linux上运行,Websocket连接特别慢,平均要花10秒左右才能建立连接。

框架结构
整体采用前后端分离开发:
前端:Vue.js+sockjs-client+Webstomp-client
后端:Springboot+WebStomp

关于前后端Websocket具体实现,可移步我的另一篇博客:
前后端分离WebSocket +Springboot 实战详解

过程
排除了网络问题之后,在一步步的Debug之中,拨开了Bug的层层面纱。最终发现原来是Java原生方法InetAddress.getLocalHost()的坑~

在websocket连接过程中,会将http协议升级为websocket协议,在升级过程中,调用了InetAddress.getLocalHost(),而这个方法的底层获取依赖于JDK原生InetAddress类的操作。
下面是JDK中InetAddress类的描述

InetAddress Caching
The InetAddress class has a cache to store successful as well as unsuccessful host name resolutions.
By default, when a security manager is installed, in order to protect against DNS spoofing attacks, the result of positive host name resolutions are cached forever. When a security manager is not installed, the default behavior is to cache entries for a finite (implementation dependent) period of time. The result of unsuccessful host name resolution is cached for a very short period of time (10 seconds) to improve performance.

为了防止DNS欺骗攻击,这个类会缓存获取主机地址的结果,默认缓存10秒,也就是说如果获取失败了,10秒之内都会处于等待状态,拿不到正确的结果。

解决方案
在系统hosts文件中增加本地ip地址与主机名的对应项

例如说你的ip是 10.1.4.166 主机名是centos1

那么配置: 10.1.4.166 centos1