解決centos下tomcat啟動太慢 & JDBC連接oracle太慢的問題


近期遇到一個非常奇怪的問題,也不知道改了什么,tomcat啟動非常慢,以前幾秒就啟動好了,現在要30秒左右。

而且,通過jdbc連接oracle數據庫也非常慢,以前建立一個連接只要幾十毫秒,現在也要10秒左右。

折騰了好幾天,終於解決了,記錄下來,幫助大家少走彎路。

 

遇到這個問題時,最初以為是random策略問題,以前遇到過,通過修改隨機數策略可以解決,參照我的這篇文章:

https://www.cnblogs.com/lavezhang/p/6106356.html

但是,修改后發現問題沒有解決,只能繼續排查。

 

懷疑是jdk自動尋找proxy的問題,於是設置ProxySelector.setDefault(null),還是沒有解決。

 

懷疑是tomcat版本問題,從tomat8到tomcat8.5,到tomcat9,都試了一遍,還是沒解決。

 

懷疑是jdk的問題,從openjdk換成了oraclejdk,還是沒解決。

 

最后,這種疑難問題,還是依賴Tomcat堆棧數據來分析。

於是導出tomcat堆棧信息

> pgrep java

> 21257

> jstack 21257 > thread_data1

 

注意:默認通過yum安裝的是openjdk,沒有jstack這個工具,得安裝特殊的包才有,辦法去網上搜吧。

最簡單的辦法是,直接換成oracle jdk,因為openjdk的jstack工具有坑!

 

開始分析堆棧數據,發現tomcat啟動,以及Oracle連接,都是卡在一個地方:

"main" #1 prio=5 os_prio=0 tid=0x00007f812000a000 nid=0x5813 runnable [0x00007f8126dee000]
java.lang.Thread.State: RUNNABLE
at java.net.Inet4AddressImpl.getLocalHostName(Native Method)
at java.net.InetAddress.getLocalHost(InetAddress.java:1474)
at sun.management.VMManagementImpl.getVmId(VMManagementImpl.java:140)
at sun.management.RuntimeImpl.getName(RuntimeImpl.java:59)
at org.springframework.boot.system.ApplicationPid.getPid(ApplicationPid.java:55)
at org.springframework.boot.system.ApplicationPid.<init>(ApplicationPid.java:46)

------------------------------------------------------------------------------------------

"http-nio-8082-exec-4" #23 daemon prio=5 os_prio=0 tid=0x00007fa7fc77a800 nid=0x5438 runnable [0x00007fa7b97d1000]
java.lang.Thread.State: RUNNABLE
at java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
at java.net.InetAddress.getLocalHost(InetAddress.java:1500)
- locked <0x0000000688fca748> (a java.lang.Object)
at oracle.jdbc.driver.T4CTTIoauthenticate.setSessionFields(T4CTTIoauthenticate.java:1118)
at oracle.jdbc.driver.T4CTTIoauthenticate.<init>(T4CTTIoauthenticate.java:265)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:579)
at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:666)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:566)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)

 

查了一下,這行代碼是檢索/etc/hosts文件,獲取當前機器名對應的IP地址,如果沒有明確配置機器名和IP的映射關系,就會在這里卡10秒左右,其實就是在局域網內去ping了。

打開/etc/hosts,果然沒有配置,趕緊補上,如下:

> vi /etc/hosts

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 prd_web1
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 prd_web1

其中,prd_web1就是手工設置的機器名。

 

至此,問題得以解決!

 

總結,走了很大一段彎路,其實對於這種程序卡死的現象,最佳解決方案就是分析tomcat堆棧,其它辦法都是靠猜測,不靠譜。

另外,這個現象並不是在所有機器上都存在,在有些機器上,即使沒有在hosts文件中配置自定義hostname的映射,程序也會正常運行,可能是jdk內部還依賴別的環境配置吧,這個等待其它小伙伴去探究。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM