Sha*_*ath 2 java performance https inetaddress tomcat9
请在下面找到出现问题的应用程序/环境详细信息。
我看到应用程序中的许多线程有时会进入阻塞状态几分钟。在线程转储分析中,发现 java.net.InetAddress.getLocalHost 调用花费了太多时间。很多线程都卡在这里。为应用程序中打印的每个记录器获取主机名。
该问题是间歇性的。但是当它发生时,应用程序/tomcat将进入暂停状态,从而导致大量线程的积累。一段时间(几秒钟)后,所有阻塞的线程同时解除阻塞。由于请求并发,应用程序将耗尽它在池中维护的数据库连接,从而导致问题/缓慢/服务可用性。作为修复,我确保仅将主机名访问一次到静态变量中,并在整个日志记录过程中使用相同的主机名。我想知道这个问题的详细根本原因。
以下来自线程转储的示例:
"https-jsse-nio-8443-exec-13" #95 daemon prio=5 os_prio=0 tid=0x00007fccadbba800 nid=0xaf5 waiting for monitor entry 0x00007fcb912d1000
java.lang.Thread.State: BLOCKED (on object monitor)
at java.net.InetAddress.getLocalHost(InetAddress.java:1486)
- waiting to lock <0x00000005e71878a0> (a java.lang.Object)
Run Code Online (Sandbox Code Playgroud)
在 JDK 8 中,InetAddress.getLocalHost()工作原理如下:
步骤2-4在全局下执行cacheLock。如果在此过程中出现问题,所有调用的线程都InetAddress.getLocalHost()将在此锁处阻塞——正如您所观察到的那样。
通常,只要主机地址硬编码在/etc/hosts. 但在你的情况下,似乎涉及真正的网络请求(每当 TTL 过期时)。而当第一个 DNS 请求超时时(UDP 毕竟不是一个可靠的协议),就会发生延迟。
解决方案是配置/etc/hosts包含本地主机的名称和地址,例如
192.168.1.23 myhost.mydomain
Run Code Online (Sandbox Code Playgroud)
其中myhost.mydomain与命令返回的字符串相同hostname。
最后,如果预计主机名在应用程序运行时不会更改,那么在应用程序级别上永久缓存它似乎是一个很好的解决方案。