背景:
之前在物理机搭建了若依微服务,安装的是jdk8,部署完服务后,所有人都卡在登录上,后来发现是验证码产生随机数的时候发生了死锁。
原因:
1、在获取随机数时,使用new Random()写发时,在sonar扫描提示建议使用SecureRandom.getInstanceStrong()语法获取。在本地windows上该语法还没有问题,但是在linux上执行的时候,时不时就会线程阻塞,也算是一个埋得比较深的坑。
2、SecureRandom.getInstanceStrong()造成阻塞的原因:在不同的系统环境执行的底层代码不相同,在linux系统中通过底层NativePRNG方法,通过/dev/random方式读取随机数,/dev/random方式受系统环境的影响容易造成线程阻塞;在windows系统中通过generateSeed的native方法读取,不会阻塞线程。
3、解决方法
推荐使用:new SecureRandom()获取SecureRandom, linux下从/dev/urandom读取. 虽然是伪随机, 但大部分场景下都满足。
解决:
一开始改成了非阻塞算法:
random = SecureRandom.getInstance(“NativePRNGNonBlocking”)。
后来在linux启动命令做了修改:java -Dfile.encoding=utf8 -Djava.security.egd=file:/dev/./urandom -jar app.jar。