Анализ ошибки переполнения очереди полного соединения TCP из исходного кода и реального боя
Анализ ошибки переполнения очереди полного соединения TCP из исходного кода и реального боя

Краткое содержание статьи: Трехстороннее рукопожатие TCP должно быть изучено таким образом

«Углубленный анализ управления TCP-соединениями: стратегии трехстороннего рукопожатия и реагирования на переполнение очереди»

картина
картина

Сначала подведем итог содержания статьи:

Процесс трехстороннего установления связи TCP:

  1. Клиент отправляет SYN:клиентконецвызовconnect系统вызов,Ядро устанавливает статус сокета установлен наTCP_SYN_SENT,иотправлятьSYNсообщение.этотчас,Ядро создает структуру request_sock.,Представляет запрос полусоединения.
  2. Сервер отвечает на SYN-ACK:СлужитьконецполучатьSYNПосле сообщения,Статус ядра изменится на TCP_NEW_SYN_RECV.,Подготовьте сообщение SYN-ACK для ответа клиенту на конец.
  3. Клиент завершает рукопожатие:клиентконецполучатьSYN-ACKназад,Статус обновления ядра — TCP_ESTABLISHED.,Соединение установлено,клиентконецможно начатьотправлятьданные。

Управление очередью TCP:

  • Полусвязная очередь (очередь SYN):Клиент отправляет SYNПосле сообщения,Получатель Служить получает и переходит в состояние SYN_RECV.,Соединение помещается в очередь полусоединения.。Длина очереди определяется выражениемtcp_max_syn_backlognet.core.somaxconnиlisten(fd, backlog)изbacklogОпределяется минимумом из трех。
  • Полная очередь подключений (очередь ACCEPT):клиент Отправить с концаACKПосле сообщения,Сервер Служить перемещает соединение из очереди полуподключения в очередь полного подключения.,ВходитьESTABLISHEDсостояние。Длина очереди определяется выражениемnet.core.somaxconnиlisten(fd, backlog)изbacklogМинимальное значение из двух определяет。

Обработка исключений очереди подключений:

  • Очередь полуподключений заполнена:Служить Сервер не может обработать новыйизSYNпросить,привести к новымиз Попытка подключения не удалась。Можетпроходить Корректированиеnet.core.somaxconnиtcp_max_syn_backlogПараметры для добавления очередиразмер.
  • Полная очередь подключений заполнена:Служить Сервер установил соединение,Но приложение не соответствует требованиямчасвызовaccept(),привести к новым连接无法被接受。Можетпроходить КорректированиеsomaxconnПараметры для добавления очереди大小,и根据tcp_abort_on_overflowРешение по параметрудавыброситьACKГарантированный возвратдаотправлятьRSTСумка给клиентконец。

Соответствующие параметры ядра:

  • tcp_max_syn_backlog:定义系统Может同час Потому что трехстороннее рукопожатие не завершеноиз Сколько позиций в очереди полусоединения резервирует соединение?。
  • net.core.somaxconn:обозначение Все розетки в системемониторочередьизмаксимальная длина。
  • tcp_abort_on_overflow:Решать Полное переполнение очереди соединенийчасиз Поведение(выброситьACKилиотправлятьRST)。

Команды устранения неполадок:

  • netstat -ant или ss -ant:Посмотреть локальноизTCPстатус соединения, проверьте, является ли количество SYN_SENTiz ненормальным.
  • sysctl net.core.somaxconn:Проверятьинастраиватьsomaxconnизценить。
  • sysctl net.ipv4.tcp_max_syn_backlog:ПроверятьTCP半连接очередьизмаксимальная длина。
  • cat /proc/sys/net/ipv4/tcp_abort_on_overflow:Проверятьtcp_abort_on_overflowизкогда前ценить。
  • netstat -s | grep "overflowed":Проверять Полное переполнение очереди соединенийизчастота。

Инструмент стресс-тестирования: легкий инструмент для тестирования производительности HTTP.

wrk — это инструмент тестирования производительности HTTP, написанный на языке C и разработанный пользователем GitHub wg/wrk. Он может выполнять нагрузочное тестирование на сервере, генерируя большое количество HTTP-запросов, и выводить результаты тестирования в режиме реального времени, включая ключевые показатели производительности, такие как частота запросов, скорость передачи и количество подключений. Первоначальная цель разработки wrk — предоставить простой и удобный в использовании инструмент для тестирования производительности, гарантируя при этом точность и надежность результатов тестирования.

Особенности работы

  1. Легкость: wrk написан на языке C, занимает меньше ресурсов и имеет высокую эффективность работы. Он может быстро генерировать большое количество HTTP-запросов, не потребляя слишком много системных ресурсов.
  2. Мощные функции. Хотя wrk имеет простой интерфейс, его функции очень мощные. Он поддерживает настраиваемые заголовки запросов, методы запросов, содержимое запросов и другие параметры, а также может моделировать различные сложные сценарии HTTP-запросов.
  3. Реальностьчасобратная связь:во время тестирования,wrk внедрит и выведет различные показатели эффективности.,Например, скорость запроса, скорость передачи и т. д.,Помогите разработчикам ичас Понятноразвязать Служитьустройствоиз Производительность。
  4. Простота в использовании: wrk очень прост в использовании и требует всего лишь нескольких параметров для начала тестирования, что позволяет разработчикам быстро приступить к работе и провести тестирование производительности.

Как использовать работу

Использовать wrk очень просто. Основной формат команды следующий:

Язык кода:javascript
копировать
wrk [options] http://host:port/path

Среди них [options] — необязательный параметр, а http://host:port/path — это URL-адрес, который необходимо протестировать. Вот некоторые часто используемые варианты:

  • -c, --connections:настраиватьи发连接数。
  • -t, --threads:настраивать线程数。
  • -d, --duration:настраивать测试持续часмежду(Второй)。
  • -D, --header:添加自定义просить头。
  • -H, --default-header:настраивать默认просить头。
  • -s, --script:обозначениеLuaфайл сценария,Используется для настройки поведения запроса.

Например, для стресс-тестирования веб-сервера используйте следующую команду:

Язык кода:javascript
копировать
wrk -c 100 -t 10 -d 60 http://example.com/

Эта команда будет моделировать 100 одновременных подключений, использовать 10 потоков и продолжать тестирование в течение 60 секунд.

Практический бой — переполнение очереди полного соединения TCP

Полный контроль максимальной длины очереди подключений

Максимальное значение очереди полного соединения TCP зависит от минимального значения между somaxconn и backlog, которое равно min(somaxconn, backlog), где:

  • somaxconn — это параметр ядра Linux, указанный в /proc/sys/net/core/somaxconn.
  • Backlog — это один из параметров функции прослушивания в протоколе TCP, то есть размер очереди в функции int Listen(int sockfd, int backlog).

Соответствующий код ядра:

Язык кода:javascript
копировать
// https://github.com/torvalds/linux/blob/master/net/socket.c  /*  *  Perform a listen. Basically, we allow the protocol to do anything  *  necessary for a listen, and if that works, we mark the socket as  *  ready for listening.  */ int __sys_listen(int fd, int backlog) {   struct socket *sock;   int err, fput_needed;   int somaxconn;    sock = sockfd_lookup_light(fd, &err, &fput_needed);   if (sock) {     somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;  // /proc/sys/net/core/somaxconn     if ((unsigned int)backlog > somaxconn)       backlog = somaxconn;   // TCP Максимальная длина полной очереди подключений min(somaxconn, backlog)      err = security_socket_listen(sock, backlog);     if (!err)       err = sock->ops->listen(sock, backlog);      fput_light(sock->file, fput_needed);   }   return err; }

Просмотр команд для полного переполнения очереди подключений

ss

Язык кода:javascript
копировать
# -n Не разбирать Служить имя # -t Показать только tcp sockets # -l Показ монитора(СЛУШАТЬ)из sockets  ss -lnt State               Recv-Q              Send-Q                           Local Address:Port                           Peer Address:Port              Process              LISTEN              0                   511                                    0.0.0.0:80                                  0.0.0.0:*                                      LISTEN              0                   128                                    0.0.0.0:22                                  0.0.0.0:*                                      LISTEN              0                   128                                  127.0.0.1:631                                 0.0.0.0:*                                      LISTEN              0                   4096                             127.0.0.53%lo:53                                  0.0.0.0:*                                      LISTEN              0                   511                                       [::]:80                                     [::]:*                                      LISTEN              0                   128                                       [::]:22                                     [::]:*                                      LISTEN              0                   128                                      [::1]:631                                    [::]:*

Мы можем видеть из исходного кода ss Получено по команде Recv-Q/Send-Q В «СЛУШАЙТЕ статус» и «нет LISTEN Значения, выражаемые словом «статус», различны.

