2012-04-10 4 views
4

Балансировщик нагрузки будет иметь некоторое ограничение на количество портов TCP, которые он может одновременно использовать на основе платформы, на которой он работает (например, я где-то читал, что Linux может одновременно открывать до 65535 портов tcp) , Это означает, что балансир становится узким местом и не сможет обслуживать такие многочисленные одновременные запросы, даже если ферма серверных серверов может обслуживать еще много запросов. Есть ли способ преодолеть эту проблему?Масштабирование балансировки нагрузки и максимальные порты #tcp

ответ

8

Номера портов TCP и UDP 16-разрядные, поэтому данный IP-адрес имеет только 65535 из них (порт 0 недействителен, я считаю). Но TCP-соединение идентифицируется 4-кортежем (исходный IP-адрес, исходный порт, целевой IP-адрес, порт назначения). (Похоже, wikipedia имеет ссылки, чтобы узнать больше.)

Для запросов клиента-> балансировщик: до тех пор, пока каждое входящее соединение имеет отдельный (исходный IP-адрес, порт источника), нет проблем. И клиент обычно это гарантирует. Единственные проблемы на этой стороне, о которых я помню, были с чрезвычайно популярным веб-сайтом со многими изображениями на странице при доступе от огромных интернет-провайдеров, которые NAT их клиенты за очень немногими адресами IPv4. Вероятно, это не ваша ситуация.

Запросы балансировки-> бэкэнд более интересны, так как вы, вероятно, создаете аналогичную ситуацию с проблемой NAT, о которой я упоминал выше. Я думаю, что Linux обычно пытается назначить отдельный ephemeral port для каждого сокета, и по умолчанию их всего 28,233. И IIRC он не использует их в состоянии TIME_WAIT, так что вы можете исчерпать диапазон, не имея при этом одновременного открытия нескольких соединений. IIRC, если вы нажмете этот предел, вы получите ошибку EADDRINUSE на connect (или на bind, если вы явно привязываете гнездо до подключения). Я не помню точно, как я получил вокруг этого раньше, гораздо меньше абсолютного лучший способ, но здесь есть несколько вещей, которые могут помочь:

  • сохраняя постоянную balancer-> соединения бэкэнд, а не создавать новый по одному для каждого (возможно, недолговечного) клиент-> балансировочного соединения.
  • установка SO_REUSEADDR на разъемах до bind/connect.
  • включение sysctl net.ipv4.tcp_tw_reuse и/или net.ipv4.tcp_tw_recycle.
  • явно выбирает исходный IP-адрес и/или порт для использования через bind, вместо того, чтобы позволить ядру автоматически назначать connect. У вас не может быть двух одновременных соединений с одним и тем же 4-кортежем, но все остальное в порядке. (Исключение: Я понтировавшего на продумывание ли TIME_WAIT повторного использования для того же 4-кортежа в порядке, я должен был бы освежить свою память о TIME_WAIT, прочитав некоторую TCP РЛКА.)

Вы, вероятно, придется немного экспериментировать. Хорошая новость заключается в том, что, как только вы поймете проблему, ее легко воспроизвести и проверьте, исправили ли вы ее.

Смежные вопросы