简体   繁体   English

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

[英]Uniquely identify source JDBC process in Oracle DB

We are developing microservices using java (Spring and Spring Boot), and the access to our Oracle DB is done via the JDBC Oracle Driver. 我们正在使用java(Spring和Spring Boot)开发微服务,并且通过JDBC Oracle Driver访问我们的Oracle DB。

The problem is that our DBAs can only see on the Oracle side that a "JDBC Thin Client" is connected. 问题是我们的DBA只能在Oracle端看到连接了“JDBC瘦客户端”。 There is no better, logical representation of the connected application. 连接的应用程序没有更好的逻辑表示。 Without such identification, it is hard to know which microservice might be behaving badly. 没有这样的识别,很难知道哪个微服务可能表现不好。 Other non-JDBC clients identify themselves clearly with the hostname. 其他非JDBC客户端使用主机名清楚地标识自己。

Is there any way to change the identification String so that it represents a clear identity of the source application/process? 有没有办法更改标识字符串,以便它代表源应用程序/进程的清晰标识?

Note: Our system runs on Cloud Foundry which uses containers, so a it's not really possible to provide a machine name or anything like that - a logical application name would be preferred. 注意:我们的系统在使用容器的Cloud Foundry上运行,因此实际上不可能提供机器名称或类似的东西 - 首选逻辑应用程序名称。

Thanks 谢谢

Database users 数据库用户

If you name the Database users used for connection like the Microservice, the DBA should be able to map the connections to the microservices. 如果您将用于连接的数据库用户命名为Microservice,则DBA应该能够将连接映射到微服务。

IP addresses IP地址

For a Database a connection also contains an incomming IP address. 对于数据库,连接还包含一个允许的IP地址。 Using a table of ip-addresses to microservices, the DBA might be able to map the connections down to the microservice. 使用ip-addresses表到微服务,DBA可能能够将连接映射到微服务。

Respectfully 尊敬

It might be a exciting work for DBA to find the Programmers faults. DBA找到程序员故障可能是一项令人兴奋的工作。 If the realtionship between Programmers and DBAs is harmonized, a talk might solve the problem where they occour (in the code). 如果程序员和DBA之间的关系得到协调,那么谈话可能会解决它们出现的问题(在代码中)。 If no harmonization is possible soon, a more detailed contract or specification might be a solution. 如果不能尽快进行协调,则更详细的合同或规范可能是一种解决方案。

It looks like a Workaround. 它看起来像一个变通方法。 The bug is in the code, lets find it in the code. 错误在代码中,让我们在代码中找到它。

Disqualification of API 取消API资格

If you like to identify the Microservice by the Database connection, you disqualificate the use of a API for the database access. 如果您希望通过数据库连接识别微服务,则取消资格使用API​​进行数据库访问。 The Database API might be usefull if you like to have the Single-Source-Of-Truth as a Microservice. 如果您希望将Single-Source-Of-Thuth作为微服务,那么Database API可能会很有用。

Depending on your Oracle version, the feature is implemented in the method setEndToEndMetrics (It has been deprecated since 12.1 in favor of setClientInfo()) or setClientInfo 根据您的Oracle版本,该功能在方法setEndToEndMetrics中实现 (自12.1以来已弃用,有利于setClientInfo())或setClientInfo

Here a small example of the usage. 这里是一个小例子的用法。 The client (your service) after acquiring a connection (typically from a connection pool) sets the properties action , clientId and module 获取连接后的客户端(您的服务)(通常来自连接池)设置属性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);

and resets them before returning the connection. 并在返回连接之前重置它们。

The DBA may observe the setting in the V$SESSION with the following query DBA可以使用以下查询观察V$SESSION的设置

select sid,  client_info, module, action from v$session

so she is possible to relate the database session no only with the service, but the combination of client / module and action may provide further details of the state of the service. 因此,她可以将数据库会话不仅与服务相关联,而且客户端/模块和动作的组合可以提供服务状态的进一步细节。

Three things are important to consider: 有三件事需要考虑:

This work only if all services establish certain discipline in setting the values. 仅当所有服务在设置值时建立某些规则时 ,此工作才有效。 While re-using the sessions from the connection pool it is easy to "inherit" a wrong setting from a predecessor service. 在重用连接池中的会话时,很容易从先前服务“继承”错误的设置。 I'd recomment to implement it as an aspect of the connection pool resource handling. 我建议将其作为连接池资源处理的一个方面来实现。

Further the Java version, JDBC driver and Oracle Server must have compatible versions , so it is a good practice to test the functionality in a simple script. 此外,Java版本,JDBC驱动程序和Oracle Server必须具有兼容版本 ,因此在简单脚本中测试功能是一种很好的做法。

Finaly DON'T use for the setting the PL/SQL API (which a PL/SQL developer would naturally do). 最后不要用于设置PL / SQL API (PL / SQL开发人员自然会这样做)。 The great difference is that the PL/SQL API triggers a roundtrip to the database, while JDBC API not (the values are send with the next request). 最大的区别是PL / SQL API触发到数据库的往返,而JDBC API没有(这些值是在下一个请求时发送的)。

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

Thank you everyone for your suggestions, I have tried them all and sadly they did not work. 谢谢大家的建议,我已经尝试了所有这些,可悲的是他们没有工作。

This is probably since I am connection using Spring Data and the default Hikari connection pool. 这可能是因为我使用Spring Data和默认的Hikari连接池进行连接。

After spending hours on it, the final solution was found here: Spring Boot 1.3.5 with Hikari Connection Pool not able to set program name in v$session 花了几个小时后,最终的解决方案在这里找到: Spring Boot 1.3.5与Hikari Connection Pool无法在v $ session中设置程序名称

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

Simple, no code changes, and it works! 简单,没有代码更改,它的工作原理!

If you have access to the code that connects to the Oracle Database, you can try: 如果您可以访问连接到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>);

If you have access to the command-line which is launching java, try: 如果您有权访问启动java的命令行,请尝试:

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

The available keywords for identifying to whom a session "belongs to" are (Unix-style syntax): 用于标识会话“属于”的可用关键字是(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>" ...

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

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