zoukankan      html  css  js  c++  java
  • The Network Adapter could not establish the connection问题研究

    最近一个项目会报上述错误,但也不是经常发生,所以很难跟踪,影响不是很大,但每次看到日志中这个错误就会不舒服,还是要想办法解决才是。

    • 错误提示信息很明确是网络适配器不能创建连接。

    查了很多资料,并且Oracle官网也有说明并且列举了可能产生这种问题的原因,但是如何规避还是不知所措。其中涉及到Oracle MTS模式、IPv4、IPv6、JVM,最有可能原因是Oracle服务器支持IPv4和IPv6网卡,所以可能同时提供了这两种连接服务,而JDBC客户端连接时也支持IPv4和IPv6,猜测IPv4服务不能对IPv6请求服务,所以报错。

    • 要解决这种时隐时现的问题,很重要一个方法则是能方便重现。

    多次尝试,终于在并发线程提高到500时,重新了错误。并且也得到SQLException的ErrorCode:17002。这个错误信息和Oracle官网提示是一样的了。

    然后按照猜测进一步去解决问题。

    • 把涉及到点先搞明白,最关键两点:

    Oracle MTS模式和Dedicated模式,

    MTS模式:Dispatch进程将Client Connection Request,进行排队,由后台多个Shared Server并行处理排队的请求。所以如果存在Client Request请求处理耗时过长,则整体处理效率就会下降。

    Dedicated模式:会为每个Client Connection Request分配专门进程进行处理,所以该模式更适应于请求处理时间较长,请求数相对较少情况。

    客户采用的Oracle配置方式是MTS模式。Oracle官网介绍这种情形下JDBC程序可能会产生这个错误。

    IPv4、IPv6,

    IPv4、IPv6它们分别是两种寻址协议,由于IPv4的局限性和缺点,所以产生了IPv6,简言之:IPv6迟早是要替代IPv4的,然而由于历史原因,它们是要共存一段时间的,但是共存期间它们又存在互相通信的需求,所以就产生了一系列解决方案,无论哪种方案都离不开这两种协议的互转,不是你转成它就是它转成你,总之是翻译成一致后才能互相交流。

    • 据Oracle所述:Java在1.4版本后加入了对两种协议的支持,其中Windows平台是Java5版本后才支持的。Java在检测到OS支持双协议时优先采用IPv6进行通信,除非显式指定采用哪种协议。

    到目前为止,算是知道Oracle官方明确提示这个问题是可能产生的,并且罗列了产生的情景,以及解决方法。这时问题应该能解决才对。

    首先对于Oracle两种模式,Oracle提示可以通过在JDBC连接符中知指定参数使程序固定采用Dedicated模式,并且JVM也提供参数可以指定程序固定采用IPv4进行通信,分别尝试了两种方法仍然不行。无奈,固才有此文诞生。

    但还是得要解决问题啊,,,重新找分析原因。

    • 无奈再出发,完整异常堆栈:
    java.sql.SQLException: Io 异常: The Network Adapter could not establish the connection
    ErrorCode:17002 SQLState:null Io 异常: The Network Adapter could not establish the connection
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:125)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:162)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:274)
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:328)
        at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:348)
        at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:151)
        at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
        at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:563)
        at java.sql.DriverManager.getConnection(DriverManager.java:571)
        at java.sql.DriverManager.getConnection(DriverManager.java:215)
        at com.sfit.dorado.utils.BaseDaoTest.getConnection(BaseDaoTest.java:30)
        at com.sfit.dorado.utils.BaseDaoTest$1.run(BaseDaoTest.java:71)

    关键点oracle.jdbc.driver.T4CConnection.logon,即通过Oracle用户名密码去获取连接,无法建立连接。也许真的是达到可以创建的最大连接数了。

    降低并发量再测试,300并发只出现一次没拿到连接,再来2次300并发测试都是最多一次错误,说明还真的可能达到上限了。加到400测试2次,出现一次以上错误。加到500测试,除上述错误,还出现了另外错误,

    java.sql.SQLException: Listener refused the connection with the following error:
    ORA-12519, TNS:no appropriate service handler found
    The Connection descriptor used by the client was:
    (description=(address=(host=172.19.124.3)(protocol=tcp)(port=1521))(connect_data=(sid=ctp))(SERVER=DEDICATED))
    
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:125)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:280)
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:328)
        at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:348)
        at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:151)
        at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
        at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:563)
        at java.sql.DriverManager.getConnection(DriverManager.java:571)
        at java.sql.DriverManager.getConnection(DriverManager.java:215)
        at com.sfit.dorado.utils.BaseDaoTest.getConnection(BaseDaoTest.java:30)
        at com.sfit.dorado.utils.BaseDaoTest$1.run(BaseDaoTest.java:71)

    所以猜测采用200并发测试,多次测试均能正常通过。结果错误频发。

    降低至50个并发,7次测试,1次出现1个错误,6次全通过。

    补充,以上测试均采用固定IPv4即指定了运行参数-Djava.net.preferIPv4Stack=true,并且程序指定dedicated模式,每次测试,持有连接20s。

    去掉-Djava.net.preferIPv4Stack=true参数,7次100并发测试,2次出现1个错误,2次2个错误,3次全通过。

    去掉IPv4参数,再去掉连接符中指定Dedicated模式测试,7次100并发测试,7次全通过。7次200并发测试,1次出现1个错误,6次全通过。

    上述测试情况正好印证了MTS模式和Dedicated模式的优缺点以及分别适应的场景。

    结合目前客户Oracle数据库使用情况,大概有10个维护人员通过PLSQL使用数据库,10个人开发人员在通过Tomcat使用数据库,2个WEB系统使用数据库,WEB系统启动过程时会较长时间持有数据库连接进行初始化数据;WEB系统采用数据库连接池机制,启动时初始化4个连接池,以前每个连接池初始化连接50,最大100个(会经常报上述错误),优化后开发人员每个连接池分配5个连接,最多10个,部署的WEB系统为10-30个。

    这么分析话,目前偶尔报无法建立连接的错误算是正常了。

    真的要进一步优化,就要在Oracle配置上面花费些功夫了。

    补充:有些论坛提供的IP地址添加到host文件中解决了问题,也是因为那情那景下添加了IPv4地址到host文件,所以采用IPv4通信了。

    连接池数量不够用时也会报这个错误。

    终于想通了。

    岁月留痕
  • 相关阅读:
    用wamp配置的环境,想用CMD连接mysql怎么连
    Mysql删除表
    MySQL创建表
    Leetcode 130. Surrounded Regions
    Leetcode 111. Minimum Depth of Binary Tree
    Leetcode 110. Balanced Binary Tree
    Leetcode 98. Validate Binary Search Tree
    Leetcode 99. Recover Binary Search Tree
    Leetcode 108. Convert Sorted Array to Binary Search Tree
    Leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/navigate/p/4772615.html
Copyright © 2011-2022 走看看