ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

使用 Testcontainers 在 JUnit 测试中启动 Redpanda:完整配置、安全认证与多监听器实战指南

使用 Testcontainers 在 JUnit 测试中启动 Redpanda:完整配置、安全认证与多监听器实战指南 使用 Testcontainers 在 JUnit 测试中启动 Redpanda完整配置、安全认证与多监听器实战指南【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-javaTestcontainers 的testcontainers-redpanda模块可以在测试中自动实例化并管理 Redpanda 容器让开发者无需在本地搭建 Kafka 兼容环境即可完成消息队列、Schema Registry 与安全认证相关功能的集成测试。读完本文你将掌握 Redpanda 容器的创建与启动、Bootstrap Servers 与 Schema Registry 地址的获取、SASL/Authorization/Superuser 安全配置、AdminClient 的创建以及如何通过注册额外监听器让同网络容器或外部代理进程如 Toxiproxy连接 Redpanda。模块概述官方镜像与默认端口Testcontainers 使用 Redpanda 官方 Docker 镜像docker.redpanda.com/redpandadata/redpanda或redpandadata/redpanda来实例化 Redpanda 容器模块依赖镜像中提供的内置功能完成启动与配置注入。从 RedpandaContainer.java 的源码可见容器默认暴露以下四个端口端口用途9092BrokerKafka 兼容协议入口9644Redpanda Admin API8081Schema Registry8082REST ProxyPandaproxy镜像版本方面模块要求 Redpanda 版本必须不低于 v22.2.1。源码中通过ComparableVersion对镜像版本进行校验若传入更早版本会抛出IllegalArgumentException(Redpanda version must be v22.2.1)测试 RedpandaContainerTest.java 与 CompatibleImageTest.java 均验证了这一约束。容器启动时模块会以root:root用户、以--modedev-container --smp1 --memory1G参数运行redpanda start并等待日志中出现Successfully started Redpanda!才判定就绪见RedpandaContainer构造函数。同时它会将 classpath 资源testcontainers/entrypoint-tc.sh等待注入配置完成后才转发给官方入口脚本以及由 FreeMarker 模板bootstrap.yaml.ftl、redpanda.yaml.ftl渲染生成的配置文件分别复制到容器/etc/redpanda/下。最小示例创建容器并连接 Kafka 客户端创建RedpandaContainer并启动它即可在测试中使用代码示例如下取自 RedpandaContainerTest.java// constructorWithVersion { RedpandaContainer container new RedpandaContainer(docker.redpanda.com/redpandadata/redpanda:v23.1.2) // }容器支持传入字符串形式的完整镜像名也支持DockerImageName对象。启动后运行在本机或同一测试进程的任意客户端可通过如下方式获得 Broker 连接地址// getBootstrapServers { container.getBootstrapServers() // }getBootstrapServers()返回形如PLAINTEXT://host:mappedPort的地址其中 host 与端口由容器实际映射决定确保本机进程可以直接访问。模块同时提供其他地址获取方法getSchemaRegistryAddress()返回http://host:mappedPort8081 端口用于 Schema Registry 客户端。getAdminAddress()返回http://host:mappedPort9644 端口用于调用 Redpanda Admin API。getRestProxyAddress()返回http://host:mappedPort8082 端口用于 REST Proxy 的 HTTP 访问。验证完整消息链路抽象测试基类 AbstractRedpanda.java 展示了一条完整的“建 Topic → 生产 → 消费”链路使用 KafkaAdminClient创建NewTopic用KafkaProducer发送(testcontainers, rulezzz)消息再通过KafkaConsumerauto.offset.resetearliest在 10 秒内轮询并断言消息完整到达。这说明 Redpanda 与 Kafka 客户端协议完全兼容现有 Kafka 生态工具生产者、消费者、AdminClient无需修改即可复用。使用 Schema RegistryRedpanda 提供了 Schema Registry 实现地址同样由容器映射动态生成// getSchemaRegistryAddress { container.getSchemaRegistryAddress() // }测试 RedpandaContainerTest.java 使用 RestAssured 通过该地址调用/subjects与/subjects/{subject}/versions接口注册并查询 schema验证了 Schema Registry 的完整读写能力。启用安全特性授权、SASL 与超级用户模块支持在测试中一键开启 Redpanda 的安全能力通过链式方法组合使用// security { RedpandaContainer redpanda new RedpandaContainer(docker.redpanda.com/redpandadata/redpanda:v23.1.7) .enableAuthorization() .enableSasl() .withSuperuser(superuser-1) // }三个核心方法见 RedpandaContainer.java说明如下方法作用底层效果enableAuthorization()开启 Kafka API 授权在渲染bootstrap.yaml.ftl时写入kafka_enable_authorization: true并影响内部监听器的认证方式enableSasl()开启 SASL 认证将authenticationMethod置为sasl注入到 Kafka API 与 Schema Registry 的配置中withSuperuser(String username)注册超级用户将用户名写入bootstrap.yaml.ftl的superusers列表该用户可绕过授权检查此外模块还提供enableSchemaRegistryHttpBasicAuth()为 Schema Registry 开启 HTTP Basic 认证对应测试schemaRegistryWithHttpBasic未认证访问返回 401携带超级用户 Basic 凭据后返回 200。创建用户与 AdminClient开启 SASL 后需要通过 Redpanda Admin API 创建用户再构造携带凭据的 KafkaAdminClientprivate void createSuperUser(RedpandaContainer redpanda) { String adminUrl String.format(%s/v1/security/users, redpanda.getAdminAddress()); RestAssured .given() .contentType(application/json) .body({\username\: \superuser-1\, \password\: \test\, \algorithm\: \SCRAM-SHA-256\}) .post(adminUrl) .then() .statusCode(200); } // createAdminClient { AdminClient adminClient AdminClient.create( ImmutableMap.of( AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer, AdminClientConfig.SECURITY_PROTOCOL_CONFIG, SASL_PLAINTEXT, SaslConfigs.SASL_MECHANISM, SCRAM-SHA-256, SaslConfigs.SASL_JAAS_CONFIG, org.apache.kafka.common.security.scram.ScramLoginModule required username\superuser-1\ password\test\; ) ); // }注意bootstrapServer由redpanda.getHost() : redpanda.getMappedPort(9092)拼出。测试 RedpandaContainerTest.java 还验证了三种安全场景超级用户建 Topic 成功、非授权用户建 Topic 抛出TopicAuthorizationException、未认证访问抛出SaslAuthenticationException可用于编写安全回归测试时对照预期行为。注册额外监听器连接同网络容器默认情况下Redpanda 容器对外暴露的端口是9092其监听器地址advertised listener指向宿主机映射端口。但存在两类场景需要额外监听器消费者/生产者是同一 Docker 网络中的另一个容器此时外部映射端口在容器网络内不可用需要以容器网络别名访问连接端口与默认暴露端口不同的进程例如通过 Toxiproxy 模拟网络故障时客户端实际连接的是代理端口。模块通过withListener系列方法支持注册额外监听器。首先看“同网络容器”场景注册监听器// registerListener { RedpandaContainer kafka new RedpandaContainer(docker.redpanda.com/redpandadata/redpanda:v23.1.7) .withListener(kafka:19092) .withNetwork(network); // }再创建同一网络内的 kcat 容器// createKCatContainer { GenericContainer? kcat new GenericContainer(confluentinc/cp-kcat:7.9.0) .withCreateContainerCmdModifier(cmd - { cmd.withEntrypoint(sh); }) .withCopyToContainer(Transferable.of(Message produced by kcat), /data/msgs.txt) .withNetwork(network) .withCommand(-c, tail -f /dev/null) // }客户端使用新注册的监听器地址kafka:19092完成生产与消费// produceConsumeMessage { kcat.execInContainer(kcat, -b, kafka:19092, -t, msgs, -P, -l, /data/msgs.txt); String stdout kcat .execInContainer(kcat, -b, kafka:19092, -C, -t, msgs, -c, 1) .getStdout(); // }实现原理在 RedpandaContainer.java 的configure()中注册监听器的主机名会被加入网络别名network alias同时渲染redpanda.yaml.ftl时会把这些监听器追加到kafka_api与advertised_kafka_api列表。默认的监听器配置为默认监听器listeners0.0.0.0:9092external、0.0.0.0:9093internal供 Schema Registry / Pandaproxy 客户端在容器内使用默认广告监听器advertised listenerscontainerHost:mappedPort(9092)、127.0.0.1:9093。redpanda.yaml.ftl中还固定了 Admin API9644、Schema Registry8081、Pandaproxy8082的监听地址以及rpk默认连接的localhost:9093保证容器内部工具开箱即用。通过代理注册监听器外部进程访问场景当客户端运行在容器网络之外、且连接端口与默认映射端口不一致时可以注册一个“监听器 广告监听器”的组合。官方文档以SocatContainer作为代理为例。首先创建代理容器将宿主机某端口转发到容器网络内的kafka:19092// createProxy { SocatContainer socat new SocatContainer().withNetwork(network).withTarget(2000, kafka, 19092); // }随后注册监听器与广告监听器// registerListenerAndAdvertisedListener { RedpandaContainer kafka new RedpandaContainer(docker.redpanda.com/redpandadata/redpanda:v23.1.7) .withListener(kafka:19092, () - socat.getHost() : socat.getMappedPort(2000)) .withNetwork(network) // }此时 Kafka 客户端实际通过代理地址连接并完成完整消息链路验证// produceConsumeMessageFromProxy { String bootstrapServers String.format(%s:%s, socat.getHost(), socat.getMappedPort(2000)); testKafkaFunctionality(bootstrapServers); // }withListener(String listener, SupplierString advertisedListener)的语义是listener格式host:port注册为容器内实际监听端点其 host 同时成为网络别名advertisedListener则通过Supplier动态计算因为此时容器端口尚未映射完成客户端会根据广告监听器地址去连接从而实现“容器内监听 网络外代理访问”的完整链路。这对构造故障注入如 Toxiproxy或流量代理测试非常有用。兼容性说明源码中还有一个Deprecated的withListener(SupplierString)旧接口新代码应使用上述字符串/Supplier 组合形式withListener(String)与withListener(String, SupplierString)。添加模块依赖在项目中引入testcontainers-redpanda模块{{latest_version}}请替换为实际使用的版本号 GradletestImplementation org.testcontainers:testcontainers-redpanda:{{latest_version}} Mavendependency groupIdorg.testcontainers/groupId artifactIdtestcontainers-redpanda/artifactId version{{latest_version}}/version scopetest/scope /dependency与 Testcontainers 其他模块一致该模块仅需声明为测试依赖即可运行测试前请确保当前环境已具备 Docker 可用条件参见仓库根目录 README.md 与环境要求说明。实战要点小结版本下限Redpanda 镜像版本必须 ≥ v22.2.1否则模块直接拒绝启动并抛出IllegalArgumentException。端口规划9092Broker、9644Admin、8081Schema Registry、8082REST Proxy均已默认暴露并注入对应配置。安全组合enableAuthorization()enableSasl()withSuperuser(...)可一键构建带认证与授权的集群用户创建走 Admin API/v1/security/users客户端需携带 SCRAM-SHA-256 凭据。多监听器同网络容器用withListener(host:port)自动注册网络别名外部代理场景用withListener(host:port, supplier)提供动态广告监听器地址。配置注入机制模块通过 FreeMarker 模板redpanda.yaml.ftl、bootstrap.yaml.ftl在容器启动时生成配置文件并借助 entrypoint-tc.sh 等待配置就绪后再启动 Redpanda 主进程确保端口映射已知且配置一致。以上所有用法均可在仓库测试中找到可运行的完整示例建议结合 RedpandaContainerTest.java 与 CompatibleImageTest.java 进一步阅读验证。【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表