random CONNECTION_RESET on apache2.4 debian 9

My server has some strange behaviour and I just cant find the cause. I've been looking everywhere.

I will pay 200$ worth of bitcoin to anyone who can figure this out.

The problem:

When requesting any resource from apache (page, image, css, js), it sometimes takes a very long time to respond. About half of the time, the connection gets reset. (on Chrome: net::ERR_CONNECTION_RESET) Это случается редко, случайным образом и совершенно непредсказуемо. Что еще более сбивает с толку, хотя кажется, что один запрос завис, я могу сделать дополнительные запросы, которые отлично работают.

О сервере:

Я запускаю apache2.4 mpm-prefork с php7.0 на debian 9. Apache модуль использует mod_rewrite и ssl-сертификат от certbot. В некоторых случаях php вызывает inkscape для рендеринга svgs в png.

Загрузка сервера очень мала (0,02), и на нем не работает только apache.

Что-то проверено:

  • проверил все журналы сервера. (syslog, apache log) - ничто
  • не увеличивало ограничения apache mpm-prefork - nope
  • проверило возможные проблемы с DNS - ничего
  • Я даже перешел на совершенно новый корневой сервер (на другом провайдере) - все еще тот же самый

Я продолжил и проанализировал TCP-трафик с помощью Wireshark, и обнаружил подозрительное поведение. Когда соединение зависает, есть некоторые нарушения порядка TCP, Вот файлы pcap, обрезанные до последних ~ 30 секунд.

serveride.pcap

clientside.pcap

Если кто-нибудь со знанием дела может быстро взглянуть на него и рассказать мне, что происходит, я ' я буду в восторге.

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ:

Мне удалось сделать ошибку воспроизводимой , по крайней мере, с включенным KeepAlive. Когда запрос завершен и контент обслуживается, tcp-соединение закрывается с помощью FIN-ACK через 5 секунд. При повторном запросе во временном окне 5-12 секунд после FIN-ACK соединение зависает.

Однако, когда KeepAlive отключен, этого больше не происходит, хотя ошибка возникает еще чаще при загрузке нескольких ресурсов одновременно. Но тогда это уже невозможно воспроизвести.

5
задан 5 February 2018 в 20:20
2 ответа

Я бы проверил размер TCP-пакетов, проходящих между сервером и клиентом. ЕСЛИ они приближаются к размеру 1500, есть вероятность, что они будут отброшены из-за множества возможностей:

  1. Если бит DNF установлен в пакете и пакет где-то фрагментируется, это может быть проблемой, которая приводит к тому, что пакет отбрасывается

    1. 12114] Если для MTU установлено значение 1500, а пакеты проходят через туннели, шифрование и т. Д., Что приводит к добавлению дополнительных заголовков к пакету, то это также приведет к падению ваших пакетов. Попробуйте установить для MTU на обоих концах используемых вами интерфейсов значение ниже 1500, возможно, 1420 или даже ниже.

1
ответ дан 3 December 2019 в 01:56

Уверен, что я нашел проблему :-), так как со мной случилось то же самое.

1. Причина

Я думаю, у вас есть ДВА или более процессов, обслуживающих порт 80 (или 443, если речь идет о соединениях SSL). Вы можете проверить это следующим образом, используя команду для порта 80 и вывод моей системы, в которой возникла проблема:

# netstat -tupan | grep ":80.*LISTEN"

Proto Recv-Q Send-Q Local    Foreign  State   PID/Program name
                    Address  Address
tcp6       0      0 :::80    :::*     LISTEN  22718/apache2
tcp6       0      0 :::80    :::*     LISTEN  1794/apache2

Два процесса, обслуживающие одни и те же IP-адреса с одного и того же порта, действительно возможны с параметрами порта SO_REUSEADDR и SO_REUSEPORT , см. здесь и здесь (раздел о «Linux> = 3.9»).

Что ядро ​​делает с SO_REUSEPORT предназначен для распределения входящих TCP-соединений по процессам, обслуживающим этот порт, недетерминированным образом. Один процесс - это ваш Apache, который правильно обслуживает запрос, а другой - "что-то еще", которое никогда ни на что не отвечает. В моем случае это был другой процесс Apache2.

