如何使用Couchbase Java SDK 3来使用不同的端口

huangapple go评论57阅读模式
英文:

How to use different ports using Couchbase Java SDK 3

问题

Context:
我正在使用 Docker 编写一些集成测试(使用 testcontainers)。并且我想使用 toxiproxy 连接到 couchbase。

The problem:
我无法使用与默认端口不同的端口连接到 couchbase。文档上说只需使用 SeedNode,但不起作用。

Client:

<dependency>
    <groupId>com.couchbase.client</groupId>
    <artifactId>java-client</artifactId>
    <version>3.0.5</version>
</dependency>

Couchbase setup:

echo "Initializing new cluster"
docker-compose exec couchbase \
  couchbase-cli cluster-init -c 127.0.0.1 --cluster-username Administrator --cluster-password password \
  --services data,index,query --cluster-ramsize 4096

echo "Creating new bucket"
docker-compose exec couchbase \
  couchbase-cli bucket-create -c couchbase:8091 --username Administrator \
  --password password --bucket default --bucket-type couchbase \
  --bucket-ramsize 1024

It works:

services:
  couchbase:
    image: couchbase:latest
    volumes:
      - .couchbase:/opt/couchbase/var
    ports:
      - "8091:8091"
      - "11210:11210"
SeedNode seedNode = SeedNode.create("127.0.0.1", Optional.of(11210), Optional.of(8091));
ClusterOptions clusterOptions = ClusterOptions.clusterOptions("Administrator", "password");
Cluster cluster = Cluster.connect(Collections.singleton(seedNode), clusterOptions);

Bucket bucket = cluster.bucket("default");
Collection collection = bucket.defaultCollection();

collection.insert("key", "Hello, Couchbase!");

It doesn't work:

services:
  couchbase:
    image: couchbase:latest
    volumes:
      - .couchbase:/opt/couchbase/var
    ports:
      - "28091:8091"
      - "21210:11210"
SeedNode seedNode = SeedNode.create("127.0.0.1", Optional.of(21210), Optional.of(28091));

Error:
我看到很多警告,如下所示:

[cb-events] WARN  com.couchbase.endpoint  - [com.couchbase.endpoint][EndpointConnectionFailedEvent][1282us] Connect attempt 7 failed because of AnnotatedConnectException: finishConnect(..) failed: Connection refused: /127.0.0.1:11210 {"bucket":"default","circuitBreaker":"DISABLED","coreId":"0xdf4c6e800000001","remote":"127.0.0.1:11210","type":"KV"}
com.couchbase.client.core.deps.io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: /127.0.0.1:11210

并且在插入行上失败:

com.couchbase.client.core.error.AmbiguousTimeoutException: InsertRequest
 {"cancelled":true,"completed":true,"coreId":"0xdf4c6e800000001","idempotent":false,"reason":"TIMEOUT","requestId":3,"requestType":"InsertRequest","retried":14,"retryReasons":["ENDPOINT_NOT_AVAILABLE","BUCKET_OPEN_IN_PROGRESS"],"service":{"bucket":"default","collection":"_default","documentId":"key","opaque":"0x2","scope":"_default","syncDurability":{"present":false},"type":"kv"},"timeoutMs":2500,"timings":{"encodingMicros":5015,"totalMicros":2509788}}
    ...

使用 CouchbaseContainer 取代我自己的 docker-compose 后,它可以使用容器的随机端口正常工作,但对我来说不够,因为我想设置 toxiproxy 端口。这是一个 bug 还是我做错了什么?

英文:

Context:
I'm writing some integration tests using docker (using testcontainers).
And I want to connect to couchbase using toxiproxy.

The problem:
I can't connect to couchbase using different ports than the default ones.
The docs says to just use SeedNode, but it does not work.

Client:

&lt;dependency&gt;
    &lt;groupId&gt;com.couchbase.client&lt;/groupId&gt;
    &lt;artifactId&gt;java-client&lt;/artifactId&gt;
    &lt;version&gt;3.0.5&lt;/version&gt;
&lt;/dependency&gt;

Couchbase setup:

echo &quot;Initializing new cluster&quot;
docker-compose exec couchbase \
  couchbase-cli cluster-init -c 127.0.0.1 --cluster-username Administrator --cluster-password password \
  --services data,index,query --cluster-ramsize 4096

echo &quot;Creating new bucket&quot;
docker-compose exec couchbase \
  couchbase-cli bucket-create -c couchbase:8091 --username Administrator \
  --password password --bucket default --bucket-type couchbase \
  --bucket-ramsize 1024

It works:

services:
  couchbase:
    image: couchbase:latest
    volumes:
      - .couchbase:/opt/couchbase/var
    ports:
      - &quot;8091:8091&quot;
      - &quot;11210:11210&quot;
SeedNode seedNode = SeedNode.create(&quot;127.0.0.1&quot;, Optional.of(11210), Optional.of(8091));
ClusterOptions clusterOptions = ClusterOptions.clusterOptions(&quot;Administrator&quot;, &quot;password&quot;);
Cluster cluster = Cluster.connect(Collections.singleton(seedNode), clusterOptions);

Bucket bucket = cluster.bucket(&quot;default&quot;);
Collection collection = bucket.defaultCollection();

collection.insert(&quot;key&quot;, &quot;Hello, Couchbase!&quot;);

It doesn't work:

services:
  couchbase:
    image: couchbase:latest
    volumes:
      - .couchbase:/opt/couchbase/var
    ports:
      - &quot;28091:8091&quot;
      - &quot;21210:11210&quot;
SeedNode seedNode = SeedNode.create(&quot;127.0.0.1&quot;, Optional.of(21210), Optional.of(28091));

Error:
I see many warnings like:

[cb-events] WARN  com.couchbase.endpoint  - [com.couchbase.endpoint][EndpointConnectionFailedEvent][1282us] Connect attempt 7 failed because of AnnotatedConnectException: finishConnect(..) failed: Connection refused: /127.0.0.1:11210 {&quot;bucket&quot;:&quot;default&quot;,&quot;circuitBreaker&quot;:&quot;DISABLED&quot;,&quot;coreId&quot;:&quot;0xdf4c6e800000001&quot;,&quot;remote&quot;:&quot;127.0.0.1:11210&quot;,&quot;type&quot;:&quot;KV&quot;}
com.couchbase.client.core.deps.io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: /127.0.0.1:11210

And it fails on the insert line:

com.couchbase.client.core.error.AmbiguousTimeoutException: InsertRequest
{&quot;cancelled&quot;:true,&quot;completed&quot;:true,&quot;coreId&quot;:&quot;0xdf4c6e800000001&quot;,&quot;idempotent&quot;:false,&quot;reason&quot;:&quot;TIMEOUT&quot;,&quot;requestId&quot;:3,&quot;requestType&quot;:&quot;InsertRequest&quot;,&quot;retried&quot;:14,&quot;retryReasons&quot;:[&quot;ENDPOINT_NOT_AVAILABLE&quot;,&quot;BUCKET_OPEN_IN_PROGRESS&quot;],&quot;service&quot;:{&quot;bucket&quot;:&quot;default&quot;,&quot;collection&quot;:&quot;_default&quot;,&quot;documentId&quot;:&quot;key&quot;,&quot;opaque&quot;:&quot;0x2&quot;,&quot;scope&quot;:&quot;_default&quot;,&quot;syncDurability&quot;:{&quot;present&quot;:false},&quot;type&quot;:&quot;kv&quot;},&quot;timeoutMs&quot;:2500,&quot;timings&quot;:{&quot;encodingMicros&quot;:5015,&quot;totalMicros&quot;:2509788}}
at com.couchbase.client.java.AsyncUtils.block(AsyncUtils.java:51)
at com.couchbase.client.java.Collection.insert(Collection.java:381)
at ToxyproxyCouchbaseIT.testCouchbase(ToxyproxyCouchbaseIT.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Suppressed: java.lang.Exception: The above exception was originally thrown by another thread at the following location.
at com.couchbase.client.core.msg.BaseRequest.cancel(BaseRequest.java:163)
at com.couchbase.client.core.Timer.lambda$register$2(Timer.java:157)
at com.couchbase.client.core.deps.io.netty.util.HashedWheelTimer$HashedWheelTimeout.expire(HashedWheelTimer.java:672)
at com.couchbase.client.core.deps.io.netty.util.HashedWheelTimer$HashedWheelBucket.expireTimeouts(HashedWheelTimer.java:747)
at com.couchbase.client.core.deps.io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:472)
at com.couchbase.client.core.deps.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)

Somehow, using CouchbaseContainer instead of my own docker-compose it works with container's random ports, but it's not enough for me because I want to set toxiproxy ports instead.

Is it a bug or am I doing something wrong?

答案1

得分: 1

为了回答问题(但不幸的是无法解决 OP 的问题),在 SDK 3 中,您可以像这样指定自定义 KV 端口:

Cluster cluster = Cluster.connect("localhost:12345", username, password);

如果您不知道 KV 端口,您可以像这样指定管理端口:

Cluster cluster = Cluster.connect("localhost:45678=manager", username, password);

(作为替代方案,您可以创建 SeedNode 对象,但我个人认为那有点繁琐。)

为了使自定义端口起作用,您需要使用支持 alternate addresses 的 Couchbase Server 6.5 或更高版本,并使用 setting-alternate-address 命令配置 Couchbase 以使用 "external" 地址来广播非标准端口。

SDK 使用传递给 Cluster.connect 的地址来引导连接。一旦连接到服务器,它会丢弃您提供的地址,而是使用从服务器获取的地址。服务器需要配置为报告 "external" 地址,以便告诉客户端将来请求时使用哪些主机和端口。

英文:

To answer the question (but not solve OP's problem, unfortunately), with SDK 3 you can specify a custom KV port like this:

 Cluster cluster = Cluster.connect(&quot;localhost:12345&quot;, username, password);

If you don't know the KV port, you can specify a manager port like this:

 Cluster cluster = Cluster.connect(&quot;localhost:45678=manager&quot;, username, password);

(As an alternative you can create SeedNode objects, but personally I find that a bit cumbersome.)

In order for custom ports to work, you will need to use Couchbase Server 6.5 or later which supports alternate addreses, and use the setting-alternate-address command to configure Couchbase to advertise the non-standard ports using "external" addresses.

The SDK uses the addresses passed to Cluster.connect to bootstrap the connections. Once it connects to the server, it throws away the addresses you gave it and instead uses the addresses it gets from the server. The server needs to be configured to report the "external" addresses so it can tell the client which hosts and ports to use for future requests.

huangapple
  • 本文由 发表于 2020年7月31日 00:48:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63177762.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定