我们最近将我们的Web应用程序升级到MongoDB C#Driver 2.0并部署到生产环境。低于一定负载,应用程序运行正常。一旦生产服务器上的负载超过某个限制,应用程序的CPU立即降至0,大约30秒后,将多次记录此异常:
System.TimeoutException message: A timeout occured after 30000ms selecting a server using CompositeServerSelector{ Selectors = ReadPreferenceServerSelector{ ReadPreference = { Mode = Primary, TagSets = System.Collections.Generic.List`1[MongoDB.Driver.TagSet] } }, LatencyLimitingServerSelector{ AllowedLatencyRange = 00:00:00.0150000 } }. Client view of cluster state is { ClusterId : "1", Type : "Standalone", State : "Disconnected", Servers : [{ ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/10.4.0.113:27017" }", EndPoint: "Unspecified/10.4.0.113:27017", State: "Disconnected", Type: "Unknown" }] }.
stack trace:
at MongoDB.Driver.Core.Clusters.Cluster.ThrowTimeoutException(IServerSelector selector, ClusterDescription description)
at MongoDB.Driver.Core.Clusters.Cluster.<WaitForDescriptionChangedAsync>d__18.MoveNext()
--- End of stack trace
我们正在使用单个MongoClient对象,它是这样启动的:
private static object _syncRoot = new object();
private static MongoClient _client;
private static IMongoDatabase _database;
private IMongoDatabase GetDatabase()
{
...
if (_client == null)
{
lock (_syncRoot)
{
if (_client == null)
{
_client = new MongoClient(
new MongoClientSettings
{
Server = new MongoServerAddress(host, port),
Credentials = new[] { credentials },
});
_database = _client.GetDatabase("proddb");
return _database;
}
}
}
return _database;
}
public IMongoCollection<T> GetCollection<T>(string name)
{
return GetDatabase().GetCollection<T>(name);
}
对数据库的典型调用如下所示:
public async Task<MongoItem> GetById(string id)
{
var collection = _connectionManager.GetCollection<MongoItem>("items");
var fdb = new FilterDefinitionBuilder<MongoItem>();
var f = fdb.Eq(mi => mi.Id, id);
return await collection.Find(f).FirstOrDefaultAsync();
}
我们如何找到原因并解决此问题?
答案 0 :(得分:5)
这post可能有所帮助:
我明白了。 This JIRA ticket有详细信息。
实际上,我们已经区分了连接到 独立服务器并直接连接到副本集成员, 后者相对不常见的地方。不幸的是,MongoLab的 单节点设置实际上是单节点副本集和此 使我们不相信它。你可以通过追加来解决这个问题
?connect=replicaSet
到你的连接字符串。它会迫使 驱动程序进入副本设置模式,一切都会正常工作。鉴于此,我们将重新考虑CSHARP-1160。谢谢你 很多报道,如果附加
?connect=replicaSet
,请告诉我 你的连接字符串不起作用。
答案 1 :(得分:2)
我使用驱动程序v2.2.4遇到了同样的问题。升级到v2.3.0后,问题似乎已经解决
答案 2 :(得分:1)
此问题与CSHARP-1435,CSHARP-1515和CSHARP-1538错误报告有关,而且最有可能在最近的C#MongoDB驱动程序中已修复此问题。
此问题可能与读取多个适合单个批次的文档数量有关。 source
所以可能的解决方案是:
如果要连接到mongod
个进程组(请参阅:replication),请将?connect=replicaSet
添加到您的连接字符串中。例如:
mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000
示例ConnectionStrings.config
文件:
<connectionStrings>
<add name="MongoDB" connectionString="mongodb://10.0.80.231:27017,10.0.108.31:27017/?replicaSet=groupname&connectTimeoutMS=600000&socketTimeoutMS=600000" />
<add name="RedisCache" connectionString="www-redis.foo.cache.amazonaws.com:6379" />
<add name="SqlConnection" connectionString="server=api.foo.eu-west-1.rds.amazonaws.com;database=foo;uid=sqlvpc;pwd=somepass;" providerName="System.Data.SqlClient" />
</connectionStrings>
相关:CSHARP-1160, How to include ampersand in connection string?
如果以上工作无效,请检查:C# MongoDB Driver Ignores timeout options。
根据上述错误报告尝试升级MongoDB.Driver
。
尝试增加连接和套接字超时。
将?connectTimeoutMS=60000&socketTimeoutMS=60000
附加到您的连接字符串。请参阅:mongoDB Connection String Options。
或者更改代码中的设置(例如connecttimeout
,maxpoolsize
,waitQueueSize
和waitQueueTimeout
)。请参阅example here。
答案 3 :(得分:0)
当我在MongoLab中使用免费(版本2.6)沙箱时,我遇到了同样的问题,当我开始使用付费群集时,超时问题就消失了。
我打算说我认为问题是只支持MongoDB版本3.0+(因为我发现一些文档说的很多,我发誓我通过MongoLab完成了3.0升级过程)但是当我去的时候为了搜索文档,它现在说支持2.6并且我付费的MongoLab DB仍然说它的版本是2.6.9。
我想我一定很疯狂,但至少我的代码现在正在运作!