# Oracle Connection reset by peer
# 问题现象
环境:
- Linux服务器
- Oracle 11g
com.succez.commons.jdbc.SuccezSQLException: (xzzlyk)IO Error: Connection reset by peer
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:779)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:921)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1099)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3640)
at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1384)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3687)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1165)
at oracle.jdbc.OracleDatabaseMetaData.getTables(OracleDatabaseMetaData.java:2723)
# 异常原因
Oracle JDBC在建立连接时默认读取的Linix的/dev/random
来产生随机数,但是读取过程可能发送阻塞:
- Oracle JDBC在建立连接时需要一些随机数据用以加密session token之类的东西,它会读取
/dev/random
设备,/dev/random
设备会返回小于熵池噪声总数的随机字节。 - Linux内核熵池,通过搜集键盘,鼠标,中断,磁盘操作来产生随机数据。
/dev/random
可生成高随机性的公钥或一次性密码本。若熵池空了,对/dev/random
的读操作将会被阻塞,直到收集到了足够的环境噪声为止。 /dev/urandom
则是一个非阻塞的发生器:dev/random
的一个副本是/dev/urandom
(”unlocked”,非阻塞的随机数发生器),它会重复使用熵池中的数据以产生伪随机数据。对/dev/urandom
的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random
的。- 随机数据源默认用的是
/dev/random
。
具体的在java中,是使用java.security.SecureRandom
产生的随机数:
java.security.SecureRandom is a standard API provided by sun. Among various methods offered by this class void nextBytes(byte[])
is one. This method is used for generating random bytes.
Oracle 11g JDBC drivers use this API to generate random number during login. Users using Linux have been encountering SQLException("Io exception: Connection reset").
The problem is two fold
The JVM tries to list all the files in the /tmp (or alternate tmp directory set by
-Djava.io.tmpdir
) when SecureRandom.nextBytes(byte[]) is invoked. If the number of files is large the method takes a long time to respond and hence cause the server to timeoutThe method void
nextBytes(byte[])
uses/dev/random
on Linux and on some machines which lack the random number generating hardware the operation slows down to the extent of bringing the whole login process to a halt. Ultimately the the user encountersSQLException("Io exception: Connection reset")
Users upgrading to 11g can encounter this issue if the underlying OS is Linux which is running on a faulty hardware.
Cause The cause of this has not yet been determined exactly. It could either be a problem in your hardware or the fact that for some reason the software cannot read from dev/random
Solution Change the setup for your application, so you add the next parameter to the java command:
-Djava.security.egd=file:/dev/./urandom
# 解决办法
# 方法一
直接修改$JAVA_HOME/jre/lib/security路径下的java.security文件。把securerandom.source=file:/dev/random
修改成securerandom.source=file:/dev/./urandom
。
# 方法二
tomcat文档里的建议,采用非阻塞的熵源(entropy source),通过java系统属性来设置:
-Djava.security.egd=file:/dev/./urandom
# 参考资料
- https://www.usn-it.de/2009/02/20/oracle-11g-jdbc-driver-hangs-blocked-by-devrandom-entropy-pool-empty/ (opens new window)
- https://stackoverflow.com/questions/2327220/oracle-jdbc-intermittent-connection-issue (opens new window)
- https://blog.csdn.net/guodaoying/article/details/52421758?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242 (opens new window)