简体   繁体   English

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

[英]C# MongoDB Driver Ignores timeout options

We are using the C# driver (1.9.1) for Mongo DB. 我们正在使用Mongo DB的C#驱动程序(1.9.1)。 We have some fallback logic which needs to run if the DB is not accessible, however the default timeout is too long. 如果DB不可访问,我们有一些需要运行的回退逻辑,但是默认超时太长。 We tried to change it but the values we put are getting ignored. 我们试图改变它,但我们放置的值被忽略了。 For the tests we were using the IP of a non-responding machine. 对于测试,我们使用的是无响应机器的IP。

We tried setting the timeout in the connection string: 我们尝试在连接字符串中设置超时:

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

Or via the code: 或者通过代码:

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)
});

Both time the requests timeout after an average of about 20 seconds. 两次请求在平均约20秒后超时。

What could be wrong in the way we are setting the timeout options. 我们设置超时选项的方式可能有什么问题。

There is a JIRA ticket CSHARP-1018 to track this issue. 有一个JIRA票据CSHARP-1018来跟踪这个问题。 Basically the driver ignores timeout option when machine is not accessible. 基本上,当机器无法访问时,驱动程序会忽略超时选项。 Timeout option it is ignored if the machine is turned off or not accessible. 如果机器已关闭或无法访问,则会忽略超时选项。

Connection logic has been fixed in 2.0. 连接逻辑已在2.0中修复。 It currently will try for 30 seconds, but that is configurable to something smaller if you need faster connection times 它目前将尝试30秒,但如果您需要更快的连接时间,则可配置为更小的值

Please refer to the JIRA ticket to follow progress on this issue. 请参阅JIRA机票以了解此问题的进展情况。

See the workaround posted to CSHARP-1231 for a way that the ServerSelectionTimeout can be set in the current 2.0.0 version of the driver if you prefer that approach to using shorter timeouts on specific operations. 有关在特定操作中使用较短超时的方法,可以在当前2.0.0版本的驱动程序中设置ServerSelectionTimeout的方法,请参阅发布到CSHARP-1231的变通方法。


If you are using the new 2.0 async API you can use a cancellation token to apply your own timeout to the overall operation. 如果您使用的是新的2.0异步API,则可以使用取消令牌将自己的超时应用于整个操作。

So I would recommend the cancellation token approach in the previous comment. 所以我会在之前的评论中推荐取消令牌方法。 Using short server selection timeouts can result in spurious exceptions during replica set elections if the server selection timeout is shorter than the time it takes an election to complete. 如果服务器选择超时短于选举完成所需的时间,则使用短服务器选择超时可能会导致副本集选举期间出现虚假异常。

You can write something like this: 你可以写这样的东西:

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);
}

In this example, even though the ServerSelectionTimeout is still the default value of 30 seconds, this particular operation will be cancelled after only 500 milliseconds (approximately, cancellation can sometimes take slightly longer). 在此示例中,即使ServerSelectionTimeout仍然是默认值30秒,此特定操作将在仅500毫秒后被取消(大约,取消有时可能需要稍长一些)。

The JIRA ticket referred to by @Robert Stam mentions a workaround. @Robert Stam提到的JIRA门票提到了一种解决方法。

I tried it, and it works 100%. 我试过了,它100%有效。

If you are using the new 2.0 async API you can use a cancellation token to apply your own timeout to the overall operation. 如果您使用的是新的2.0异步API,则可以使用取消令牌将自己的超时应用于整个操作。 You can write something like this: 你可以写这样的东西:

 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); } 

In this example, even though the ServerSelectionTimeout is still the default value of 30 seconds, this particular operation will be cancelled after only 500 milliseconds (approximately, cancellation can sometimes take slightly longer). 在此示例中,即使ServerSelectionTimeout仍然是默认值30秒,此特定操作将在仅500毫秒后被取消(大约,取消有时可能需要稍长一些)。

Anyone in 2018 ? 2018年的任何人? please try below code 请尝试下面的代码

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM