MongoWaitQueueFullException:获取服务器连接的等待队列已满 [英] MongoWaitQueueFullException: The wait queue for acquiring a connection to server is full

查看:0
本文介绍了MongoWaitQueueFullException:获取服务器连接的等待队列已满的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时,当插入一小串不同的文档(同步)时,我得到以下异常(请参阅下面的完整堆栈跟踪):

MongoDB.Driver.MongoWaitQueueFullException:的等待队列 正在获取到服务器xyz.monGolab.com:54128的连接已满。

我在所有存储库之间使用单个MongoDatabase实例(因此是单个连接)。实际上,我正在做这样的事情(每个集合中的文档不超过20个):

Context.Collection<ClientDocument>("clients").InsertMany(clients);
Context.Collection<VendorDocument>("vendors").InsertMany(vendors);
Context.Collection<SaleDocument>("sales").InsertOne(sale);

下面是单例上下文:

public class MongoContext
{
    public IMongoDatabase Database { get; }

    public MongoContext(IOptions<MongoSettings> settings)
    {
        var url = MongoUrl.Create(settings.Value.EndpointUri);

        var client = new MongoClient(new MongoClientSettings()
        {
            Server = url.Server
        });

        Database = client.GetDatabase(url.DatabaseName);
    }

    public IMongoCollection<TDocument> Collection<TDocument>(string collection)
        where TDocument : IDocument
    {
        return Database.GetCollection<TDocument>(collection);
    }
}

MongoDB的Jira(https://jira.mongodb.org/browse/CSHARP-1144)上也有类似的情况,但这些案例都在处理巨大的批量插入(通常是异步的)。

我认为没有必要使用如此小的插入来增加MaxConnectionPoolSize或WaitQueueSize。

这可能是什么原因?

我使用的是mLabs托管的MongoDB 3.0.7。我们的应用程序托管在Azure中(作为Web应用程序),而我使用的是C#2.2.3 SDK。

MongoDB.Driver.MongoWaitQueueFullException:的等待队列 获取到服务器xyz.monGolab.com:54128的连接已满。在… MongoDB.Driver.Core.ConnectionPools.ExclusiveConnectionPool.AcquireConnectionHelper.CheckingOutConnection() 在… MongoDB.Driver.Core.ConnectionPools.ExclusiveConnectionPool.AcquireConnection(CancellationToken 取消令牌)位于 MongoDB.Driver.Core.Servers.ClusterableServer.GetChannel(CancellationToken 取消令牌)位于 MongoDB.Driver.Core.Bindings.ServerChannelSource.GetChannel(CancellationToken 取消令牌)位于 MongoDB.Driver.Core.Bindings.ChannelSourceHandle.GetChannel(CancellationToken 取消令牌)位于 MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.Execute(IWriteBinding 绑定,取消令牌取消令牌)在 MongoDB.Driver.OperationExecutor.ExecuteWriteOperation[TResult](IWriteBinding 绑定,IWriteOperation"%1"操作,CancellationToken 取消令牌)位于 MongoDB.Driver.MongoCollectionImpl‘1.ExecuteWriteOperation[TResult](IWriteOperation`1 操作,取消令牌取消令牌)位于 MongoDB.Driver.MongoCollectionImpl‘1.BulkWrite(IEnumerable’1请求、 批量写入选项、取消令牌取消令牌)位于 MongoDB.Driver.MongoCollectionBase‘1.InsertOne(TDocument文档, InsertOneOptions选项,取消令牌取消令牌)

编辑:

如果我将MaxConnectionPoolSize设置为500,并将WaitQueueSize设置为2000,则会出现以下异常:

MongoConnectionException:打开 与服务器的连接。->System.Net.Sockets.SocketException:一个 试图以其访问所禁止的方式访问套接字 权限191.235.xxx.xxx:54128

实例化MongoClient

var client = new MongoClient(new MongoClientSettings()
{
    Server = url.Server,
    Credentials = credentials,
    MaxConnectionPoolSize = 500,
    WaitQueueSize = 2000
});

我最初提出了这个问题here。这让我试图弄明白,我到底为什么有这么多人脉。这导致了this post(质疑Insert/InsertBulk是否可能是原因)。无论如何,我仍然需要修复原始的MongoWaitQueueFullException问题。

推荐答案

解决问题的长期方法可能是引入限制机制,以确保您不会超过最大连接数。幸运的是,使用信号量很容易实现这一点。

public class ConnectionThrottlingPipeline : IConnectionThrottlingPipeline
{
    private readonly Semaphore openConnectionSemaphore;

    public ConnectionThrottlingPipeline( IMongoClient client )
    {
        //Only grabbing half the available connections to hedge against collisions.
        //If you send every operation through here
        //you should be able to use the entire connection pool.
        openConnectionSemaphore = new Semaphore( client.Settings.MaxConnectionPoolSize / 2,
            client.Settings.MaxConnectionPoolSize / 2 );
    }

    public async Task<T> AddRequest<T>( Task<T> task )
    {
        openConnectionSemaphore.WaitOne();
        try
        {
            var result = await task;
            return result;
        }
        finally
        {
            openConnectionSemaphore.Release();
        }
    }
}

如果您通过此限制管道将所有请求发送到数据库,则永远不会达到限制。

在您的示例中,通过管道发送操作可能如下所示(您必须进行的重大更改是使数据库调用处于异步状态):

await connectionThrottlingPipeline.AddRequest( 
   Context.Collection<ClientDocument>("clients").InsertManyAsync(clients))

这篇关于MongoWaitQueueFullException:获取服务器连接的等待队列已满的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