我有以下应用程序:
application deployment diagram
A - 应用程序 A 是托管在 IIS 7.5 中的 .net wcf 服务,使用在 .net 4.5 中编译的 c# mongodriver 2.2.4
B - 应用程序 B 是使用 mongodriver 1.11 在 .net 3.5 中编译的 Windows 服务应用程序
两种服务是相似的,服务 B 是为遗留系统维护的,而服务 A 正在演变。
这两个应用程序都托管在相同的服务器中。 (Windows 标准 2008 R2)
该应用程序已经完美运行了 1 年多,但自 2016 年 6 月 24 日以来,应用程序 A (WCF) 在打开与 Mongo Server 的新连接时开始出现奇怪的行为:
> System.TimeoutException: A timeout occured after 30000ms selecting a > server using CompositeServerSelector{ Selectors = > ReadPreferenceServerSelector{ ReadPreference = { Mode = Primary, > TagSets = [] } }, LatencyLimitingServerSelector{ AllowedLatencyRange = > 00:00:00.0150000 } }. Client view of cluster state is { ClusterId : > "1", ConnectionMode : "ReplicaSet", Type : "ReplicaSet", State : > "Disconnected", Servers : [{ ServerId: "{ ClusterId : 1, EndPoint : > "Unspecified/mongodb-log-act01:27017" }", EndPoint: > "Unspecified/mongodb-log-act01:27017", State: "Disconnected", Type: > "Unknown" }] }. at > MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChangedHelper.HandleCompletedTask(Task > completedTask) at > MongoDB.Driver.Core.Clusters.Cluster.<WaitForDescriptionChangedAsync>d__44.MoveNext() > --- End of stack trace from previous location where exception was thrown --- at > System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at > System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task > task) at > MongoDB.Driver.Core.Clusters.Cluster.<SelectServerAsync>d__37.MoveNext() > --- End of stack trace from previous location where exception was thrown --- at > System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at > System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task > task) at > System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() > at > MongoDB.Driver.Core.Bindings.ReadPreferenceBinding.<GetReadChannelSourceAsync>d__8.MoveNext() > --- End of stack trace from previous location where exception was thrown --- at > System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at > System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task > task) at > System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() > at > MongoDB.Driver.Core.Operations.FindOperation`1.<ExecuteAsync>d__107.MoveNext() > --- End of stack trace from previous location where exception was thrown --- at > System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at > System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task > task) at > MongoDB.Driver.OperationExecutor.<ExecuteReadOperationAsync>d__1`1.MoveNext() > --- End of stack trace from previous location where exception was thrown --- at > System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at > System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task > task) at > MongoDB.Driver.MongoCollectionImpl`1.<ExecuteReadOperationAsync>d__59`1.MoveNext() > --- End of stack trace from previous location where exception was thrown --- at > System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at > System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task > task) at > System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() > at > MongoDB.Driver.IAsyncCursorSourceExtensions.<ToListAsync>d__16`1.MoveNext() > --- End of stack trace from previous location where exception was thrown --- at > System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at > System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task > task) at > Liberty.LogService.Implementation.LogManagerService.<Inicializar>d__0.MoveNext()
最佳答案
这是一个与任务库相关的非常棘手的问题。简而言之,创建和调度的任务太多,因此 MongoDB 驱动程序正在等待的任务之一将无法完成。我花了很长时间才意识到这不是一个僵局,尽管看起来确实如此。
这是重现的步骤:
MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChangedHelper.HandleCompletedTask(Task completedTask)Cluster.cs 中添加调试行: protected void UpdateClusterDescription(ClusterDescription newClusterDescription)
{
ClusterDescription oldClusterDescription = null;
TaskCompletionSource<bool> oldDescriptionChangedTaskCompletionSource = null;
Console.WriteLine($"Before UpdateClusterDescription {_descriptionChangedTaskCompletionSource?.Task.Id}, {_descriptionChangedTaskCompletionSource?.Task?.GetHashCode().ToString("F8")}");
lock (_descriptionLock)
{
oldClusterDescription = _description;
_description = newClusterDescription;
oldDescriptionChangedTaskCompletionSource = _descriptionChangedTaskCompletionSource;
_descriptionChangedTaskCompletionSource = new TaskCompletionSource<bool>();
}
OnDescriptionChanged(oldClusterDescription, newClusterDescription);
Console.WriteLine($"Setting UpdateClusterDescription {oldDescriptionChangedTaskCompletionSource?.Task.Id}, {oldDescriptionChangedTaskCompletionSource?.Task?.GetHashCode().ToString("F8")}");
oldDescriptionChangedTaskCompletionSource.TrySetResult(true);
Console.WriteLine($"Set UpdateClusterDescription {oldDescriptionChangedTaskCompletionSource?.Task.Id}, {oldDescriptionChangedTaskCompletionSource?.Task?.GetHashCode().ToString("F8")}");
}
private void WaitForDescriptionChanged(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
{
using (var helper = new WaitForDescriptionChangedHelper(this, selector, description, descriptionChangedTask, timeout, cancellationToken))
{
Console.WriteLine($"Waiting {descriptionChangedTask?.Id}, {descriptionChangedTask?.GetHashCode().ToString("F8")}");
var index = Task.WaitAny(helper.Tasks);
helper.HandleCompletedTask(helper.Tasks[index]);
}
}
Dns.GetHostAddressesAsync .这个永远不会被执行。如果您稍微修改代码并将其转换为: var task = Dns.GetHostAddressesAsync(dnsInitial.Host).ConfigureAwait(false);
return (await task)
.Select(x => new IPEndPoint(x, dnsInitial.Port))
.OrderBy(x => x, new PreferredAddressFamilyComparer(preferred))
.ToArray();
Task.Factory.StartNew(DoOneThing, TaskCreationOptions.LongRunning);
var taskScheduler = new ThrottledTaskScheduler(
TaskScheduler.Default,
128,
TaskCreationOptions.LongRunning | TaskCreationOptions.HideScheduler,
logger
);
var taskFactory = new TaskFactory(taskScheduler);
for (var i = 0; i < 30000; i++)
{
tasks.Add(taskFactory.StartNew(DoOneThing))
}
Task.WaitAll(tasks.ToArray());
关于c# - System.TimeoutException : A timeout occured after 30000ms selecting a server using CompositeServerSelector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38859755/