根据我所做的研究,似乎由于Amazon Elasticsearch仅支持HTTP,所以这两者不能一起使用。
希望有人能澄清,是否Spring Data Elasticsearch也不支持这种情况。
根据我所做的研究,似乎由于Amazon Elasticsearch仅支持HTTP,所以这两者不能一起使用。
希望有人能澄清,是否Spring Data Elasticsearch也不支持这种情况。
看起来从3.2.0版本开始,Spring data elastic search可以使用http rest client工作,因此可以通过Rest API和端口443连接到AWS Elastic实例。不知何故,他们将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 和 Searchly
- 传输协议的端口
以及 AWS 关于 ES 服务限制的文档;请到底部,最后一行写道:
该服务支持80端口的HTTP,但不支持TCP传输。
目前还无法使用使用Java API的Spring Data ES与只能通过REST进行访问的Amazon服务。
有一个很不错的项目,提供了Spring Data ES的Jest实现,可以与AWS托管的ES服务一起使用。
Spring Data ElasticSearch已与最新的ElasticSearch标准整合,因此从spring-data-elasticsearch:3.2.X
开始,它提供了一种灵活的方式来实现自定义的RestHighLevelClient
。(link)
虽然可以使用基于HTTP的ElasticSearch API调用,无论是否进行身份验证,但这不会解决与AWS ElasticSearch API调用相关的问题。
因为任何针对AWS服务或APIGW支持的服务的HTTP请求都必须遵循"签名版本4签名过程(SigV4)"
,最终通过HTTP发送的AWS请求将添加身份验证信息。出于安全考虑,大多数对AWS的请求必须使用访问密钥进行签名,其中包括一个accesskey ID
和一个secret access key
。因此,在调用AWS ElasticSearch服务时,我们必须遵循标准。
让我们动手编码,深入了解实现细节
请按照以下步骤操作: <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>
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,则必须为您的 Amazon ECS 任务分配 IAM 角色 了解更多。
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
**RestHighLevelClient**
给抽象方法 **AbstractElasticsearchConfiguration#elasticsearchClient()**
。通过这种方式,我们将 "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 elastic的优势以及Amazon弹性搜索服务。完整的解决方案已在Medium Post中记录。
如果涉及访问索引(例如刷新)的权限问题,请使用answer添加权限。
AWSCredentialsProvider
。请验证您的凭证accessKey
和secretId
。我已经在超过2个微服务中使用了这个片段。我没有遇到过403问题。 - Prasanth Rajendran我在与 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