Подтвердить что ты не робот

WCF: System.Net.SocketException - разрешено только одно использование каждого адреса сокета (протокол/сетевой адрес/порт)

У меня есть служба WCF и веб-приложение. Веб-приложение делает звонки на эту услугу WCF непрерывным способом a.k.a. В нашей производственной среде я получаю эту ошибку очень редко. Поскольку это внутренняя активность, пользователи не знали о том, когда эта ошибка выдается.

Не удалось подключиться к http://localhost/QAService/Service.svc. Код ошибки TCP 10048: Только одно использование каждого адреса сокета (протокол/сетевой адрес/порт) обычно разрешено 127.0.0.1:80. --- > System.Net.WebException: невозможно выполнить подключиться к удаленному серверу --- > System.Net.Sockets.SocketException: Только одно использование каждого адреса сокета (протокол/сетевой адрес/порт) обычно разрешено 127.0.0.1:80

У меня возникают проблемы с воспроизведением этого поведения в нашей среде dev/qa. Я убедился, что клиентское соединение закрыто в файле try..catch..finally. Все еще не понимаю, что вызывает эту проблему. Кто-нибудь знает об этом?

Примечание. Я рассмотрел этот вопрос SO, но, похоже, не отвечает на мою проблему, так что это не повторяющиеся вопросы.

4b9b3361

Ответ 1

Вы перегружаете стек TCP/IP. Windows (и я думаю, что все стеки сокетов фактически) имеют ограничение на количество сокетов, которые могут быть открыты в быстрой последовательности из-за того, как сокеты закрываются при нормальной работе. Всякий раз, когда сокет закрывается, он переходит в состояние TIME_WAIT в течение определенного времени (240 секунд IIRC). Каждый раз, когда вы проводите опрос, сокет потребляется из динамического диапазона по умолчанию (я думаю, его около 5000 динамических портов чуть выше 1024), и каждый раз, когда этот опрос заканчивается, этот конкретный сокет переходит в TIME_WAIT. Если вы достаточно часто проводите опрос, вы в конечном итоге будете использовать все доступные порты, что приведет к ошибке TCP 10048.

Как правило, WCF пытается избежать этой проблемы путем объединения соединений и подобных вещей. Обычно это касается внутренних служб, которые не переходят через Интернет. Я не уверен, что привязка wsHttp поддерживает объединение пулов, но привязка netTcp должна. Я бы предположил, что именованные каналы не сталкиваются с этой проблемой. Я не могу сказать для привязки MSMQ.

Существует два решения, которые можно использовать для решения этой проблемы. Вы можете либо увеличить диапазон динамического порта, либо сократить период TIME_WAIT. Первый, вероятно, более безопасный маршрут, но если вы потребляете чрезвычайно большой объем сокетов (что не похоже на случай вашего сценария), уменьшение TIME_WAIT - лучший вариант (или оба вместе).

Изменение диапазона динамических портов

  • Откройте regedit.
  • Открыть ключ HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
  • Изменить (или создать как DWORD) значение MaxUserPort.
  • Установите его на большее число. (т.е. 65534).

Изменение задержки TIME_WAIT

  • Откройте regedit.
  • Открыть ключ HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
  • Изменить (или создать как DWORD) TcpTimedWaitDelay.
  • Установите его на меньшее число. Значение находится в секундах. (то есть 60 за 1 минуту задержки).

Одно из вышеуказанных решений должно решить вашу проблему. Если он будет сохраняться после изменения диапазона портов, я бы попытался увеличить период вашего опроса, чтобы он случался реже... это даст вам больше возможностей для работы во времени задержки ожидания. Я бы изменил задержку ожидания времени как последнее средство.

Ответ 2

HttpClient, хотя он реализует IDisposable, является общим объектом, вы должны максимально сократить количество экземпляров. Вы можете уйти, имея только один экземпляр для всего вашего приложения, а не по одному для каждого запроса.

Я писал об этом довольно подробно на http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/