【问题标题】:Zookeeper + Solr in TestContainersTestContainers 中的 Zookeeper + Solr
【发布时间】:2020-06-03 00:06:40
【问题描述】:

我正在使用 org.testcontainers 来执行与 Solr 的集成测试。

[在我的单元测试中使用 SolrJ]

当我使用嵌入式 ZooKeeper 实例以云模式启动 Solr 时,我能够从我的单元测试连接到 solr 实例,但无法从我的 SolrClient 连接到 ZooKeeper。
我认为这是因为嵌入式 ZooKeeper 绑定到 IP 127.0.0.1 并且无法访问。

如果我启动两个单独的容器 [使用共享网络] ZooKeeper 和 Solr,我可以将 Solr 连接到 ZooKeeper,并且我可以从我的单元测试中连接到 Zookeeper,但是当 Zookeeper 返回活动的 SOLR 节点时,它会返回无法从我的单元测试 [在我的 SolrJ 客户端中] 访问的内部服务器 IP。

我不知道该去哪里。
也许有一种网络模式可以进行地址转换?

想法?

【问题讨论】:

  • 你可以在启动Solr之前设置SOLR_HOST强制它使用特定ip进行节点间通信,或者如果你想让jetty监听特定ip,你可以在里面使用-Djetty.host=<ip> SOLR_OPTS。但是,如果内部 zookeeper 绑定到 localhost,那应该仍然是您运行测试时所在的同一台服务器吗?嵌入式 Zookeeper 不使用默认的 ZK 端口 (2181),而是使用 <solr port> + 1000 - 因此如果 Solr 使用默认端口 8983,嵌入式 ZK 将使用 9983。

标签: solr apache-zookeeper solrj testcontainers


【解决方案1】:

更新:

有一个官方的Testcontainers Module:https://www.testcontainers.org/modules/solr/


看来这个问题没那么容易解决。

一种方法是使用带有 testcontainer 的固定端口。在这种情况下,端口 9983 和 8983 将映射到主机上的相同端口。这使得使用 Solr 云客户端成为可能。但这仅在您可以确保测试将按顺序运行时才有效,这可能有点棘手,例如在具有特征分支的 Jenkins 上。

另一种解决方案是使用另一个客户端。由于 Solrj 提供了多个客户端,因此您可以选择要使用的客户端。如果您只想搜索或更新,您可以使用 LBHttp2SolrClient 在多个节点之间进行负载平衡。如果您想为集成测试使用特定客户端,则此示例可以工作:

// Create the solr container.
SolrContainer container = new SolrContainer();

// Start the container. This step might take some time...
container.start();

// Do whatever you want with the client ...
SolrClient client = new Http2SolrClient.Builder("http://localhost:" + container.getSolrPort() + "/solr").build();
SolrPingResponse response = client.ping("dummy");

// Stop the container.
container.stop();

这里是java中的solr客户端列表:https://lucene.apache.org/solr/guide/8_3/using-solrj.html#types-of-solrclients

【讨论】:

  • 感谢@Raynigon - 我开发了一种解决方法,我认为它与您的建议相似。我回去工作后会检查并发布。
【解决方案2】:

我遇到了完全相同的问题。我使用代理解决了它。在我的 docker_compose.yml 中,我添加了:

  squid:
    image: sameersbn/squid:3.5.27-2
    ports:
      - "3128:3128"
    volumes:
      - ./squid.conf:/etc/squid/squid.conf
      - ./cache:/var/spool/squid
    restart: always
    networks:
     - solr

并且在我添加的 SolrClient 的配置中:

[...]

HttpClient httpClient = HttpClientBuilder.create().setProxy(new HttpHost("localhost", 3128)).build()
CloudSolrClient c = new CloudSolrClient.Builder(getZookeeperList(), Optional.empty()).withHttpClient(httpClient).build();

[...]

protected List<String> getZookeeperList() {
  List<String> zookeeperList = new ArrayList<String>();

  for (Zookeepers z : Zookeepers.values()) {
            zookeeperList.add(testcontainer.getServiceHost(z.getServicename(), z.getPort()) + ":"
                    + testcontainer.getServicePort(z.getServicename(), z.getPort()));
  }

  return zookeeperList;
}

但我仍然对 Jeremy 在 comment 中提到的解决方法感兴趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    相关资源
    最近更新 更多