OpenJDK下SpringBoot使用HttpSession時頁面打開卡住

近期將一個老項目向ARM版的CentOS7移植時,遇到了SpringBoot啓動順利,但訪問頁面卡住的問題。由於是aarch64架構,因此使用了openjdk,這個項目之前在x86_64環境下一直是用Oracle的ServerJRE,沒有遇到問題。此次啓動正常,但啓動完成後,訪問部分頁面正常,部分頁面會卡住,卡住的時間不固定,有時長有時短,毫無規律可言。而且當卡住的頁面正常後,再刷新不會再次卡住。


第一想法肯定是查日誌,在首次訪問卡頓頁面時,Spring框架有一條這樣的WARN:


2019-12-09 17:40:32.995  WARN 15161 --- [https-jsse-nio-443-exec-8] o.a.c.util.SessionIdGeneratorBase        :
 Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [178,241] milliseconds.


爲Session創建SecureRandom實例耗時將近3分鐘,這就是頁面卡住的原因,同時也解釋了爲什麼只有部分頁面卡住,因爲不是所有頁面都使用了Session,同時也解析了爲什麼卡住的頁面可訪問後再刷新就正常了,因爲創建SecureRandom instance只進行一次。


翻回來看看原因,項目中使用了Tomcat Embed作爲內嵌WEB服務器,而Tomcat在生成session ID時會使用org.apache.catalina.util.SessionIdGeneratorBase來產生安全隨機類SecureRandom實例。爲了算法保密性較強,需要用到僞隨機數生成器,Tomcat用到的是SHA1PRNG算法,爲了得到隨機種子,在Linux中,一般從/dev/random或/dev/urandom中產生,兩者原理都是利用系統的環境噪聲產生一定數量的隨機比特,區別在於系統環境噪聲不夠時,random會阻塞,而urandom會犧牲安全性避免阻塞。


從卡頓現象上看,一定是用了/dev/random導致的,看一下$JAVA_HOME/jre/lib/security/java.security文件,找到下面的內容:


#
# Sun Provider SecureRandom seed source.
#
# Select the primary source of seed data for the "SHA1PRNG" and
# "NativePRNG" SecureRandom implementations in the "Sun" provider.
# (Other SecureRandom implementations might also use this property.)
#
# On Unix-like systems (for example, Solaris/Linux/MacOS), the
# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from
# special device files such as file:/dev/random.
#
# On Windows systems, specifying the URLs "file:/dev/random" or
# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding
# mechanism for SHA1PRNG.
#
# By default, an attempt is made to use the entropy gathering device
# specified by the "securerandom.source" Security property.  If an
# exception occurs while accessing the specified URL:
#
#     SHA1PRNG:
#         the traditional system/thread activity algorithm will be used.
#
#     NativePRNG:
#         a default value of /dev/random will be used.  If neither
#         are available, the implementation will be disabled.
#         "file" is the only currently supported protocol type.
#
# The entropy gathering device can also be specified with the System
# property "java.security.egd". For example:
#
#   % java -Djava.security.egd=file:/dev/random MainClass
#
# Specifying this System property will override the
# "securerandom.source" Security property.
#
# In addition, if "file:/dev/random" or "file:/dev/urandom" is
# specified, the "NativePRNG" implementation will be more preferred than
# SHA1PRNG in the Sun provider.
#

securerandom.source=file:/dev/random


果然用的是/dev/random,按照上面的註釋部分,解決方案也不復雜,可以添加啓動參數或者修改java.security:


解決方法1:

啓動參數添加-Djava.security.egd=file:/dev/urandom,如:

java -Djava.security.egd=file:/dev/urandom -jar xxxxx.jar


解決方法2:

修改$JAVA_HOME/jre/lib/security/java.security,找到securerandom.source並修改:

securerandom.source=file:/dev/urandom



再重啓站點,卡頓現象消失。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章