Язык кода:javascript
копировать
// https://github.com/torvalds/linux/blob/master/net/ipv4/tcp_diag.c static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,             void *_info) {   struct tcp_info *info = _info;    if (inet_sk_state_load(sk) == TCP_LISTEN) { // socket Статус да LISTEN час     r->idiag_rqueue = READ_ONCE(sk->sk_ack_backlog);  // Текущий размер очереди полного подключения     r->idiag_wqueue = READ_ONCE(sk->sk_max_ack_backlog); // Максимальная длина полной очереди подключений   } else if (sk->sk_type == SOCK_STREAM) {    // socket Статус не да LISTEN час     const struct tcp_sock *tp = tcp_sk(sk);      r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) -                READ_ONCE(tp->copied_seq), 0);    // Количество байтов, полученных, но не прочитанных приложением     r->idiag_wqueue = READ_ONCE(tp->write_seq) - tp->snd_una;   // Количество отправленных байтов, но не получено подтверждение   }   if (info)     tcp_get_info(sk, info); }

Для сокетов в состоянии LISTEN

  • Recv-Q: размер текущей полной очереди соединений, то есть TCP-канала, который завершил трехстороннее рукопожатие и ожидает принятия приложения().
  • Send-Q: максимальная длина полной очереди подключений, то есть размер полной очереди подключений.
Язык кода:javascript
копировать
# -n Не разбирать Служить имя # -t Показать только tcp sockets # -l Показ монитора(СЛУШАТЬ)из sockets
картина
картина

Для сокетов в состоянии не-LISTEN

  • Recv-Q: количество полученных, но не прочитанных приложением байтов.
  • Send-Q: количество отправленных байтов, но не полученное подтверждение.
Язык кода:javascript
копировать
# -n Не разбирать Служить имя 
# -t Показать только tcp sockets
картина
картина

моделируемая среда

Чтобы добиться очевидных экспериментальных результатов, мы модифицируем настройки системы с длинной очередью подключений.

Установите somaxconn на 8

1. Обновите файл /etc/sysctl.conf, который является файлом конфигурации параметров ядра.

а. Добавьте новую строку net.core.somaxconn=8.

2. Выполните sysctl -p, чтобы конфигурация вступила в силу.

Язык кода:javascript
копировать
sudo sysctl -p 
net.core.somaxconn = 8

3. Проверьте файл /proc/sys/net/core/somaxconn и убедитесь, что somaxconn является обновленной версией 8.

Язык кода:javascript
копировать
cat /proc/sys/net/core/somaxconn
8

Перезагрузите сервер и подтвердите полный размер очереди подключений с помощью ss -lnt grep :8888.

Язык кода:javascript
копировать
ss -lnt | grep 8080
LISTEN 0      8          0.0.0.0:8080      0.0.0.0:*  

Как видите, максимальная длина полной очереди ссылок теперь равна 64, и обновление прошло успешно.

Развертывание службы nginx

Язык кода:javascript
копировать
apt  install nginx

Настроить мониторинг nginx

Язык кода:javascript
копировать
vim /etc/nginx/conf.d/bingo.conf
server {
    listen 8080 default; 
    server_name localhost; 

    location / {
    return 200 "bingo";
    }
}

Изменить количество рабочих мест

Язык кода:javascript
копировать
vim /etc/nginx/nginx.conf
worker_processes 1;

relead nginx

Язык кода:javascript
копировать
nginx -s reload

Проводить постоянное стресс-тестирование

Язык кода:javascript
копировать
wrk -t 6 -c 30000 -d 60s http://127.0.0.1:8080/

Используйте команду ss, чтобы просмотреть текущую ситуацию с очередью полных подключений TCP:

картина
картина

Может看到когда前изTCPПолностью подключен к Понятно9больше максимальногоTCP全连接очередь,Как только оно превысит Понятно系统настраиватьизTCP最大全连接очередь,Служитьконец потеряет последующие входящие запросы,我们Можетделатьиспользоватьnetstat -s Посмотреть статистику

картина
картина

Вы можете нажать 514458 раз, чтобы указать, сколько раз была переполнена очередь подключений. Обратите внимание, что это накопительное значение.

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

Анализ посредством захвата пакетов

картина
картина

Вы можете увидеть много сообщений SYN + ACK. Это связано с тем, что вся очередь подключений заполнена, что заставляет Клиента думать, что соединение TCP-сокета с Сервером было успешно установлено, и Сервер продолжает думать, что последующая отправка данных не удалась. что TCP-соединение не установлено и продолжает отправлять SYN+ACK.

