JVM上的随机数与熵池策略
bug(端口监听启动后,Tomcat耗时2min+ ):
2017-09-01 15:51:05.146 WARN 20923 --- [http-nio-80-exec-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [141,273] milliseconds.
2017-09-01 15:51:05.160 WARN 20923 --- [http-nio-80-exec-4] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [67,573] milliseconds.
2017-09-01 15:51:05.160 WARN 20923 --- [http-nio-80-exec-3] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [72,205] milliseconds.
2017-09-01 15:51:05.163 WARN 20923 --- [http-nio-80-exec-2] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [132,321] milliseconds.
2017-09-01 18:24:26.447 WARN 21241 --- [http-nio-80-exec-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [166,806] milliseconds.
2017-09-01 20:11:12.953 WARN 21508 --- [http-nio-80-exec-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [173,287] milliseconds.
2017-09-03 16:50:59.385 WARN 25289 --- [http-nio-80-exec-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [154,563] milliseconds.
这个SecureRandom
的初始化竟然花了100秒之多。。。
后来查了一下,发现这个问题抱怨的还是蛮多的,以至于tomcat的wiki里面还单独列出来作为加速启动的一个方面:
Tomcat 7+ heavily relies on SecureRandom class to provide random values for its session ids and in other places. Depending on your JRE it can cause delays during startup if entropy source that is used to initialize SecureRandom is short of entropy. You will see warning in the logs when this happens.
There is a way to configure JRE to use a non-blocking entropy source by setting the following system property: -Djava.security.egd=file:/dev/./urandom
尝试使用-Djava.security.egd=file:/dev/./urandom
启动了一下,果然快了很多。
不过tomcat的wiki中提到,如果使用这个非阻塞的/dev/urandom
的话,会有一些安全方面的风险,这块我倒确实不太明白,不过好在有明白人,而且还写了一篇长文来证明使用/dev/urandom
是没问题的,所以就先用着吧:-)
另外:
有两种解决办法:
1.在Tomcat环境中解决
可以通过配置JRE使用非阻塞的Entropy Source。
在catalina.sh中加入这么一行:-Djava.security.egd=file:/dev/./urandom 即可。
加入后再启动Tomcat,整个启动耗时下降到Server startup in 6213 ms,大大降低了启动的时间。
2.在JVM环境中解决
先执行which javac命令检查jdk安装路径
/usr/local/java/jdk1.8.0_92/bin/javac
去到$JAVA_PATH/jre/lib/security/java.security这个文件,找到下面的内容:
securerandom.source=file:/dev/urandom
替换成
securerandom.source=file:/dev/./urandom
这样问题就解决了
在apache-tomcat官方文档:
如何让tomcat启动更快里面提到了一些启动时的优化项,其中一项是关于随机数生成时,采用的“熵源”(entropy source)的策略。
他提到tomcat7的session id的生成主要通过java.security.SecureRandom
生成随机数来实现,随机数算法使用的是”SHA1PRNG”
private String secureRandomAlgorithm = "SHA1PRNG";
在sun/oracle的jdk里,这个算法的提供者在底层依赖到操作系统提供的随机数据,在linux上,与之相关的是/dev/random
和/dev/urandom
,对于这两个设备块的描述以前也见过讨论随机数的文章,
wiki中有比较详细的描述,摘抄过来,先看/dev/random
:
在读取时,/dev/random设备会返回小于熵池噪声总数的随机字节。
/dev/random可生成高随机性的公钥或一次性密码本。
若熵池空了,对/dev/random的读操作将会被阻塞,直到收集到了足够的环境噪声为止
而/dev/urandom
则是一个非阻塞的发生器:
dev/random的一个副本是/dev/urandom (”unlocked”,非阻塞的随机数发生器),它会重复使用熵池中的数据以产生伪随机数据。
这表示对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。
它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。
https://bugs.openjdk.java.net/browse/JDK-6202721
另外wiki里也提到了为什么linux内核里的随机数生成器采用SHA1散列算法而非加密算法,是为了避开法律风险(密码出口限制)。
回到tomcat文档里的建议,采用非阻塞的熵源(entropy source),通过java系统属性来设置:
-Djava.security.egd=file:/dev/./urandom
这个系统属性egd表示熵收集守护进程(entropy gathering daemon),但这里值为何要在dev
和random
之间加一个点呢?是因为一个jdk的bug,在这个bug的连接里有人反馈及时对 securerandom.source 设置为/dev/urandom
它也仍然使用的/dev/random
,有人提供了变通的解决方法,其中一个变通的做法是对securerandom.source设置为/dev/./urandom
才行。也有人评论说这个不是bug,是有意为之。
我看了一下我当前所用的jdk7的java.security文件里,配置里仍使用的是/dev/urandom
:
## Select the source of seed data for SecureRandom. By default an# attempt is made to use the entropy gathering device specified by# the securerandom.source property. If an exception occurs when# accessing the URL then the traditional system/thread activity# algorithm is used.## On Solaris and Linux systems, if file:/dev/urandom is specified and it# exists, a special SecureRandom implementation is activated by default.# This "NativePRNG" reads random bytes directly from /dev/urandom.## On Windows systems, the URLs file:/dev/random and file:/dev/urandom# enables use of the Microsoft CryptoAPI seed functionality.#securerandom.source=file:/dev/urandom
我不确定jdk7里,这个/dev/urandom
也同那个bug报告里所说的等同于/dev/random
;要使用非阻塞的熵池,这里还是要修改为/dev/./urandom
呢,还是jdk7已经修复了这个问题,就是同注释里的意思,只好验证一下。
使用bug报告里给出的代码:
import java.security.SecureRandom; public class JRand { public static void main(String args[]) throws Exception {
System.out.println("Ok: " +SecureRandom.getInstance("SHA1PRNG").nextLong());
}
}
然后设置不同的系统属性来验证,先是在我的mac上:
% time java -Djava.security.egd=file:/dev/urandomJRandOk: 8609191756834777000java -Djava.security.egd=file:/dev/urandom JRand0.11s user .03s system % cpu 0.117 total
% time java -Djava.security.egd=file:/dev/./urandomJRandOk: -3573266464480299009java -Djava.security.egd=file:/dev/./urandom JRand0.11s user .03s system % cpu 0.116 total
可以看到/dev/urandom
和/dev/./urandom
的执行时间差不多,有点纳闷,再仔细看一下wiki里说的:
FreeBSD操作系统实现了256位的Yarrow算法变体,以提供伪随机数流。与Linux的/dev/random不同,FreeBSD的/dev/random不会产生阻塞,与Linux的/dev/urandom相似,提供了密码学安全的伪随机数发生器,而不是基于熵池。而FreeBSD的/dev/urandom则只是简单的链接到了/dev/random。
尽管在我的mac上/dev/urandom
并不是/dev/random
的链接,但mac与bsd内核应该是相近的,/dev/random
也是非阻塞的,/dev/urandom
是用来兼容linux系统的,这两个随机数生成器的行为是一致的。参考这里。
然后再到一台ubuntu系统上测试:
% time java -Djava.security.egd=file:/dev/urandomJRandOk: 6677107889555365492java -Djava.security.egd=file:/dev/urandom JRand0.14s user .02s system % cpu 1.661 total
% time java -Djava.security.egd=file:/dev/./urandomJRandOk: 5008413661952823775java -Djava.security.egd=file:/dev/./urandom JRand0.12s user .02s system % cpu 0.145 total
这回差异就完全体现出来了,阻塞模式的熵池耗时用了1.6秒,而非阻塞模式则只用了0.14秒,差了一个数量级,当然代价是转换为对cpu的开销了。
// 补充,连续在ubuntu上测试几次/dev/random
方式之后,导致熵池被用空,被阻塞了60秒左右。应用服务器端要避免这种方式。
http://www.th7.cn/Program/java/201406/226039.shtml
JVM上的随机数与熵池策略的更多相关文章
- CentOS7 Tomcat 启动过程很慢,JVM上的随机数与熵池策略
1. CentOS7 Tomcat 启动过程很慢 在centos启动官方的tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的: <co ...
- Springboot程序启动慢及JVM上的随机数与熵池策略
问题描述 线上环境中很容易出现一个java应用启动非常耗时的情况,在日志中可以发现是session引起的随机数问题导致的 o.a.c.util.SessionIdGeneratorBase : Cre ...
- Tomcat 8熵池阻塞变慢详解(转)
Tomcat 8熵池阻塞变慢详解 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Tomcat 8启动很慢,且日志上无任何错误,在日志中查看到如下信息: ...
- tomcat(不仅仅是tomcat)通过熵池解决在linux启动应用慢
tomcat启动过程中报错 -Jul- ::] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web applica ...
- 多数据源连接Oracle报错,linux熵池耗尽问题
最近碰到了个很有意思的问题,springboot加载多数据源,遇到了在启动时数据库连接报错的问题. 报错信息: The error occurred while executing a query 然 ...
- Tomcat 8熵池阻塞变慢详解(putty)
原因 Tomcat 7/8都使用org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom类产生安全随机类SecureRand ...
- tomcat 7+ 启动慢 熵池阻塞变慢详解
原因: Tomcat 7/8都使用org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom类产生安全随机类SecureRan ...
- java线程池与五种常用线程池策略使用与解析
背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...
- linux内核的熵池
也可以看百度科 Linux内核采用熵来描述数据的随机性.熵(entropy)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大.在信息学中,熵被用来表征一个符号或 ...
随机推荐
- Android(java)学习笔记200:Android中View动画之 XML实现 和 代码实现
1.Animation 动画类型 Android的animation由四种类型组成: XML中: alph 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动 ...
- iOS UIKit:viewController之层次结构(1)
ViewController是iOS应用程序中重要的部分,是应用程序数据和视图之间的重要桥梁.且应用程序至少有一个view controller.每个view controller对象都负责和管理一个 ...
- linux 命令终端提示符显示-bash-4.1#解决方法
昨天在配置linux,突然发现root登录的CRT的终端提示符显示的是-bash-4.1# 而不是root@主机名 + 路径的显示方式.搞了半天也不知道为什么出现这种情况.今天终于搞定这个问题, 原因 ...
- oracle中创建表时添加注释
CREATE TABLE t1(id varchar2(32) primary key,name VARCHAR2(32) ,age VARCHAR2(32) );comment on column ...
- PHP获取文件行数
原文出处 提供两种实现方法,但是第一种效率最好 第一种: <?php $file_path = 'test.txt'; //文件路径 此处找一个1094644行的TXT文件 test.txt $ ...
- Java_Activiti5_菜鸟也来学Activiti5工作流_之入门简单例子(一)
// VacationRequest.java /** * author : 冯孟活 ^_^ * dates : 2015年9月1日 下午10:32:58 * class : 演示简单的公司请假流程 ...
- foreach遍历----for(object o: list)
备注,两种写法是一样的.
- SGU 103.Traffic Lights(最短路)
时间: 0.50 second(s) 空间: 4096 kilobytes 输入: 标准输入 输出: 标准输出 Dingiville 城市的交通规则非常奇怪,城市公路通过路口相连,两个不同路口之间最多 ...
- wordpress通过代码禁用IE8, IE9,IE10等IE浏览器兼容视图模式(Compatibility View)
目前wordpress主流主题大多都放弃了对IE6的支持!甚至IE6,IE7,IE8等的兼容模式也不支持!目前特别是国内的双核浏览器大多数使用使用IE内核都是使用的兼容模式!那将是非常糟糕!如何让IE ...
- asp.net Handler中的IsReusable属性及在Handler中使用Session
大家在用HttpHandler的时候,一般都会有两个大的疑问(当然,前提是你有钻研精神的话,呵呵) 1. IsReusable到底什么意思? 老实说,这个属性很多人都感兴趣,但搞懂的人确实不多.MSD ...