2. Решение

  1. Если у вас есть два процесса Apache, сначала выясните, какой из них является «зомби». Для этого остановите свой обычный сервер Apache ( service apache2 stop ) и проверьте, какой из них остался ( netstat -tupan | grep ": 80. * LISTEN" ). Это «зомби». Обратите внимание на его PID.

  2. Чтобы узнать больше о том, кто или что запустил этот «зомби-процесс»:

    • Выполните cat / proc / / loginuid с PID этого «зомби-процесса» . Если отображается 4294967295 , это означает, что его запустила система, а не пользователь ( причина ). В противном случае вы можете найти UID пользователя.

    • Выполните ps auxf и определите время безотказной работы вашего «зомби» процесса. Если он соответствует времени безотказной работы системы, это означает, что процесс каким-то образом был запущен во время загрузки.

  3. Чтобы (возможно) узнать больше о том, что происходит внутри этого «зомби-процесса», вы можете подключиться к нему с помощью strace . Это создаст множество трудных для чтения журналов, но, поскольку воспроизвести проблему наличия этого «зомби-процесса» может быть нелегко, кажется полезным хотя бы собрать некоторые из этих журналов (особенно HTTP-запросов, идущих к этому процессу), прежде мы убиваем процесс. Вы должны выполнить с PID вашего процесса вместо $ PID :

     strace -o strace.log -f -p $ PID
     
  4. Чтобы решить проблему на данный момент, завершите процесс «зомби», указав его PID для $ PID : kill $ PID или, если необходимо, kill -9 $ PID .

  5. Проверьте, запущен ли этот "зомби-процесс" и снова работает после перезагрузки, и если да, вам нужно будет исследовать и устранить причину , .

3. Воспроизведение причины

Возможно (но не тривиально) вручную создать «зомби-процесс» Apache2, который будет работать параллельно с обычным сервером Apache и просто «ничего не отвечать». Вот почти - но не совсем полные инструкции:

  1. Создайте копии соответствующих файлов конфигурации:

     cp / etc / apache2 / envvars / etc / apache2 / envvars-zombie
    cp /etc/apache2/apache2.conf /etc/apache2/apache2-zombie.conf
     
  2. Отредактируйте / etc / apache2 / envvars-zombie и в начале скрипта статически установите SUFFIX = "- zombie" , переопределив в нем условное присвоение.

  3. Изменить /etc/apache2/apache2-zombie.conf и предотвратить включение любых файлов конфигурации VirtualHost. В моем случае я бы изменил соответствующую строку на:

     # IncludeOptional sites-enabled /
     
  4. Убедитесь, что порты прослушивания по умолчанию включены в ваш файл apache2-zombie.conf . В моем случае это уже произошло через Include ports.conf .

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

     mkdir / var / log / apache2-zombie
    чавн www-данных / вар / журнал / apache2-зомби /
    
    mkdir / вар / блокировка / apache2-зомби
    чавн www-данные / вар / блокировка / apache2-зомби /
     
  6. Теперь у вас должна быть возможность запустить свой «зомби» процесс Apache следующим образом:

     cd / etc / apache2 /
    источник envvars-zombie
     / usr / sbin / apache2 -f apache2-zombie.conf -k начало
     
  7. Убедитесь, что на стандартных портах Apache2 действительно запущен второй процесс: netstat -tupan | grep ": 80. * LISTEN" .

  8. Этот второй сервер Apache2 еще не является «зомби», потому что он все равно будет отвечать «404 Not Found» или (поскольку мы не настроили SSL) приведет к ошибке SSL при выполнении запроса на порт 443. Но вы уже можете наблюдать эффект, что несколько запросов поступают на этот новый сервер и приводят к этим ошибкам недетерминированным образом. (Я дошел до этого момента на практике…)

  9. Чтобы создать «правильный» зомби-Apache, настройте простой скрипт, который будет принимать HTTP-запрос и ничего не делать ( sleep () ) для несколько минут, чтобы браузер отказался, соответственно.чтобы время ожидания TCP-соединения истекло. Установите его для хоста Apache по умолчанию. Таким образом, он будет использоваться для всех HTTP-запросов к порту, поскольку мы отключили все конфигурации VirtualHost, поэтому Apache не может найти более подходящий хост для любого запроса и выберет хост по умолчанию.

1
ответ дан 3 December 2019 в 01:56

Теги

Похожие вопросы