【问题标题】:MongoDB Client throws Wait Queue Full exceptionMongoDB 客户端抛出等待队列满异常
【发布时间】:2020-12-19 18:12:11
【问题描述】:

我看到一个奇怪的问题,即 MongoDB 的 .NET 客户端引发 The wait queue for acquiring a connection to server 127.0.0.1:27017 is full. 异常。

我有一个信号量来保护对 MongoDB 的任何调用,大小为 10。 也就是说,对 Mongo 的并发调用永远不会超过 10 个。

.NET 驱动的默认连接池大小为 100,大于 10。 所以 10 个并发调用应该不是问题。

为了复制这一点,我有以下代码,做作是的,但它使问题可见。

我还为 MongoDB 找到了这个规范 https://github.com/mongodb/specifications/blob/master/source/connection-monitoring-and-pooling/connection-monitoring-and-pooling.rst#id94

这有关系吗? 每个调用线程(在这种情况下是线程池工作者)是否进入等待队列并尝试抓取一个连接,如果我有更多的工作线程,即使并发级别低,连接仍然必须分配给这个新调用工作线程?

using System;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using System.Threading;

namespace ConsoleApp58
{
    public class AsyncSemaphore
    {
        private readonly SemaphoreSlim _semaphore;

        public AsyncSemaphore(int maxConcurrency)
        {
            _semaphore = new SemaphoreSlim(
                maxConcurrency,
                maxConcurrency
            );
        }

        public async Task<T> WaitAsync<T>(Task<T> task)
        {
            await _semaphore.WaitAsync();
            //proves we have the correct max concurrent calls
            //  Console.WriteLine(_semaphore.CurrentCount);

            try
            {
                var result = await task;
                return result;
            }
            finally
            {
                _semaphore.Release();
            }
        }
    }
    
    class Program
    {
        public class SomeEntity
        {
            public ObjectId Id { get; set; }
            public string Name { get; set; }
        }

        static void Main(string[] args)
        {
            var settings = MongoClientSettings.FromUrl(MongoUrl.Create("mongodb://127.0.0.1:27017"));
            // settings.MinConnectionPoolSize = 10;
            // settings.MaxConnectionPoolSize = 1000;
            
            // I get that I can tweak settings, but I want to know why this occurs at all?
            // if we guard the calls with a semaphore, how can this happen?

            var mongoClient = new MongoClient(settings);
            var someCollection = mongoClient.GetDatabase("dummydb").GetCollection<SomeEntity>("some");
            var a = new AsyncSemaphore(10);
            
            // is this somehow related ?
            // https://github.com/mongodb/specifications/blob/master/source/connection-monitoring-and-pooling/connection-monitoring-and-pooling.rst#id94


            _ = Task.Run(() =>
                {
                    while (true)
                    {
                        // this bit is protected by a semaphore of size 10
                        // (we will flood the thread pool with ongoing tasks, yes)
                        _ = a.WaitAsync(RunTask(someCollection))
                            //after the task is done, dump the result
                            // dot is OK, else exception message
                            .ContinueWith(x =>
                            {
                                if (x.IsFaulted)
                                {
                                    Console.WriteLine(x.Exception);
                                }
                            });
                    }
                }
            );

            Console.ReadLine();
        }

        private static async Task<SomeEntity> RunTask(IMongoCollection<SomeEntity> pids)
        {
            //simulate some mongo interaction here
            var res = await pids.Find(x => x.Name == "").FirstOrDefaultAsync();
            return res;
        }
    }
}

【问题讨论】:

    标签: c# mongodb multithreading


    【解决方案1】:

    建立连接需要时间。您不会立即获得 100 个可用连接。如果您创建一个客户端并立即请求 10 个操作,而没有可用的连接,您可能会遇到等待队列超时。

    一些司机也有等待队列长度限制。它不是标准化的,在我的理解中应该被弃用,但出于兼容性原因可能会继续存在。请参阅您的驱动程序文档以了解如何提高它。

    然后,要么增加 waitQueueTimeoutMS 或逐渐增加负载,要么在开始加载之前等待连接建立(后者可以使用 CMAP 事件)。

    确保您的 10 个未完成操作的并发限制实际上也正常工作。

    【讨论】:

      猜你喜欢
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      • 2016-06-24
      • 1970-01-01
      • 2019-04-21
      相关资源
      最近更新 更多