Процесс запроса можно увидеть следующим образом:

  • Клиент отправляет серверу сообщение подтверждения пакета SYN.
  • server После получения пакета SYN терминал отвечает SYN. + Пакет ACK, хранилище соединений Пучоксокет к Очереди полусоединения (SYN Queue)
  • После того, как клиент получает пакет SYN+ACK от сервера, он отвечает ACK серверу, и клиент переходит в состояние ESTABLESHED — совет: в это время только клиент думает, что TCP-соединение установлено успешно.
  • Поскольку TCP-соединение задачи на стороне клиента было установлено, оно отправит данные [PSH, ACK] на сторону сервера, но оно не получило пакет ACK со стороны сервера, поэтому оно всегда будет RETRY.
Язык кода:javascript
копировать
 Server конец socket Соединение попадает в очередь полусоединения, и после получения Client конец ACK После этого должно было быть socket Соединения сохраняются в полной очереди соединений, но дальняя очередь подключений заполнена,так Server конец DROP Пришло время ACK просить.
  • Серверная сторона продолжает отправлять SYN+ACK в RETRY.
Язык кода:javascript
копировать
 Server конец всегда здесь RETRY отправлять SYN+ACK, потому что DROP Понятно client конециз ACK просьба, так что socket Соединение все еще находится в очереди полусоединения, ожидая Client конецотвечать ACK。

По умолчанию отправляется запрос DROP, когда полная очередь подключений заполнена. Вы можете настроить /proc/sys/net/ipv4/tcp_abort_on_overflow, чтобы сервер отправлял сообщение RST клиенту, когда полная очередь подключений заполнена.

Язык кода:javascript
копировать
cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0

tcp_abort_on_overflow

tcp_abort_on_overflow имеет два необязательных значения:

  • 0: Если полная очередь подключений заполнена, серверная сторона ОТДАЕТ подтверждение, возвращенное клиентской стороной.
  • 1: Если полная очередь подключений заполнена, сервер отправляет клиенту сообщение RST и разрывает соединение через сокет TCP.

Установите для tcp_abort_on_overflow значение 1.

Язык кода:javascript
копировать
root@adming-virtual-machine:/mnt/hgfs# echo "1" > /proc/sys/net/ipv4/tcp_abort_on_overflowroot@adming-virtual-machine:/mnt/hgfs# cat  /proc/sys/net/ipv4/tcp_abort_on_overflow1
Язык кода:javascript
копировать
Сделать запрос
Язык кода:javascript
копировать
wrk -t 6 -c 30000 -d 60s http://127.0.0.1:8080/

Вы можете видеть, что вся очередь подключений заполнена.

картина
картина

Благодаря захвату пакетов вы можете увидеть множество сообщений о сбросе.

картина
картина

Контрмеры

Настройка по умолчанию:Обычно рекомендуетсяtcp_abort_on_overflowустановлен на0,Это помогает при скачках трафика.часподдерживать связьизстабильность。

Управление трафиком:когдаTCP全连接очередь因流量突增而溢出час,если Служитьустройствовыбросить ПонятноклиентконецизACKСумка,Клиентский конец подумает, что соединение не удалось установить.,тем самым запуская механизм повторной передачи。настраиватьtcp_abort_on_overflowдля0允许系统существоватьочередь有空междучас继续处理这些连接просить,без немедленного прекращения их действия.

статус соединения:Прямо сейчасделатьсуществовать Служитьустройствоконециз Полное переполнение очереди соединенияиз случае, если у клиента закончился статус соединенияужедаESTABLISHED,клиентконец进程仍然会尝试существовать已建立из Подключеноотправлятьпросить.потому что Служитьустройство没有отвечатьACK,клиентконец Буду продолжать отправлять повторнопросить.

Управление очередью:если Служитьустройство进程只давременночас Причина в занятостиacceptочередь满,Затем, как только очередь TCP-соединения освободится,,Новое сообщение запроса (включая ACK) может заставить сервер успешно установить соединение.

Установите сцену:仅существовать确定TCP全连接очередь会长期处于溢出состояниечас,Только тогда следуетtcp_abort_on_overflowустановлен на1,Это может быстро уведомить клиента о том, что соединение не может быть установлено.,Избегайте растраты ресурсов.

Компромиссы:установлен на1Может迅速释放资源,Но некоторыми показателями успешности соединения можно пожертвовать. поэтому,Если нет явных проблем с производительностью,В противном случае сохранение настройки по умолчанию из0 обычно является лучшим выбором.

Увеличьте очередь полных соединений TCP:существовать系统确认да Полное переполнение соединения,Основная причина не обнаружена. Мы можем увеличить размер полной очереди подключений в соответствии с вычислительной мощностью системы.,Восстановить и смягчить влияние онлайн-сбоев на клиентов.

Я участвую в последнем конкурсе эссе для специального учебного лагеря Tencent Technology Creation 2024. Приходите и разделите со мной приз!

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.