在Oracle DB中唯一标识源JDBC进程

时间:2018-04-30 07:15:11

标签: java spring oracle jdbc spring-jdbc

我们正在使用java(Spring和Spring Boot)开发微服务,并且通过JDBC Oracle驱动程序访问我们的Oracle DB。

问题是我们的DBA只能在Oracle端看到“JDBC瘦客户端”已连接。连接的应用程序没有更好的逻辑表示。没有这样的识别,很难知道哪个微服务可能表现不好。其他非JDBC客户端使用主机名清楚地标识自己。

有没有办法更改标识字符串,以便它代表源应用程序/进程的清晰标识?

注意:我们的系统在使用容器的Cloud Foundry上运行,因此无法提供机器名称或类似的东西 - 首选逻辑应用程序名称。

由于

5 个答案:

答案 0 :(得分:1)

数据库用户

如果您将用于连接的数据库用户命名为微服务,则DBA应该能够将连接映射到微服务。

IP地址

对于数据库,连接还包含一个允许的IP地址。使用ip-addresses表到微服务,DBA可能能够将连接映射到微服务。

此致

DBA找到程序员的错误可能是一项令人兴奋的工作。如果程序员和DBA之间的关系得到协调,那么谈话可能会解决它们出现的问题(在代码中)。如果不能尽快进行协调,则可能需要更详细的合同或规范。

它看起来像一个解决方法。错误在代码中,让我们在代码中找到它。

取消API的资格

如果您希望通过数据库连接识别微服务,则取消资格使用API​​进行数据库访问。如果您希望将单一来源作为微服务,那么数据库API可能会很有用。

答案 1 :(得分:1)

根据您的Oracle版本,该功能在该方法中实现 setEndToEndMetrics(自12.1以来已经弃用了setClientInfo()) 或setClientInfo

这是一个小用法示例。获取连接后(通常来自连接池)的客户端(您的服务)设置属性 actionclientIdmodule

String[] metrics = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
 metrics[OracleConnection.END_TO_END_ACTION_INDEX] = 'myAction1';
 metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = 'myClient';
 metrics[OracleConnection.END_TO_END_MODULE_INDEX] = 'myModule1';
 con.setEndToEndMetrics(metrics, (short) 0);

并在返回连接之前重置它们。

DBA可能会使用以下查询

来观察V$SESSION中的设置
select sid,  client_info, module, action from v$session

所以她不仅可以将数据库会话与服务相关联,而且客户端/模块和操作的组合可以提供服务状态的更多细节。

需要考虑三件事:

仅当所有服务在设置值时建立某些纪律时,才能执行此操作。在重用连接池中的会话时,很容易继承"继承"来自前任服务的错误设置。我建议将其作为连接池资源处理的一个方面来实现。

此外,Java版本,JDBC驱动程序和Oracle Server必须具有兼容版本,因此在一个简单的脚本中测试功能是一种很好的做法。

最终 DON' T 用于设置PL/SQL API(PL / SQL开发人员自然会这样做)。最大的区别是PL / SQL API触发到数据库的往返,而JDBC API没有(这些值是在下一个请求时发送的)。

答案 2 :(得分:0)

JDBC连接属性“oracle.jdbc.v$session.process”可以设置(作为系统prop -D)到唯一标识您的微服务的值,然后可以在V $ SESSION视图中检索(“process”列)。

答案 3 :(得分:0)

谢谢大家的建议, 我已经尝试了所有这些,可悲的是它们没有用。

这可能是因为我使用Spring Data和默认的Hikari连接池进行连接。

花了几个小时后,最终的解决方案在这里找到:Spring Boot 1.3.5 with Hikari Connection Pool not able to set program name in v$session

spring:
  datasource:
    hikari:
      data-source-properties:
         v$session.program: AppName

简单,没有代码更改,而且有效!

答案 4 :(得分:0)

如果您有权访问连接到Oracle数据库的代码,则可以尝试:

private static String getProcessId(final String fallback) {
 // Note: may fail in some JVM implementations
 // therefore fallback has to be provided
 // something like '<pid>@<hostname>', at least in SUN / Oracle JVMs
 final String jvmName = ManagementFactory.getRuntimeMXBean().getName();
 final int index = jvmName.indexOf('@');

 if (index < 1) {
   // part before '@' empty (index = 0) / '@' not found (index = -1)
   return fallback;
 }

 try {
   return Long.toString(Long.parseLong(jvmName.substring(0, index)));
   } catch (NumberFormatException e) {
   // ignore
   }
 return fallback;
 }



public void init() {
    java.util.Properties props = new java.util.Properties();
    String javaPid;
    try {
        oracleConnexionPool = new OracleConnectionPoolDataSource();
        oracleConnexionPool.setDriverType(oracle.jdbc.driver.OracleDriver);
        //Java 9+ version:
        //long pid = ProcessHandle.current().pid();
        //Java < 9 version:
        try
        {
            javaPid = getProcessId("<PID>");
            props.put("v$session.process", javaPid);
            props.put("v$session.program", "<Your program name>");
            oracleConnexionPool.setConnectionProperties(props);
        }
        catch (SQLException e) {
            }

        oracleConnexionPool.setURL(<DB URL>);

如果您有权访问正在启动Java的命令行,请尝试:

java ...-Doracle.jdbc.v\$session.process=$$ ...

用于标识会话“属于”谁的可用关键字是(Unix样式的语法):

java ...-Doracle.jdbc.v\$session.process=<My PID> \
  -Doracle.jdbc.v\$session.machine="<My machine>" \
  -Doracle.jdbc.v\$session.osuser="<My OS username>" \
  -Doracle.jdbc.v\$session.program="<My program>" \
  -Doracle.jdbc.v\$session.terminal="<My term>" ...