微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

测试容器 Couchbase 超时

如何解决测试容器 Couchbase 超时

我创建了一个最小、完整且可验证的示例来说明我的问题:https://github.com/Virkom/CouchbaseMCVE.

我已经使用 Testcontainers 和 CouchbaseContainer 创建了一个集成测试。 我的 gradle.build:

implementation "com.couchbase.client:java-client:3.1.3"
testImplementation "io.micronaut.test:micronaut-test-junit5"
testImplementation "org.testcontainers:junit-jupiter"
testImplementation "org.testcontainers:testcontainers"
testImplementation "org.testcontainers:couchbase"

Couchbase 客户端:

ClusterEnvironment env = ClusterEnvironment.builder()
    .transcoder(SerializableTranscoder.INSTANCE)
    .aggregatingMeterConfig(AggregatingMeterConfig.builder()
        .enabled(true)
        .emitInterval(Duration.ofSeconds(60)))
    .build();

ClusterOptions opts = ClusterOptions.clusterOptions(bucket,password).environment(env);
couchbaseCluster = Cluster.connect("localhost",opts);
couchbaseBucket = couchbaseCluster.bucket(bucket);

当存储桶为“testBucket”且密码为“testtest”时。

测试中的容器创建代码

BucketDeFinition bucketDeFinition = new BucketDeFinition("testBucket");

CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server")
    .withCredentials("testBucket","testtest")
    .withBucket(bucketDeFinition);

couchbaseContainer.start();

Containers 启动,我可以通过 webinterface 连接它,testBucket 存在并且一切正常,但是当我尝试更新值时出现异常。

方法代码

public void set(String key,Serializable o,int ttlSeconds) {
    UpsertOptions opts = UpsertOptions.upsertOptions()
        .durability(PersistTo.NONE,Replicateto.NONE)
        .expiry(Duration.ofSeconds(ttlSeconds));
    couchbaseBucket.defaultCollection().upsert(key,o,opts);
}

结果:

UpsertRequest,Reason: TIMEOUT
com.couchbase.client.core.error.AmbiguousTimeoutException: UpsertRequest,Reason: TIMEOUT {"cancelled":true,"completed":true,"coreId":"0x48ac5a3200000001","idempotent":false,"reason":"TIMEOUT","requestId":5,"requestType":"UpsertRequest","retried":14,"retryReasons":["BUCKET_OPEN_IN_PROGRESS"],"service":{"bucket":"testBucket","collection":"_default","documentId":"0","opaque":"0x3","scope":"_default","type":"kv"},"timeoutMs":2500,"timings":{"encodingMicros":1434,"totalMicros":8118167}}

此外,我在终端中有很多警告,例如:

12:54:15.896 [cb-events] WARN  com.couchbase.endpoint - [com.couchbase.endpoint][EndpointConnectionFailedEvent][948us] Connect attempt 9 Failed because of AnnotatedConnectException: finishConnect(..) Failed: connection refused: localhost/127.0.0.1:8091 {"circuitBreaker":"disABLED","remote":"localhost:8091","type":"MANAGER"}
com.couchbase.client.core.deps.io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) Failed: connection refused: localhost/127.0.0.1:8091
Caused by: java.net.ConnectException: finishConnect(..) Failed: connection refused

我花了很多时间寻找原因,尝试使用 couchbase 容器端口 couchbaseCluster = Cluster.connect(serverIp + ":" + serverPort,opts); 连接到集群,并尝试使用暴露的端口 .withExposedPorts(8091,8092,8093,8094,11207,11210,11211,18091,18092,18093) 创建容器,但它不起作用。有人可以帮我吗?

解决方法

集成测试设置的关键点是指示被测应用程序使用依赖项的随机端口,由测试容器启动。 在您的情况下是 Couchbase DB。您的应用程序正在尝试使用默认的 8091 端口(如 application-test.yml 中设置的)连接到数据库,但正如您在评论中提到的,docker 容器在随机端口上公开了 Couchbase。

例如,为了使用 Micronaut 和 JUnit5 执行此操作,您可以使用 TestPropertyProvider 接口。在 Micronaut documentation 中查看有关它的更多详细信息。

// @Testcontainers MUST be before @MicronautTest to make sure
// container is started before adjusting properties
@Testcontainers
@MicronautTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class CouchbaseServiceTest implements TestPropertyProvider {

    @Inject
    private CouchbaseService couchbaseService;

    @Container
    private static final CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server")
            .withCredentials("testBucket","testPassword")
            .withExposedPorts(8091,8092,8093,8094,11207,11210,11211,18091,18092,18093)
            .withBucket(new BucketDefinition("testBucket"));

    @Override
    public Map<String,String> getProperties() {
        return Map.of(
                "app.server_port",String.valueOf(couchbaseContainer.getBootstrapHttpDirectPort()),"app.kv_port",String.valueOf(couchbaseContainer.getBootstrapCarrierDirectPort())
        );
    }
    ...

但是接下来你还需要稍微修改集群连接代码(CouchbaseClient.java):

...
SeedNode seedNode = SeedNode.create(
    serverIp,Optional.of(Integer.valueOf(kvPort)),Optional.of(Integer.valueOf(serverPort)));
couchbaseCluster = Cluster.connect(Set.of(seedNode),opts);

您可能已经注意到,您需要为 kv_port 再公开一个属性。与您对 server_port 所做的相同。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。