Исключения сокетов MongoDB C# в IIS 7.0 Web Garden (например, разрешено только одно использование каждого адреса сокета (протокола / сетевого адреса / порта))

У меня есть приложение ASP MVC, использующее драйвер 10gen Mongo C# ( github) для подключения к серверу базы данных через определенный порт. Я развернул это в веб-саду IIS 7.0 с 3 рабочими процессами. Каждые несколько минут под нагрузкой выдается следующее исключение, и 500 возвращается пользователю:

Only one usage of each socket address (protocol/network address/port) is normally permitted <database-ip>:<database-port>

Stack Trace:    

   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
   at MongoDB.Driver.Internal.MongoConnection.Open() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Internal\MongoConnection.cs:line 266
   at MongoDB.Driver.Internal.MongoConnection.GetNetworkStream() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Internal\MongoConnection.cs:line 409
   at MongoDB.Driver.Internal.MongoConnection.SendMessage(MongoRequestMessage message, SafeMode safeMode) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Internal\MongoConnection.cs:line 377
   at MongoDB.Driver.Internal.MongoConnection.RunCommand(String collectionName, QueryFlags queryFlags, CommandDocument command) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Internal\MongoConnection.cs:line 296
   at MongoDB.Driver.Internal.MongoConnection.Authenticate(String databaseName, MongoCredentials credentials) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Internal\MongoConnection.cs:line 98
   at MongoDB.Driver.Internal.MongoConnection.CheckAuthentication(MongoDatabase database) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Internal\MongoConnection.cs:line 195
   at MongoDB.Driver.MongoServerInstance.AcquireConnection(MongoDatabase database) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoServerInstance.cs:line 185
   at MongoDB.Driver.MongoServer.AcquireConnection(MongoDatabase database, Boolean slaveOk) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoServer.cs:line 893
   at MongoDB.Driver.MongoCursorEnumerator`1.AcquireConnection() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCursorEnumerator.cs:line 184
   at MongoDB.Driver.MongoCursorEnumerator`1.GetFirst() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCursorEnumerator.cs:line 194
   at MongoDB.Driver.MongoCursorEnumerator`1.MoveNext() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCursorEnumerator.cs:line 126
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at MongoDB.Driver.MongoCollection.FindOneAs[TDocument](IMongoQuery query) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCollection.cs:line 493
   at MongoDB.Driver.MongoCollection.FindOneByIdAs[TDocument](BsonValue id) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCollection.cs:line 529
   at MongoDB.Driver.MongoCollection`1.FindOneById(BsonValue id) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCollection.cs:line 1462

Я потратил много времени на поиск этого исключения и почти убедил себя, что у меня заканчиваются сокеты, как описано в WCF: System.Net.SocketException - только одно использование каждого адреса сокета (протокол / сетевой адрес / порт) обычно разрешено

но проблема не была затронута моим увеличением максимального числа доступных сокетов и уменьшением значения TIME_WAIT.

Недавно мне пришло в голову, что, хотя драйвер Mongo выполняет пул соединений, каждый рабочий процесс имеет свой пул. Эти пулы либо работают вместе, чтобы запустить систему из сокетов, либо просто пытаются использовать один и тот же адрес сокета одновременно. Последнее условие представляется более вероятным, поскольку это именно то, что предлагает исключение, и проблема не возникает, когда сайт развертывается в одном процессе. Но за пределами веб-сада снижение производительности очень заметно, и в случае сбоя процесса задержка повторного использования недопустима. При этом пользователи, получившие 500 ответов, в равной степени неприемлемы.

Я учел следующее:

  1. Оберните все вызовы доступа к данным в конструкции try / retry-n-times / fail (некрасиво и просто плохо)
  2. Переход на несколько машин вместо многопроцессорных (дорогостоящих и ненужных при текущих пользовательских нагрузках)

Вопросы:

  1. Есть ли способ, чтобы эти рабочие процессы изящно разделяли адрес / порт?
  2. Есть ли способ сделать своего рода "запуск порта" (я уверен, что это не правильный термин), когда исходящее соединение каждого рабочего процесса может использовать другой локальный порт для подключения к тому же удаленному порту? Удаленный компьютер может обрабатывать несколько входящих соединений на одном и том же порту без проблем.
  3. Если вы думаете, что у меня заканчиваются сокеты, есть ли способ ограничить количество соединений сокетов для каждого процесса, чтобы они могли совместно использовать 65536 сокетов.

0 ответов

Другие вопросы по тегам