0

我正在尝试使用测试容器对在 Docker 容器中启动的 HBase 运行集成测试。我遇到的问题对于客户端与 HBase 的交互方式可能有点独特。

当 HBase Master 在容器中启动时,它会将其 hostname:port 存储在 Zookeeper 中,以便客户端可以找到它。在这种情况下,它存储“localhost:16000”。

在我在容器外运行的测试用例中,客户端从 Zookeeper 检索“localhost:16000”并且无法连接。连接失败,因为该端口已被 TestContainers 重新映射到其他一些随机端口,而不是 16000。

任何想法如何克服这个问题?

(1) 一个想法是找到一种方法告诉 HBase 客户端使用重新映射的端口,忽略它从 Zookeeper 检索到的值,但我还没有找到一种方法来做到这一点。

(2) 如果我可以让 HBase Master 在 Zookeeper 中编写外部可访问的 host:port 也可以解决问题。但我不相信容器本身对测试容器如何进行端口重新映射有任何了解。

(3) 也许测试容器为这种情况提供了不同的解决方案?

4

2 回答 2

1

你可以看看KafkaContainer的实现,我们首先启动一个 Socat(快速 tcp 代理)容器来获取一个半随机端口,然后使用它来配置目标容器。

算法是:

  1. doStart,首先启动 Socat,以原始容器的网络别名和端口为目标,例如 12345
  2. 获取映射端口(类似于 32109 指向 12345)
  3. 使原始容器(例如使用环境变量)在原始端口之外使用映射端口,或者,如果只能配置一个端口,请参阅CouchbaseContainer以获得更高级的选项
  4. 将 Socat 的主机和端口返回给客户端
于 2019-05-03T19:48:31.690 回答
0

我们构建了一个新的 hbase 镜像以兼容测试容器。

使用此图像:

docker run --env HBASE_MASTER_PORT=16000 --env HBASE_REGION_PORT=16020 jcjabouille/hbase-standalone:2.4.9

然后创建这个容器(在 scala 中)

private[test] class GenericHbase2Container
    extends GenericContainer[GenericHbase2Container](
      DockerImageName.parse("jcjabouille/hbase-standalone:2.4.9")
    ) {
  private val randomMasterPort: Int = FreePortFinder.findFreeLocalPort(18000)
  private val randomRegionPort: Int = FreePortFinder.findFreeLocalPort(20000)
  private val hostName: String = InetAddress.getLocalHost.getHostName

  val hbase2Configuration: Configuration = HBaseConfiguration.create
  addExposedPort(randomMasterPort)
  addExposedPort(randomRegionPort)
  addExposedPort(2181)
  withCreateContainerCmdModifier { cmd: CreateContainerCmd =>
    cmd.withHostName(hostName)
    ()
  }
  waitingFor(Wait.forLogMessage(".*0 row.*", 1))
  withStartupTimeout(Duration.ofMinutes(10))
  withEnv("HBASE_MASTER_PORT", randomMasterPort.toString)
  withEnv("HBASE_REGION_PORT", randomRegionPort.toString)
  setPortBindings(Seq(s"$randomMasterPort:$randomMasterPort", s"$randomRegionPort:$randomRegionPort").asJava)

  override protected def doStart(): Unit = {
    super.doStart()
    hbase2Configuration.set("hbase.client.pause", "200")
    hbase2Configuration.set("hbase.client.retries.number", "10")
    hbase2Configuration.set("hbase.rpc.timeout", "3000")
    hbase2Configuration.set("hbase.client.operation.timeout", "3000")
    hbase2Configuration.set("hbase.client.scanner.timeout.period", "10000")
    hbase2Configuration.set("zookeeper.session.timeout", "10000")
    hbase2Configuration.set("hbase.zookeeper.quorum", "localhost")
    hbase2Configuration.set("hbase.zookeeper.property.clientPort", getMappedPort(2181).toString)
  }
}

更多细节在这里:https ://hub.docker.com/r/jcjabouille/hbase-standalone

于 2022-02-25T14:05:19.310 回答