使用Testcontainers搭配Couchbase .NET SDK时出现SocketNotAvailableException异常的问题求助
Testcontainers搭配Couchbase .NET SDK时出现SocketNotAvailableException异常的问题求助
我最近在尝试用Testcontainers启动Couchbase容器,同时结合Couchbase .NET SDK来创建Bucket,但运行基础的初始化代码时,遇到了一个信息不够详细的异常:
Couchbase.Core.Exceptions.KeyValue.SocketNotAvailableException:ChannelConnectionPool
at Couchbase.Core.ClusterContext.GetOrCreateBucketLockedAsync(String name) at Program.<Main>$(String[] args) in \ConsoleApp4\ConsoleApp4\Program.cs:line 24
重现问题的代码
项目文件(Csproj):
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="CouchbaseNetClient" Version="3.4.12" /> <PackageReference Include="Testcontainers" Version="3.5.0" /> <PackageReference Include="Testcontainers.Couchbase" Version="3.5.0" /> </ItemGroup> </Project>
主程序代码(Program.cs):
using Couchbase; using Testcontainers.Couchbase; const string TestBucketName = "Test"; CouchbaseContainer CouchbaseContainer = new CouchbaseBuilder() .Build(); try { await CouchbaseContainer.StartAsync(); var options = new ClusterOptions { UserName = CouchbaseBuilder.DefaultUsername, Password = CouchbaseBuilder.DefaultPassword, }; var connectionString = CouchbaseContainer.GetConnectionString(); var cluster = await Cluster.ConnectAsync(connectionString, options); var bucket = await cluster.BucketAsync(TestBucketName); var collection = await bucket.DefaultCollectionAsync(); } catch (Exception e) { await CouchbaseContainer.DisposeAsync(); Console.WriteLine(e); }
我的尝试
我试过通过Couchbase的Web UI手动创建Bucket,是可以成功的,说明容器本身是正常工作的。
补充排查信息(编辑1)
经过进一步排查,我发现问题的核心原因是:在我尝试创建Bucket之前,ChannelConnectionPool已经被释放了。以下是相关的调用栈:
at Couchbase.Core.IO.Connections.Channels.ChannelConnectionPool.Dispose() at Couchbase.Core.ClusterNode.Dispose() at Couchbase.Core.ClusterContext.BootstrapGlobalAsync() at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object s) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action innerContinuation, Task innerTask) at System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining) at System.Threading.Tasks.Task.RunContinuations(Object continuationObject) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task`1.TrySetResult(TResult result) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 task, TResult result) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetResult(TResult result) at Couchbase.Core.ClusterNode.GetClusterMap(Nullable`1 configVersion) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object s) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action innerContinuation, Task innerTask) at System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining) at System.Threading.Tasks.Task.RunContinuations(Object continuationObject) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task`1.TrySetResult(TResult result) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 task, TResult result) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetResult(TResult result) at Couchbase.Core.ClusterNode.ExecuteOp(Func`4 sender, IOperation op, Object state, CancellationTokenPair tokenPair) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread) at System.Threading.ThreadPool.<>c.<.cctor>b__87_0(Object state) at Couchbase.Core.IO.Operations.OperationBase`1.HandleOperationCompleted(SlicedMemoryOwner`1& data) at Couchbase.Core.IO.Operations.OperationBase`1.Couchbase.Core.IO.Operations.IOperation.HandleOperationCompleted(SlicedMemoryOwner`1& data) at Couchbase.Core.IO.AsyncStateBase.SendResponseInternal(Object response) at System.Threading.QueueUserWorkItemCallbackDefaultContext`1.Execute() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() at System.Threading.Thread.StartCallback()
最终排查结果(编辑2)
继续深挖后,我找到了问题的根源:在ClusterContext类的BootstrapGlobalAsync方法里有这么一段代码:
if (GlobalConfig.UseAlternateAddresses) { node.Dispose(); }
这段代码会在GlobalConfig.UseAlternateAddresses为true时释放节点。我手动把这个值硬编码为false之后,程序就可以正常运行了。
备注:内容来源于stack exchange,提问作者CouchbaseUser
相关产品推荐
相关产品推荐

