Анализ ошибки переполнения очереди полного соединения 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
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose