oracle 瘦 jdbc 连接在不活动后接收“连接重置”

Posted

技术标签:

【中文标题】oracle 瘦 jdbc 连接在不活动后接收“连接重置”【英文标题】:oracle thin jdbc connection receiving "connection reset" after inactivity 【发布时间】:2012-02-08 22:54:45 【问题描述】:

我有一个在 tomcat 6、java 6 (openjdk)、centos 6.2 上运行的新 tomcat 应用程序服务器。服务器是一个在centos 6.2 主机上运行在qemu-kvm 下的虚拟机。主机和来宾都是 64 位的。

我有一个连接打开的情况,(来自连接池)然后发生大约 4 个小时的“长时间计算”,在此期间不使用连接。最后发出“commit”,服务端给出“connection reset”异常,具体如下:

Caused by: java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:185)
    at oracle.net.ns.Packet.receive(Packet.java:282)
    at oracle.net.ns.DataPacket.receive(DataPacket.java:103)
    at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:230)
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:175)
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:100)
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:85)
    at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:122)
    at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:78)
    at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1179)
    at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1155)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:279)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
    at oracle.jdbc.driver.T4C7Ocommoncall.doOCOMMIT(T4C7Ocommoncall.java:75)
    at oracle.jdbc.driver.T4CConnection.doCommit(T4CConnection.java:558)

数据库服务器和客户端在同一个子网上,除了服务器是一个真实的物理主机,显然app-server是一个运行在同一个子网上的物理机内的来宾。

主机使用“桥接”网络。

这可能根本不是软件问题,而是 linux 操作系统配置(iptables?)问题,但我真的不知道。

【问题讨论】:

【参考方案1】:

我遇到过几次。几乎总是由网络超时(负载平衡器或防火墙)引起。但是您已经明确提到您的服务器位于同一子网中,因此不确定发生了什么。既然你怀疑iptables,你能不能把它关掉,运行测试看看它是否有效(太容易了哈:)

无论如何,假设您连接到 Oracle 数据库,以下调整会有所帮助

http://raibledesigns.com/rd/entry/tomcat_oracle_connectivity_problems

如果您使用不同的数据库(例如 mysql),设置可能会有所不同,但逻辑是相同的。设置一个 keepalive 值以防止连接空闲时间过长。这样firewal/load balancer/iptables软件就不会终止它了。

【讨论】:

我相信这个问题是由执行“system-config-firewall-tui”引起的,它间接刷新了 iptables 配置并重新加载。这会导致一些现有连接中断。【参考方案2】:

正如您在 Oracle 论坛中的 this 帖子中看到的那样,这可能有多个问题/解决方案。

检查您的 JDBC 驱动程序版本是否正确 检查您的 ORACLE_HOME 环境变量 尝试添加参数-Djava.security.egd=file:///dev/urandom 您的逻辑使用单例来获取连接?在帖子中也提到了这一点

希望对你有所帮助。

【讨论】:

当我读到它时,/dev/urandom 修复是针对连接超时的。这是连接的,有效的,用于某些语句,然后处于空闲状态。是否仍然有可能成为 /dev/urandom 修复? 抱歉,回车太快了。至于 ORACLE_HOME 和其他 sqlnet.ora 调整,我认为它们不适用于我正在使用的 thin 驱动程序(未指定)。我会检查驱动程序版本以确定。【参考方案3】:

@user 指的是一个很好的解决方法,通过在 sqlnet.ora 中配置“SQLNET.EXPIRE_TIME=10”。

但是,此解决方法仅适用于您的应用程序使用厚 OCI (jdbc:oci) 而不是精简 (jdbc:thin) 驱动程序的情况。

Linux 有软件防火墙,即 iptables,它可以丢弃空闲的网络连接,所以即使你在同一个子网中,你也有 iptables 软件防火墙。这在所有现代 Linux 中默认激活,并且由 Linux 管理员禁用。

默认情况下,Linux iptables 不会丢弃空闲的 TCP/IP 连接(jdbc 属于 TCP/IP 协议),因此 Linux 管理员必须配置 iptables 才能这样做。以下为有兴趣了解更多的读者的详细解释:

http://www.digitage.co.uk/digitage/software/linux-security/cutter

业务用户、安全团队或架构师经常建议网络/操作系统管理员使用防火墙和路由器中止空闲连接。这一直是反黑客社区的“建议”,但没有得到适当的讨论,并导致应用程序不稳定。最终,您应该与团队讨论以找到平衡

【讨论】:

以上是关于oracle 瘦 jdbc 连接在不活动后接收“连接重置”的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有 TNSNames 别名语法的 JDBC 瘦驱动程序连接到 Oracle 数据库

Oracle 中的 JDBC 瘦连接字符串同时使用冒号和正斜杠

为 Oracle JDBC 瘦客户端设置语言

Oracle 11g 连接重置错误

使用 Oracle 瘦客户端和 jdbc 强制加密网络流量?

Tomcat、JDBC 瘦客户端和 Oracle 钱包