使用AWS SDK v1时,如何用Apache HttpClient5/RestClient连接AWS OpenSearch
基于AWS SDK v1,通过Apache Transport连接AWS OpenSearch集群
由于你使用AWS SDK v1且无法弃用相关依赖,同时高级REST客户端已被标记为弃用,以下是两种可行的实现方案,核心是通过AWS SDK v1的签名工具为请求添加AWS身份验证签名,结合OpenSearch的Apache Transport客户端完成连接。
方案1:使用Apache RestClient Transport(基于Apache HttpClient 4.x)
1. 依赖配置(Maven)
<!-- OpenSearch Java Client --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-java</artifactId> <version>2.11.0</version> <!-- 替换为与集群兼容的版本 --> </dependency> <!-- OpenSearch RestClient Transport --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-rest-client</artifactId> <version>2.11.0</version> </dependency> <!-- AWS SDK v1 Core --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-core</artifactId> <version>1.12.500</version> <!-- 替换为你正在使用的SDK v1版本 --> </dependency> <!-- Apache HttpClient 4.x --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency>
2. 实现AWS签名拦截器
创建HttpClient拦截器,用AWS SDK v1的AWS4Signer对请求签名:
import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.auth.Signer; import com.amazonaws.auth.AWS4Signer; import com.amazonaws.regions.Regions; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.protocol.HttpContext; import java.io.IOException; import java.net.URI; public class AwsRequestSigningInterceptor implements HttpRequestInterceptor { private final Signer signer; private final AWSCredentialsProvider credentialsProvider; private final String serviceName; private final String region; public AwsRequestSigningInterceptor(String serviceName, String region) { this.signer = new AWS4Signer(); this.credentialsProvider = new DefaultAWSCredentialsProviderChain(); this.serviceName = serviceName; this.region = region; ((AWS4Signer) this.signer).setServiceName(serviceName); ((AWS4Signer) this.signer).setRegionName(region); } @Override public void process(HttpRequest request, HttpContext context) throws IOException { URI uri = URI.create(request.getRequestLine().getUri()); com.amazonaws.http.HttpRequest awsRequest = new com.amazonaws.http.HttpRequest( com.amazonaws.http.HttpMethodName.fromValue(request.getRequestLine().getMethod()), uri ); // 复制原请求头 request.getAllHeaders().forEach(header -> awsRequest.addHeader(header.getName(), header.getValue())); // 执行签名 signer.sign(awsRequest, credentialsProvider.getCredentials()); // 将签名后的头写回原请求 awsRequest.getHeaders().forEach((key, values) -> { request.removeHeaders(key); values.forEach(value -> request.addHeader(key, value)); }); } }
3. 创建OpenSearchClient实例
import org.apache.http.HttpHost; import org.apache.http.impl.client.HttpClientBuilder; import org.opensearch.client.RestClient; import org.opensearch.client.RestClientBuilder; import org.opensearch.client.json.jackson.JacksonJsonpMapper; import org.opensearch.client.opensearch.OpenSearchClient; import org.opensearch.client.transport.rest_client.RestClientTransport; public class OpenSearchAwsClientFactory { public static OpenSearchClient createClient(String opensearchEndpoint, String region) { // 解析OpenSearch集群端点 HttpHost host = HttpHost.create(opensearchEndpoint); // 构建带签名拦截器的HttpClient HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); httpClientBuilder.addInterceptorFirst(new AwsRequestSigningInterceptor("es", region)); // 构建RestClient RestClientBuilder restClientBuilder = RestClient.builder(host) .setHttpClientConfigCallback(builder -> httpClientBuilder); // 创建Transport和OpenSearchClient RestClientTransport transport = new RestClientTransport( restClientBuilder.build(), new JacksonJsonpMapper() ); return new OpenSearchClient(transport); } // 测试示例 public static void main(String[] args) { String endpoint = "https://your-opensearch-domain.us-east-1.es.amazonaws.com"; String region = Regions.US_EAST_1.getName(); OpenSearchClient client = createClient(endpoint, region); try { var response = client.info(); System.out.println("集群名称: " + response.clusterName()); } catch (Exception e) { e.printStackTrace(); } } }
方案2:使用Apache HttpClient 5 Transport
若需使用Apache HttpClient 5,核心逻辑一致,但拦截器和依赖配置需适配HttpClient 5的API:
1. 依赖配置(Maven)
<!-- OpenSearch Java Client --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-java</artifactId> <version>2.11.0</version> </dependency> <!-- OpenSearch HttpClient 5 Transport --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-httpclient5</artifactId> <version>2.11.0</version> </dependency> <!-- AWS SDK v1 Core --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-core</artifactId> <version>1.12.500</version> </dependency> <!-- Apache HttpClient 5 --> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.2.1</version> </dependency>
2. 实现AWS签名拦截器(HttpClient 5版本)
import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.auth.Signer; import com.amazonaws.auth.AWS4Signer; import com.amazonaws.regions.Regions; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.protocol.HttpContext; import java.io.IOException; import java.net.URI; public class AwsRequestSigningInterceptor5 implements HttpRequestInterceptor { private final Signer signer; private final AWSCredentialsProvider credentialsProvider; private final String serviceName; private final String region; public AwsRequestSigningInterceptor5(String serviceName, String region) { this.signer = new AWS4Signer(); this.credentialsProvider = new DefaultAWSCredentialsProviderChain(); this.serviceName = serviceName; this.region = region; ((AWS4Signer) this.signer).setServiceName(serviceName); ((AWS4Signer) this.signer).setRegionName(region); } @Override public void process(HttpRequest request, HttpContext context) throws IOException { URI uri = URI.create(request.getRequestUri()); com.amazonaws.http.HttpRequest awsRequest = new com.amazonaws.http.HttpRequest( com.amazonaws.http.HttpMethodName.fromValue(request.getMethod()), uri ); // 复制原请求头 request.getHeaders().forEach(header -> awsRequest.addHeader(header.getName(), header.getValue())); // 执行签名 signer.sign(awsRequest, credentialsProvider.getCredentials()); // 将签名后的头写回原请求 awsRequest.getHeaders().forEach((key, values) -> { request.removeHeaders(key); values.forEach(value -> request.addHeader(key, value)); }); } }
3. 创建OpenSearchClient实例
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.core5.http.HttpHost; import org.opensearch.client.httpclient5.HttpClient5Transport; import org.opensearch.client.httpclient5.HttpClient5TransportBuilder; import org.opensearch.client.json.jackson.JacksonJsonpMapper; import org.opensearch.client.opensearch.OpenSearchClient; public class OpenSearchAwsClientFactory5 { public static OpenSearchClient createClient(String opensearchEndpoint, String region) { HttpHost host = HttpHost.create(opensearchEndpoint); // 构建带签名拦截器的HttpClient 5 HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); httpClientBuilder.addRequestInterceptorFirst(new AwsRequestSigningInterceptor5("es", region)); // 构建HttpClient5Transport HttpClient5Transport transport = HttpClient5TransportBuilder.builder(host) .setHttpClient(httpClientBuilder.build()) .setMapper(new JacksonJsonpMapper()) .build(); return new OpenSearchClient(transport); } // 测试示例 public static void main(String[] args) { String endpoint = "https://your-opensearch-domain.us-east-1.es.amazonaws.com"; String region = Regions.US_EAST_1.getName(); OpenSearchClient client = createClient(endpoint, region); try { var response = client.info(); System.out.println("集群名称: " + response.clusterName()); } catch (Exception e) { e.printStackTrace(); } } }
关键注意事项
- 确保OpenSearch Java Client版本与AWS OpenSearch集群版本兼容(如集群2.x对应客户端2.x系列)
DefaultAWSCredentialsProviderChain会自动从环境变量、系统属性、IAM角色等渠道获取凭证,适配EC2、ECS等AWS环境- AWS OpenSearch的服务签名标识固定为
es - 替换代码中的集群端点和区域为实际值
内容的提问来源于stack exchange,提问作者contemplator
相关产品推荐
相关产品推荐

