【问题标题】:Single API, multiple Elasticsearch instances单个 API,多个 Elasticsearch 实例
【发布时间】:2017-05-05 01:47:53
【问题描述】:

我们有一个 Spring Boot Restful API,它需要从 2 个不同的 Elasticsearch 实例(在不同的服务器上)获取数据,1 个用于“共享”数据(上面有大约 5 个不同的索引),1 个用于“私有”数据(有大约 3 个不同的指标)。目前仅针对“私有”数据实例运行,一切都很好。但我们现在需要获取“共享”数据。

在我们的 Spring Boot 应用程序中,我们启用了这样的 Elasticsearch 存储库

@SpringBootApplication
@EnableElasticsearchRepositories(basePackages = {
    "com.company.core.repositories",  //<- private repos here...
    "com.company.api.repositories"  //<-- shared repos here...
})
public class Application { //... }

然后我们使用 ElasticsearchRepository 访问“私有”数据,例如:

package com.company.core.repositories

public interface DocRepository extends ElasticsearchRepository<Doc, Integer> { ... }

在我们的端点中,我们有...

@RestController
@CrossOrigin
@RequestMapping("/v2/statuses/")
public class StatusEndpoint {
    @Resource
    private ElasticsearchTemplate template;

    @Autowired
    private DocRepository docRepository;

    @Autowired
    private Validator validator;
    //...
}

现在我们要添加另一个存储库,例如:

package com.company.api.repositories

public interface LookupRepository extends ElasticsearchRepository<Lookup, Integer> { ... }

然后在我们的 API 层中,我们将添加一个自动连接的实例...

@Autowired
private LookupRepository lookupRepo;

我们认为我们可以定义多个具有不同名称的 Bean,但是我们如何将每个“elasticsearchTemplate”bean 与需要它们的不同 ElasticsearchRepository 实例相关联?此外,我们如何将“私有”bean/配置与注入的实例关联

@Resource
private ElasticsearchTemplate template;

我们需要在哪里原生使用它?

【问题讨论】:

    标签: java spring elasticsearch


    【解决方案1】:

    您可以使用 2 个唯一的 Elasticsearch 配置 bean 和一个 @Resource(name="XXX") 注释来解决此问题,以便在您的 StatusEndpoint 控制器中进行模板注入。

    如果您根据应使用的 Elasticsearch 集群将存储库分成不同的包,则可以使用 @EnableElasticsearchRepositories 注释将它们与不同的配置相关联。

    例如:

    如果你有这些包和类:

    com.company.data.repositories.private.YourPrivateRepository
    com.company.data.repositories.shared.YourSharedRepository
    

    然后是这些配置:

    @Configuration
    @EnableElasticsearchRepositories( 
        basePackages = {"com.company.data.repositories.private"},
        elasticsearchTemplateRef = "privateElasticsearchTemplate")
    public class PrivateElasticsearchConfiguration {
    
        @Bean(name="privateElasticsearchTemplate")
        public ElasticsearchTemplate privateTemplate() {
           //code to create connection to private ES cluster
        }
    }
    

    @Configuration
    @EnableElasticsearchRepositories( 
        basePackages = {"com.company.data.repositories.shared"},
        elasticsearchTemplateRef = "sharedElasticsearchTemplate")
    public class SharedElasticsearchConfiguration {
    
        @Bean(name="sharedElasticsearchTemplate")
        public ElasticsearchTemplate sharedTemplate() {
           //code to create connection to shared ES cluster
        }
    }
    

    由于@EnableElasticsearchRepositories 注释中的elasticsearchTemplateRef 参数,实现存储库的JPA 代码将使用basePackages 列表中的存储库的指定模板。

    对于StatusEndpoint 部分,您只需为您的@Resource 注释提供正确的模板bean 名称。你的StatusEndpoint 看起来像这样:

    @RestController
    @CrossOrigin
    @RequestMapping("/v2/statuses/")
    public class StatusEndpoint {
    
        @Resource(name="privateElasticsearchTemplate")
        private ElasticsearchTemplate template;
    
        @Autowired
        private DocRepository docRepository;
    
        @Autowired
        private Validator validator;
        //...
    }
    

    【讨论】:

    • 这正好适合这个场景。允许我使用存储库和 ElasticSearchTemplate。
    【解决方案2】:

    可能有多种方法可以做到这一点。这是一个利用@Bean 名称和@Resource 名称的方法。

    @Configuration
    public class MyElasticConfig{
    
        @Bean //this is your private template
        public ElasticsearchTemplate template(){
            //construct your template
            return template;
        }
    
        @Bean //this is your public template
        public ElasticsearchTemplate publicTemplate(){
            //construct your template
            return template;
        }
    }
    

    那么你可以像这样得到它们......

    @Resource
    private ElasticsearchTemplate template;
    
    @Resource
    private ElasticsearchTemplate publicTemplate;
    

    @Resource(name="template")
    private ElasticsearchTemplate anyName;
    
    @Resource(name="publicTemplate")
    private ElasticsearchTemplate anyOtherName;
    

    您也可以直接命名您的@Bean,而不是依赖@Bean 的方法名称。

        @Bean (name="template")
        public ElasticsearchTemplate myPrivateTemplate(){
            //construct your template
            return template;
        }
    
        @Bean (name="publicTemplate")
        public ElasticsearchTemplate myPubTemplate(){
            //construct your template
            return template;
        }
    

    查看有关该主题的这些精彩资源。

    SPRING INJECTION WITH @RESOURCE, @AUTOWIRED AND @INJECT
    Bean Annotation Type
    Autowired vs Resource

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-03
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 2011-09-02
      • 1970-01-01
      相关资源
      最近更新 更多