如何在不使用 Tomcat JDBC 的情况下为基于 Hikari 的项目设置 AWS X-Ray SQL 检测?
How do I set up AWS X-Ray SQL Instrumentation for Hikari based projects without using Tomcat JDBC?
目前AWS Documentation for AWS X-Ray没有对Java项目不使用TomcatJDBC给出任何解决方案。
为了使用 spring-boot-data-jpa
检测数据库查询,您还需要包括 Tomcat JDBC 作为依赖项,并设置 Tomcat DataSource 对象以及你的 Hikari 拦截器,并通过以下任一方式将 XRay 拦截器作为 JDBC 拦截器包括在内:
- 使用以下方法将其添加到您的配置中:
dataSource.setJdbcInterceptors("com.amazonaws.xray.sql.postgres.TracingInterceptor;");
- 作为 属性:
spring.datasource.jdbc-interceptors=com.amazonaws.xray.sql.postgres.TracingInterceptor
Gradle:
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation "com.amazonaws:aws-java-sdk-core"
implementation "com.amazonaws:aws-xray-recorder-sdk-core" // Required for core xray features
implementation "com.amazonaws:aws-xray-recorder-sdk-spring" // Required for spring annotations
implementation "com.amazonaws:aws-xray-recorder-sdk-sql-postgres" // required for db callouts
implementation 'org.apache.tomcat:tomcat-jdbc:9.0.31'
...
}
数据库配置(Spring):
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
final org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
dataSource.setUsername(getUsername());
dataSource.setPassword(getPassword());
dataSource.setUrl(POSTGRES_URL_PREFIX
+ getHost()
+ ":" + getPort()
+ "/" + getName()
+ "?stringtype=unspecified");
dataSource.setDriverClassName(getDriver());
dataSource.setJdbcInterceptors("com.amazonaws.xray.sql.postgres.TracingInterceptor;");
final HikariDataSource hikariDataSource = new HikariDataSource();
hikariDataSource.setDataSource(dataSource);
return hikariDataSource;
}
我觉得这很笨拙,如果可能的话,我宁愿不必将 Tomcat JDBC 作为附加依赖项。
不使用 Tomcat 就没有办法解决这个问题吗?
其他说明:
Spring 启动 2.1.7
Gradle6.0.1
适用于 Java 2.4.0
的 AWS SDK
事实证明,someone else had this question. The AWS developers have been working on this in a feature branch 已于 2019 年 11 月合并到 SDK 版本 2.3.0
。
我还没有找到关于这个新功能的任何文档,所以在深入研究 PR 代码之后,我发现它比以前的实现更简单。
只需将以下依赖项而不是 postgres 特定的依赖项添加到您的 build.gradle
文件(或类似文件)中:
implementation "com.amazonaws:aws-java-sdk-core:2.4.0"
implementation "com.amazonaws:aws-xray-recorder-sdk-core:2.4.0"
implementation "com.amazonaws:aws-xray-recorder-sdk-sql:2.4.0"
然后只需在您的数据源配置中创建一个 TracingDataSource
对象,并将您的原始 javax.sql.DataSource
对象传递给它。这应该在您用来创建 DataSource
bean 的任何 @Configuration
注释 class 中完成。
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
final DataSource dataSource = DataSourceBuilder
.create()
.username(getUsername())
.password(getPassword())
.url(POSTGRES_URL_PREFIX
+ getHost()
+ ":" + getPort()
+ "/" + getName()
+ "?stringtype=unspecified")
.driverClassName(getDriver())
.build();
final TracingDataSource tracingDataSource = new TracingDataSource(dataSource);
return tracingDataSource;
}
仅此而已。我真的希望这对某人有帮助,因为我花了很多时间试图在没有 Tomcat 的情况下使它工作,而且 AWS 文档在这里也没有帮助。
J Hamm 的回答无疑提供了一个很好的起点,但我不想手动设置 DataSourceBuilder
属性。此外,没有为我设置 Hikari 特定属性。我最终得到以下结果:
@Bean
@Primary
@ConfigurationProperties("spring.datasource")
//DataSourceProperties will convert `spring.datasource.url` property to hikari's jdbcUrl property
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "hikariDataSource")
@ConfigurationProperties(prefix = "spring.datasource.hikari")//set hikari specific properties
public HikariDataSource hikariDataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Bean(name = "dataSource")
@Primary
public DataSource dataSource(HikariDataSource hikariDataSource) {
//wrap the spring ds into xray tracing ds
var tracingDataSource = new TracingDataSource(hikariDataSource);
return tracingDataSource;
}
不幸的是,所有这些最终都白费了,因为 x-ray 不记录执行的 SQL 语句,这使得它几乎毫无用处。参见 https://github.com/aws/aws-xray-sdk-java/issues/28
使用 TracingDataSource 解决了同样的问题,同时仍然使用 HikariCP 作为连接池
引用https://github.com/aws/aws-xray-sdk-java/issues/88#issuecomment-570328275
代码:(注意,我正在使用 AWS Secrets Manager JDBC 库 aws-secretsmanager-jdbc
使用存储在 AWS Secrets Manager 中的秘密连接到数据库)
import com.amazonaws.xray.sql.TracingDataSource;
...
...
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return TracingDataSource
.decorate(DataSourceBuilder.create()
.driverClassName("com.amazonaws.secretsmanager.sql.AWSSecretsManagerPostgreSQLDriver")
.url("jdbc-secretsmanager:postgresql://" + System.getenv("PGHOST") + ":"
+ System.getenv("PGPORT") + "/" + System.getenv("PGDATABASE"))
.username(System.getenv("SECRET_NAME")).build());
}
依赖关系:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-sql</artifactId>
</dependency>
目前AWS Documentation for AWS X-Ray没有对Java项目不使用TomcatJDBC给出任何解决方案。
为了使用 spring-boot-data-jpa
检测数据库查询,您还需要包括 Tomcat JDBC 作为依赖项,并设置 Tomcat DataSource 对象以及你的 Hikari 拦截器,并通过以下任一方式将 XRay 拦截器作为 JDBC 拦截器包括在内:
- 使用以下方法将其添加到您的配置中:
dataSource.setJdbcInterceptors("com.amazonaws.xray.sql.postgres.TracingInterceptor;");
- 作为 属性:
spring.datasource.jdbc-interceptors=com.amazonaws.xray.sql.postgres.TracingInterceptor
Gradle:
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation "com.amazonaws:aws-java-sdk-core"
implementation "com.amazonaws:aws-xray-recorder-sdk-core" // Required for core xray features
implementation "com.amazonaws:aws-xray-recorder-sdk-spring" // Required for spring annotations
implementation "com.amazonaws:aws-xray-recorder-sdk-sql-postgres" // required for db callouts
implementation 'org.apache.tomcat:tomcat-jdbc:9.0.31'
...
}
数据库配置(Spring):
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
final org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
dataSource.setUsername(getUsername());
dataSource.setPassword(getPassword());
dataSource.setUrl(POSTGRES_URL_PREFIX
+ getHost()
+ ":" + getPort()
+ "/" + getName()
+ "?stringtype=unspecified");
dataSource.setDriverClassName(getDriver());
dataSource.setJdbcInterceptors("com.amazonaws.xray.sql.postgres.TracingInterceptor;");
final HikariDataSource hikariDataSource = new HikariDataSource();
hikariDataSource.setDataSource(dataSource);
return hikariDataSource;
}
我觉得这很笨拙,如果可能的话,我宁愿不必将 Tomcat JDBC 作为附加依赖项。
不使用 Tomcat 就没有办法解决这个问题吗?
其他说明:
Spring 启动 2.1.7
Gradle6.0.1
适用于 Java 2.4.0
的 AWS SDK
事实证明,someone else had this question. The AWS developers have been working on this in a feature branch 已于 2019 年 11 月合并到 SDK 版本 2.3.0
。
我还没有找到关于这个新功能的任何文档,所以在深入研究 PR 代码之后,我发现它比以前的实现更简单。
只需将以下依赖项而不是 postgres 特定的依赖项添加到您的 build.gradle
文件(或类似文件)中:
implementation "com.amazonaws:aws-java-sdk-core:2.4.0"
implementation "com.amazonaws:aws-xray-recorder-sdk-core:2.4.0"
implementation "com.amazonaws:aws-xray-recorder-sdk-sql:2.4.0"
然后只需在您的数据源配置中创建一个 TracingDataSource
对象,并将您的原始 javax.sql.DataSource
对象传递给它。这应该在您用来创建 DataSource
bean 的任何 @Configuration
注释 class 中完成。
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
final DataSource dataSource = DataSourceBuilder
.create()
.username(getUsername())
.password(getPassword())
.url(POSTGRES_URL_PREFIX
+ getHost()
+ ":" + getPort()
+ "/" + getName()
+ "?stringtype=unspecified")
.driverClassName(getDriver())
.build();
final TracingDataSource tracingDataSource = new TracingDataSource(dataSource);
return tracingDataSource;
}
仅此而已。我真的希望这对某人有帮助,因为我花了很多时间试图在没有 Tomcat 的情况下使它工作,而且 AWS 文档在这里也没有帮助。
J Hamm 的回答无疑提供了一个很好的起点,但我不想手动设置 DataSourceBuilder
属性。此外,没有为我设置 Hikari 特定属性。我最终得到以下结果:
@Bean
@Primary
@ConfigurationProperties("spring.datasource")
//DataSourceProperties will convert `spring.datasource.url` property to hikari's jdbcUrl property
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "hikariDataSource")
@ConfigurationProperties(prefix = "spring.datasource.hikari")//set hikari specific properties
public HikariDataSource hikariDataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Bean(name = "dataSource")
@Primary
public DataSource dataSource(HikariDataSource hikariDataSource) {
//wrap the spring ds into xray tracing ds
var tracingDataSource = new TracingDataSource(hikariDataSource);
return tracingDataSource;
}
不幸的是,所有这些最终都白费了,因为 x-ray 不记录执行的 SQL 语句,这使得它几乎毫无用处。参见 https://github.com/aws/aws-xray-sdk-java/issues/28
使用 TracingDataSource 解决了同样的问题,同时仍然使用 HikariCP 作为连接池
引用https://github.com/aws/aws-xray-sdk-java/issues/88#issuecomment-570328275
代码:(注意,我正在使用 AWS Secrets Manager JDBC 库 aws-secretsmanager-jdbc
使用存储在 AWS Secrets Manager 中的秘密连接到数据库)
import com.amazonaws.xray.sql.TracingDataSource;
...
...
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return TracingDataSource
.decorate(DataSourceBuilder.create()
.driverClassName("com.amazonaws.secretsmanager.sql.AWSSecretsManagerPostgreSQLDriver")
.url("jdbc-secretsmanager:postgresql://" + System.getenv("PGHOST") + ":"
+ System.getenv("PGPORT") + "/" + System.getenv("PGDATABASE"))
.username(System.getenv("SECRET_NAME")).build());
}
依赖关系:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-sql</artifactId>
</dependency>