症状:

在Linux主机上远程登录,执行一个简单的Oracle的JDBC连接程序(jar包),结果硬生生的卡在了连接建立验证阶段,然后等上几分钟后因为连接超时,连接被远端的Oracle服务器reset,于是报了connection reset exception



原因:

参考:http://www.usn-it.de/index.php/2009/02/20/oracle-11g-jdbc-driver-hangs-blocked-by-devrandom-entropy-pool-empty/

如参考材料中所述,oracle JDBC在建立连接时需要一些随机数据用以加密session token之类的东西,而这个随机数据源默认用的是/dev/random,如果不是,反正也是一个能让人慢的抓狂的发生源。Linux有个内核熵池(感觉太装B了),通过搜集键盘,鼠标,中断,磁盘操作来产生随机数据,可以通过以下命令查看当前的熵值:

cat /proc/sys/kernel/random/entropy_avail


由于执行程序的主机没有图形界面只是通过远程ssh进行连接,那么熵值来源就少了两个,如果机器比较空闲则后面两个来源也少了,结果就是等半天来不了一个随机数,可以通过一下命令体验一下,用/dev/random憋出个随机数是多难

dd if=/dev/random of=rnd_file bs=1 count=64


如果侥幸执行的很快,可以多试几次把积累起来的熵值用掉,可以通过前面所述的方法查看当前熵值数目

Linux中还有个随机数发生器,/dev/urandom,如其名字所述,不那么随机的随机发生器,就是伪随机的,当然会快很多。参考资料中给出的把随机源修改为/dev/urandom的方法,即在执行java程序加入命令行参数:

-Djava.security.egd=file:///dev/urandom


可是似乎不起作用。那么手工来增大熵值吧,可以执行一下命令

for i in {1..100000};do cat /proc/sys/kernel/random/entropy_avail;done;


就是反复打印当前熵值10万次,当然根据自己测试的结果当熵值到达240+时,可以按ctrl+c终止这个命令,此时再去执行Oracle JDBC程序,就可以连接成功了(保险一点可以等熵值更大时终止命令)。虽然不是实用的解决方案,但至少确定了问题所在。为了这个事,人都快奔溃了。

 

解决方案:

安装一个为提供提供熵的程序包

   sudo apt-get install haveged


熵池减少原因:

由于linux内核2.4升级到2.6后减少噪源获取,导致随机数生成量减少,通过使用rngd服务获取硬件噪源,生成随机数,补充熵池。

 

解决方案:

熵池配置:

查看是否安装 rng-tools(默认系统已经安装)

# echo 'EXTRAOPTIONS="--rng-device /dev/urandom"' >/etc/sysconfig/rngd

启动服务:

# service rngd start

配置开机启动:

# chkconfig rngd on

验证信息:

# chkconfig --list rngd
rngd               0:off    1:off    2:on    3:on    4:on    5:on    6:off

 

测试是否成功

# dd if=/dev/random of=rnd_file bs=1 count=64

记录了64+0 的读入

记录了64+0 的写出

64字节(64 B)已复制,0.00069313 秒,92.3 kB/