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

时间:2014-07-18 12:30:50

标签: c# mongodb timeout

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

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

 <add key="Mongo" value="mongodb://xxx.xxx.xxx.xxx:27017/?socketTimeoutMS=2000&amp;connectTimeoutMS=2000&amp;waitqueuetimeoutms=2000"/>

或通过代码:

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秒后超时。

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

3 个答案:

答案 0 :(得分:5)

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

  

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

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

请参阅发布到CSHARP-1231的变通方法,了解如果您希望在特定操作上使用更短的超时时间,可以在当前2.0.0版本的驱动程序中设置ServerSelectionTimeout。


如果您使用的是新的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毫秒后被取消(大约有时,取消有时需要稍长时间)。

答案 1 :(得分:2)

@Robert Stam引用的JIRA ticket提到了一种解决方法。

我试过了,它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仍然是。{1}}   默认值为30秒,此特定操作将为   仅在500毫秒后取消(大约,取消即可   有时需要稍微长一点。)

答案 2 :(得分:1)

2018年有人吗?请尝试以下代码

ServerSelectionTimeout = new TimeSpan(0, 0, 0, 2)