C#MongoDB驱动程序忽略超时选项

我们正在使用Mongo DB的C#驱动程序(1.9.1)。 如果DB不可访问,我们有一些需要运行的回退逻辑,但是默认超时太长。 我们试图改变它,但我们放置的值被忽略了。 对于测试,我们使用的是无响应机器的IP。

我们尝试在连接字符串中设置超时:

 

或者通过代码:

 var client = new MongoClient(new MongoClientSettings { Server = new MongoServerAddress("xxx.xxx.xxx.xxx"), SocketTimeout = new TimeSpan(0, 0, 0, 2), WaitQueueTimeout = new TimeSpan(0, 0, 0, 2), ConnectTimeout = new TimeSpan(0, 0, 0, 2) }); 

两次请求在平均约20秒后超时。

我们设置超时选项的方式可能有什么问题。

有一个JIRA票据CSHARP-1018来跟踪这个问题。 基本上,当无法访问机器时,驱动程序会忽略超时选项。 如果机器已关闭或无法访问,则会忽略超时选项。

连接逻辑已在2.0中修复。 它目前将尝试30秒,但如果您需要更快的连接时间,则可配置为更小的值

请参阅JIRA机票以了解此问题的进展情况。

有关在特定操作中使用较短超时的方法,可以在当前2.0.0版本的驱动程序中设置ServerSelectionTimeout的方法,请参阅发布到CSHARP-1231的变通方法。


如果您使用的是新的2.0异步API,则可以使用取消令牌将自己的超时应用于整个操作。

所以我会在之前的评论中推荐取消令牌方法。 如果服务器选择超时短于选举完成所需的时间,则使用短服务器选择超时可能会导致副本集选举期间出现虚假exception。

你可以写这样的东西:

 var startTime = DateTime.UtcNow; try { using (var timeoutCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(500))) { await collection.Find("{ _id : 1 }").ToListAsync(timeoutCancellationTokenSource.Token); } } catch (OperationCanceledException ex) { var endTime = DateTime.UtcNow; var elapsed = endTime - startTime; Console.WriteLine("Operation was cancelled after {0} seconds.", elapsed.TotalSeconds); } 

在此示例中,即使ServerSelectionTimeout仍然是默认值30秒,此特定操作将在仅500毫秒后被取消(大约,取消有时可能需要稍长一些)。

@Robert Stam提到的JIRA门票提到了一种解决方法。

我试过了,它100%有效。

如果您使用的是新的2.0异步API,则可以使用取消令牌将自己的超时应用于整个操作。 你可以写这样的东西:

 var startTime = DateTime.UtcNow; try { using (var timeoutCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(500))) { await collection.Find("{ _id : 1 }").ToListAsync(timeoutCancellationTokenSource.Token); } } catch (OperationCanceledException ex) { var endTime = DateTime.UtcNow; var elapsed = endTime - startTime; Console.WriteLine("Operation was cancelled after {0} seconds.", elapsed.TotalSeconds); } 

在此示例中,即使ServerSelectionTimeout仍然是默认值30秒,此特定操作将在仅500毫秒后被取消(大约,取消有时可能需要稍长一些)。