我们正在使用java(Spring和Spring Boot)开发微服务,并且通过JDBC Oracle驱动程序访问我们的Oracle DB。
问题是我们的DBA只能在Oracle端看到“JDBC瘦客户端”已连接。连接的应用程序没有更好的逻辑表示。没有这样的识别,很难知道哪个微服务可能表现不好。其他非JDBC客户端使用主机名清楚地标识自己。
有没有办法更改标识字符串,以便它代表源应用程序/进程的清晰标识?
注意:我们的系统在使用容器的Cloud Foundry上运行,因此无法提供机器名称或类似的东西 - 首选逻辑应用程序名称。
由于
答案 0 :(得分:1)
如果您将用于连接的数据库用户命名为微服务,则DBA应该能够将连接映射到微服务。
对于数据库,连接还包含一个允许的IP地址。使用ip-addresses表到微服务,DBA可能能够将连接映射到微服务。
DBA找到程序员的错误可能是一项令人兴奋的工作。如果程序员和DBA之间的关系得到协调,那么谈话可能会解决它们出现的问题(在代码中)。如果不能尽快进行协调,则可能需要更详细的合同或规范。
它看起来像一个解决方法。错误在代码中,让我们在代码中找到它。
如果您希望通过数据库连接识别微服务,则取消资格使用API进行数据库访问。如果您希望将单一来源作为微服务,那么数据库API可能会很有用。
答案 1 :(得分:1)
根据您的Oracle版本,该功能在该方法中实现 setEndToEndMetrics(自12.1以来已经弃用了setClientInfo()) 或setClientInfo
这是一个小用法示例。获取连接后(通常来自连接池)的客户端(您的服务)设置属性
action
,clientId
和module
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>" ...