# Oracle Connection reset by peer

# 问题现象

环境:

  1. Linux服务器
  2. 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来产生随机数,但是读取过程可能发送阻塞:

  1. Oracle JDBC在建立连接时需要一些随机数据用以加密session token之类的东西,它会读取/dev/random设备,/dev/random设备会返回小于熵池噪声总数的随机字节。
  2. Linux内核熵池,通过搜集键盘,鼠标,中断,磁盘操作来产生随机数据。/dev/random可生成高随机性的公钥或一次性密码本。若熵池空了,对/dev/random的读操作将会被阻塞,直到收集到了足够的环境噪声为止。
  3. /dev/urandom则是一个非阻塞的发生器:dev/random的一个副本是/dev/urandom(”unlocked”,非阻塞的随机数发生器),它会重复使用熵池中的数据以产生伪随机数据。对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。
  4. 随机数据源默认用的是/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

  1. 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 timeout

  2. The 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 encounters SQLException("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

# 参考资料

  1. https://www.usn-it.de/2009/02/20/oracle-11g-jdbc-driver-hangs-blocked-by-devrandom-entropy-pool-empty/ (opens new window)
  2. https://stackoverflow.com/questions/2327220/oracle-jdbc-intermittent-connection-issue (opens new window)
  3. 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)
是否有帮助?
0条评论
评论