【发布时间】:2016-03-04 18:06:00
【问题描述】:
从我所做的研究看来,这两者似乎不能一起工作,因为 HTTP 仅支持 Amazon Elasticsearch。
希望有人能澄清一下 Spring Data Elasticsearch 是否无法实现这一点。
【问题讨论】:
标签: spring spring-data spring-data-elasticsearch amazon-elasticsearch
从我所做的研究看来,这两者似乎不能一起工作,因为 HTTP 仅支持 Amazon Elasticsearch。
希望有人能澄清一下 Spring Data Elasticsearch 是否无法实现这一点。
【问题讨论】:
标签: spring spring-data spring-data-elasticsearch amazon-elasticsearch
可以将 Spring Data Elasticsearch 与 Amazon Elasticsearch 结合使用
摘自 Spring-data 弹性搜索doc
TransportClient 自 Elasticsearch 7 起已弃用,并将 在 Elasticsearch 8 中删除。这有利于 Java 高级 REST 客户。 Spring Data Elasticsearch 将支持 TransportClient 作为 只要它在 Elasticsearch 中可用。
Java 高级 REST 客户端现在是默认客户端 Elasticsearch,它为 TransportClient 因为它接受并返回相同的 请求/响应对象,因此依赖于 Elasticsearch 核心项目
Spring Data ElasticSearch 已根据 ElasticSearch 的最新标准进行了精简,因此从 spring-data-elasticsearch:3.2.X 它提供了一种灵活的方式来实现自定义 RestHighLevelClient。(@987654322 @)
即使可以使用基于 HTTP 的弹性搜索 API 调用(有或没有身份验证),但它不会解决与 AWS 弹性搜索 API 调用相关的问题。
因为对 AWS 服务或 APIGW 支持的服务 的任何 HTTP 请求 都必须遵循 "Signature Version 4 Signing Process(SigV4)" 最终将身份验证信息添加到发送的 AWS 请求中通过 HTTP。为安全起见,大多数对 AWS 的请求都必须使用访问密钥进行签名,该密钥由 accesskey ID 和 secret access key 组成。因此,我们在调用 AWS ElasticSearch 服务时必须遵循标准。
让我们动手编写代码并深入研究实现
请按以下步骤操作:
第 1 步:添加所需的依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-elasticsearch</artifactId>
<version>1.11.346</version>
</dependency>
第 2 步:添加 AWS CredentialsProvider
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AWSCredentialsConfiguration {
@Value("${aws.es.accessKey}")
private String esAccessKey = null;
@Value("${aws.es.secretKey}")
private String esSecretKey = null;
@Bean
public AWSStaticCredentialsProvider awsDynamoCredentialsProviderDevelopment() {
return new AWSStaticCredentialsProvider(new BasicAWSCredentials(
esAccessKey, esSecretKey));
}
}
或者,如果您的应用程序在 AWS 实例上运行并且您不想使用属性驱动/硬编码的 AccessKey 和 SecretKey,那么您必须将 IAM 角色分配给您的 Amazon ECS任务 for more.
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AWSCredentialsConfiguration {
@Bean
public AWSCredentialsProvider amazonAWSCredentialsProvider() {
return new EC2ContainerCredentialsProviderWrapper();
}
}
第 3 步:添加 ElasticSearchRestClientConfiguration
**AbstractElasticsearchConfiguration#elasticsearchClient()** 提供**RestHighLevelClient** 的自定义实现。这样,我们将 "elasticsearchOperations"、"elasticsearchTemplate" bean 合并的 customRestHighLevelClient 注入到 spring 容器中。HttpRequestInterceptor 是另一个需要注意的重要事项。特别感谢AWSRequestSigningApacheInterceptor.java,AWSLabs提供的示例实现帮助我们通过AWS4Signer机制将拦截器添加到RestClient。@EnableElasticsearchRepositories 注释有助于启用 elasticsearch 数据存储库。import com.amazonaws.auth.AWS4Signer;
import com.amazonaws.auth.AWSCredentialsProvider;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequestInterceptor;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.demo.aws.elasticsearch.data.repository")
public class ElasticSearchRestClientConfiguration extends AbstractElasticsearchConfiguration {
@Value("${aws.es.endpoint}")
private String endpoint = null;
@Value("${aws.es.region}")
private String region = null;
@Autowired
private AWSCredentialsProvider credentialsProvider = null;
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
AWS4Signer signer = new AWS4Signer();
String serviceName = "es";
signer.setServiceName(serviceName);
signer.setRegionName(region);
HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor(serviceName, signer, credentialsProvider);
return new RestHighLevelClient(RestClient.builder(HttpHost.create(endpoint)).setHttpClientConfigCallback(e -> e.addInterceptorLast(interceptor)));
}
}
太棒了祖鲁!而已。我们已经完成了配置部分。现在有了这个解决方案,您可以利用 spring-data 弹性优势以及 Amazon 弹性搜索服务。完整的解决方案已记录在Medium Post
如果有任何与访问索引的权限相关的问题(例如:刷新),您可以使用answer添加权限
【讨论】:
AWSCredentialsProvider。请验证您的凭据accessKey 和secretId。我已经将这个 sn-p 用于 2 个以上的微服务。没见过这样的403问题
我在与 aws es 堆栈相同的配置中收到以下错误,如本文中所示https://medium.com/@prasanth_rajendran/how-to-integrate-spring-boot-elasticsearch-data-with-aws-445e6fc72998
Error creating bean with name 'supplierContacts' defined in file ... Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'supplierContactListDaoImpl' defined in file [SupplierContactListDaoImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'supplierContactListRepository': Cannot resolve reference to bean 'elasticsearchTemplate' while setting bean property 'elasticsearchOperations'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elasticsearchOperations' defined in class path resource [ElasticSearchConfig.class]: Unsatisfied dependency expressed through method 'elasticsearchOperations' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchEntityMapper' defined in class path resource [ElasticSearchConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter]: Factory method 'elasticsearchEntityMapper' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/data/mapping/model/EntityInstantiators
【讨论】:
看起来 3.2.0 版的 Spring 数据弹性搜索与 http rest 客户端一起工作,因此可以通过 Rest API 和端口 443 连接到 aws 弹性实例。他们以某种方式将 spring-data-jest 方法集成到 spring 数据中。 我使用 RestHighLevelClient:
@Bean
public RestHighLevelClient client() {
return new RestHighLevelClient(RestClient.builder(HttpHost.create(awsUrl)));
}
awsUrl 格式为:https://some_aws_generated_address.us-east-n.es.amazonaws.com:443
注意:如果你使用默认 bom.xml 的 spring boot,你需要将 spring boot 升级到 2.2.1.RELEASE 或更新版本
【讨论】:
有一个很好的项目提供 Spring Data ES 的 Jest 实现,它与 AWS 托管的 ES 服务一起使用。
【讨论】:
来自不同的讨论:
- Spring data ES and searchly
- port for the transport protocol
和AWS documentation on ES service limitations;转到底部,最后一行说:
该服务在端口 80 上支持 HTTP,但不支持 TCP 传输。
目前还不能使用使用 Java API 的 Spring Data ES,以及只能通过 REST 获得的 Amazon 服务。
【讨论】: