Назад | Перейти на главную страницу

Устранение нехватки эфемерного TCP-порта

У нас сайт с высокой посещаемостью. За последние несколько дней у нас было несколько клиентов, которые жаловались на спорадические простои, которые мы не можем воспроизвести. У нас есть несколько веб-серверов, выбранных для приема трафика от нашего балансировщика нагрузки, и во время исследования я понял, что все серверы сбрасывают более 20 подключений в секунду. Пример подключения с одного сервера выглядел так:

  38452 TIME_WAIT
   7815 ESTABLISHED
    570 FIN_WAIT2
    105 FIN_WAIT1
    101 LAST_ACK
     36 SYN_RECV
     25 CLOSING
      4 SYN_SENT
      2 CLOSE_WAIT
      1 Foreign

Наш настроенный диапазон портов в настоящее время установлен на 15000 61000 на всех серверах. Таким образом, может показаться, что все возможные порты должны быть исчерпаны, поскольку количество соединений, установленных или ожидающих закрытия, равно 46267.

Что нам делать с разорванными соединениями, пока мы исследуем трафик? Может быть, стоит увеличить диапазон портов? Уменьшить время ожидания закрытия соединений? Обе? Будет ли это иметь потенциально негативные последствия?

Есть несколько способов решить эту проблему.

Самый простой способ - увеличить эфемерный диапазон, но вы уже сделали это, и, очевидно, есть пределы того, как далеко вы можете зайти с этим решением.

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

Две вещи, которые вы можете безопасно сделать немедленно, пока вы рассматриваете другие долгосрочные решения, - это снизить таймеры TCP и включить tcp_reuse.

tcp_reuse довольно безопасно использовать в балансировщике нагрузки, и он позволяет ядру повторно использовать сокеты в состоянии TIME_WAIT для новых подключений. Чтобы включить его, запустите в Linux:

# sysctl -w net.ipv4.tcp_tw_reuse=1

Чтобы сделать загрузку постоянной:

# echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.d/net.ipv4.tcp_tw_reuse.conf

Другие параметры настройки ядра, которые могут помочь:

  • net.core.somaxconn (размер очереди прослушивания)
  • net.ipv4.tcp_max_syn_backlog (количество запомненных запросов на подключение без ACK)

Кроме того, вы можете уменьшить net.ipv4.tcp_fin_timeout до 1 или 2 (как долго сохранять сокеты в состоянии FIN-WAIT-2, если ваш хост является единственным закрывающим соединением).

Надеюсь, поможет.