简体   繁体   English

Oracle JDBC:为“指定的未知主机”设置超时

[英]Oracle JDBC: set timeout for “Unknown host specified”

This and similar questions were asked many times but none of the recommended setting work for me.这个和类似的问题被问了很多次,但没有一个推荐的设置对我有用。

What I need is to configure the timeout for the case if the DB host is not available or Oracle DB is still not up and running.如果数据库主机不可用或 Oracle 数据库仍未启动和运行,我需要为这种情况配置超时。

I need to check the status of the Oracle DB server in Docker, so I am executing select 1 from dual in a bash loop but the DriverManager.getConnection returns (with the mentioned exception) after 20 seconds which is too much for me. I need to check the status of the Oracle DB server in Docker, so I am executing select 1 from dual in a bash loop but the DriverManager.getConnection returns (with the mentioned exception) after 20 seconds which is too much for me. I would like to reduce this timeout to 1 sec.我想将此超时减少到 1 秒。

I know there is an Oracle tool, called TNSPING for checking the Oracle DB Server status, but unfortunately, this tool is not part of the official Oracle DB image and I do not want to install any Oracle product in Docker just because of TNSPING. I know there is an Oracle tool, called TNSPING for checking the Oracle DB Server status, but unfortunately, this tool is not part of the official Oracle DB image and I do not want to install any Oracle product in Docker just because of TNSPING.

This is what I have tried so far, but the settings I use have no impact on this timeout.这是我到目前为止所尝试的,但我使用的设置对这个超时没有影响。 The java.sql.SQLRecoverableException: IO Error: The Network Adapter could not establish the connection exception appears after 20 sec. java.sql.SQLRecoverableException: IO Error: The Network Adapter could not establish the connection 20 秒后出现异常。 instead of 1 sec.而不是 1 秒。 Does not matter I use 1, 1000, or 10000 in the java code, the timeout is always 20 sec.没关系,我在 java 代码中使用 1、1000 或 10000,超时始终为 20 秒。

private Connection getConnection(String jdbcUrl) throws SQLException {
    String timeout = "100";
    Properties p = new Properties();
    p.put(OracleConnection.CONNECTION_PROPERTY_THIN_NET_CONNECT_TIMEOUT, timeout);
    p.put(OracleConnection.CONNECTION_PROPERTY_THIN_READ_TIMEOUT, timeout);
    p.put(OracleConnection.CONNECTION_PROPERTY_THIN_JNDI_LDAP_CONNECT_TIMEOUT, timeout);
    p.put(OracleConnection.CONNECTION_PROPERTY_THIN_JNDI_LDAP_READ_TIMEOUT, timeout);
    p.put(OracleConnection.CONNECTION_PROPERTY_THIN_OUTBOUND_CONNECT_TIMEOUT, timeout);
    p.put(OracleConnection.CONNECTION_PROPERTY_DOWN_HOSTS_TIMEOUT, timeout);
    p.put("oracle.jdbc.ReadTimeout", timeout);
    p.put("oracle.net.CONNECT_TIMEOUT", timeout);

    p.put (OracleConnection.CONNECTION_PROPERTY_USER_NAME, user);
    p.put (OracleConnection.CONNECTION_PROPERTY_PASSWORD, password);

    System.setProperty("oracle.net.READ_TIMEOUT", timeout);
    System.setProperty("oracle.jdbc.ReadTimeout", timeout);
    System.setProperty("oracle.jdbc.javaNetNio", "true");

    DriverManager.setLoginTimeout(Integer.valueOf(timeout));
    Connection connection = DriverManager.getConnection(jdbcUrl, p);
    connection.setNetworkTimeout(Executors.newSingleThreadExecutor(), Integer.valueOf(timeout));

    return connection;
}

I do not want to add a connection pool solution to my simple app, only pure JDBC can be enough for me.我不想在我的简单应用程序中添加连接池解决方案,只有纯 JDBC 对我来说就足够了。

What I missed here?我在这里错过了什么?

-- UPDATE -- - 更新 -

It seems that the issue is environment-specific and maybe not related to Java, but still not sure.似乎问题是特定于环境的,可能与 Java 无关,但仍不确定。

If I execute exactly the same command in my machine and in Docker then I get back total different execution times:如果我在我的机器和 Docker 中执行完全相同的命令,那么我会得到不同的执行时间:

command:命令:

$ time java -jar sql-runner-0.2.0-SNAPSHOT-with-dependencies.jar -j jdbc:oracle:thin:@//somehost:1521/somedb -U "doesnotmatter" -P "password" "select 1 from dual"

The result in docker: docker 中的结果:

IO Error: Unknown host specified 

real    0m20.521s
user    0m0.764s
sys 0m0.097s

The result if I execute it on my machine:如果我在我的机器上执行它的结果:

IO Error: Unknown host specified 

real    0m0.501s
user    0m0.715s
sys 0m0.095s

The complete source code is available here .完整的源代码可在此处获得。

This behavior is so strange.这种行为太奇怪了。

There might be various reasons why this does not work for you:这对您不起作用可能有多种原因:

  • depending on JDBC drivers version timeout can be miliseconds or seconds取决于 JDBC 驱动程序版本超时可以是毫秒或秒
  • some options you set are simply ignored by your driver's version您设置的某些选项会被您的驱动程序版本忽略
  • there might be various issues with DNS, like Oracle SCAN listener sends you redirect to RAC cluster node. DNS 可能存在各种问题,例如 Oracle SCAN 侦听器将您重定向到 RAC 集群节点。 And your client can not resolve that hostname.而且您的客户端无法解析该主机名。

You have these options to diagnose your problem:您有以下选项来诊断您的问题:

strace:追踪:

strace -f -e trace=network -o strace.log java -jar sql-runner-0.2.0-SNAPSHOT-with-dependencies.jar -j jdbc:oracle:thin:@//somehost:1521/somedb -U "doesnotmatter" -P "password" "select 1 from dual"

Debug enabled JDBC driver (*_g.jar):调试启用 JDBC 驱动程序(*_g.jar):

$ java -Doracle.jdbc.Trace=true \ 
-Djava.util.logging.config.file=Logging.properties \
-classpath "ojdbc8_g.jar:..." \
...

$ cat Logging.properties
.level=OFF

#.level=SEVERE
handlers=java.util.logging.FileHandler

#  example of a full pathname in Windows
java.util.logging.FileHandler.pattern=Networkpacket.log

# Predefined levels are: ALL, SEVERE, WARNING, INFO, CONFIG, FINE, FINER,
#                        FINEST, OFF

java.util.logging.FileHandler.limit = 500000000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.level =ALL
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
oracle.net.ns.level = ALL

## Following levels are commented to filter the network packet contents.

#oracle.jdbc.level=oFF
#oracle.jdbc.aq.level=OFF
#oracle.jdbc.driver.level=OFF
#oracle.jdbc.pool.level=OFF
#oracle.jdbc.rowset.level=OFF
#oracle.jdbc.xa.level=OFF
#oracle.sql.level=OFF

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM