【问题标题】:Spring Solr - Using multiple clients to different servicesSpring Solr - 将多个客户端用于不同的服务
【发布时间】:2017-06-07 22:18:22
【问题描述】:

我正在使用一个聚合来自多个来源的数据的应用程序。在这种情况下,我需要使用不相关的数据连接到两个不同的 Solr 服务。为此,我建立了两个不同的数据存储库。我将 bean 定义如下:

@Configuration
@EnableSolrRepositories(basePackages={"foo.utilities.solr.repos.gcr"}, multicoreSupport=true)
public class GcrSolrContext {

    @Bean
    public SolrClient solrClient() {
        return new HttpSolrClient("http://foo:8086/solr/gcr");
    }

    @Bean
    public SolrTemplate solrTemplate(SolrClient client) throws Exception {
        return new SolrTemplate(client);
    }
}

我的问题是我无法弄清楚如何拥有两个完全独立的 Solr 客户端,每个客户端都指向不同的 url。由于需要 solrClient() 和 solrTemplate() bean,并且尝试使用不同的 URL 创建新的 Context 只会让 solrClient 和 solrTemplate bean 被首先创建的 bean 覆盖。如果它们是唯一定义的 Solr 客户端,则每个客户端都可以正常工作。

简而言之,我如何创建两个(或更多)不同的 Spring Solr 客户端,每个客户端都连接到不同的 URL?

附加信息是对 cme​​ts 的响应...

我试图简单地重新创建具有不同配置的 SolrContext 类。请考虑以下几点:

@Configuration
@EnableSolrRepositories(basePackages={"foo.utilities.solr.repos.different"}, multicoreSupport=true)
public class DifferentSolrContext {

    @Bean
    public SolrClient solrClient() {
        return new HttpSolrClient("http://SomethingDifferent:8086/solr/something");
    }

    @Bean
    public SolrTemplate solrTemplate(SolrClient client) throws Exception {
        return new SolrTemplate(client);
    }
}

这里发生的是@Bean 的 solrClient 和 solrTemplate 在启动期间创建 bean 时被覆盖。

INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'solrClient' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=yyySolrContext; factoryMethodName=solrClient; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.GcrSolrContext] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=xxxSolrContext; factoryMethodName=solrClient; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.XxxSolrContext]
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'solrTemplate' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=yyySolrContext; factoryMethodName=solrTemplate; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.GcrSolrContext] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=haystackSolrContext; factoryMethodName=solrTemplate; initMethodName=null; destroyMethodName=(inferred); defined in foo.utilities.solr.XxxSolrContext]

测试表明 URL 确实只是第一个实例化的 bean。我还尝试将第二个上下文 bean 重命名为其他内容,但是 Solr 功能无法定位/识别 bean。

这是尝试定义多个 SolrClient 时引发的错误。

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.apache.solr.client.solrj.SolrClient' available: expected single matching bean but found 2: solrClient2,solrClient

简而言之,Spring Solr 数据库似乎只能使用一个 URL。 (注意:使用版本 2.1.4)是否有人在 Spring Solr 数据下拥有多个 URL(不仅仅是核心)?

【问题讨论】:

    标签: spring solr spring-data-solr


    【解决方案1】:

    由于在同一个 Spring 上下文中有多个相同类型的 bean,因此在使用自动装配时需要消除歧义。以下应该有效:

    第一个 Solr 服务器的配置

    @Configuration
    public class PrimarySolrContext {
      @Bean
      public SolrClient primarySolrClient() {
        return new HttpSolrClient(...);
      }
    
      @Bean("primary")
      public SolrTemplate solrTemplate() {
        return new SolrTemplate(primarySolrClient());
      }
    }
    

    第二个 Solr 服务器的配置

    @Configuration
    public class SecondarySolrContext {
      @Bean
      public SolrClient secondarySolrClient() {
        return new HttpSolrClient(...);
      }
    
      @Bean("secondary")
      public SolrTemplate solrTemplate() {
        return new SolrTemplate(secondarySolrClient());
      }
    }
    

    使用SolrTemplates

    @Service
    public class SearchService {
      @Autowired
      @Qualifier("primary")
      private SolrTemplate primarySolrTemplate;
    
      @Autowired
      @Qualifier("secondary")
      private SolrTemplate secondarySolrTemplate;
    }
    

    之所以有效,是因为:

    1. 第一个 SolrTemplate 直接通过明确的方法调用 (primarySolrClient()) 引用其 SolrClient
    2. 第二个SolrTemplate 直接通过明确的方法调用(secondarySolrClient()) 引用它的SolrClient
    3. 第一个 SolrTemplate 被明确命名为 (@Bean("primary"))。
    4. 第二个SolrTemplate 也被明确命名为 (@Bean("secondary"))。
    5. SolrTemplates 通过 @Qualifier 使用其唯一名称明确注入。

    更多SolrTemplates 可以用这种方式初始化和注入。

    on Github 提供了一个示例项目来证明这一点。

    【讨论】:

    • 它不起作用,错误是 - 一个组件需要一个名为 'solrClient' 的 bean,但无法找到。
    【解决方案2】:

    为spring创建另一个bean来使用solr,这很简单:

    @Configuration
    @EnableSolrRepositories(basePackages={"foo.utilities.solr.repos.xxx"}, multicoreSupport=true)
    public class XXXSolrContext {
    
        @Bean
        public SolrClient getClient() {
            return new HttpSolrClient("http://foo:8086/solr/xxx");
        }
    
        @Bean
        public SolrTemplate getTemplate(SolrClient client) throws Exception {
            return new SolrTemplate(client);
        }
    }
    

    【讨论】:

    • 我已经做到了。它不起作用,因为 bean 被第一个实例覆盖。我需要的是指向不同的服务器,而不是核心。这是来自启动日志“用不同的定义覆盖 bean 'solrClient' 的 bean 定义:替换 ...” solrTemplate bean 有类似的消息。
    • 它被 Spring 覆盖了吗?
    • 是的。查看添加到问题中的其他 cmets。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-02
    • 1970-01-01
    • 2013-03-25
    • 2015-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多