Re: Тест nginx -- сколько сообщений в log syslog без потерь?
Gena Makhomed
gmm на csdoc.com
Вт Фев 20 05:48:00 UTC 2024
On 19.02.2024 16:01, Anatoliy Melnik via nginx-ru wrote:
>>>> Если вы предлагаете писать напрямую с nginx-а в файл --
>>>> сделайте у себя ротацию файлов с интервалом 30 сек
>>>> при 200-250 тыс подключений/сек...
>>>>
>>>> Если у вас уже есть такое рабочее решение -
>>>> поделитесь опытом, буду рад вас выслушать.
>>>
>>> Я намеренно ввел вас в заблуждение путем публикации сообщения,
>>> допускающее двойное толкование в ту или иную сторону по желанию
>>> сторон.
>>
>> Почему / зачем?
>
> Был шанс увидеть в ответ нестандартное решение.
Из представленной Вами информации - что Вам не удалось настроить
ротацию логов nginx раз в 30 секунд при 200-250 тыс. подключений
в секунду однозначно следует что Вы использовали для ротации логов
сигнал SIGHUP, делающий полный reload nginx а не сигнал SIGUSR1,
который только переоткрывает лог-файлы, не перезапуская рабочие
процессы. Никакого нестандартного решения в этой ситуации быть
не может, кроме как использовать SIGUSR1 вместо SIGHUP
для ротации логов nginx. И, как я понимаю, из представленной
Вами информации - именно эта изначальная Ваша ошибка и стала
причиной того, что не сумев настроить ротацю логов Вы ударились
во все тяжкие с syslog, unix socket`ами и 11 процессами на Python,
называя этот набор костылей решением вышеназванной Вами проблемы X.
Какое именно "нестандартное решение" для вышеобозначенной проблемы
с невозможностью нормально настроить ротацию логов Вы сами могли бы
предложить, если бы оказались на месте читателя своих же сообщений?
Я так понимаю, что и Вы точно так же не видите никаких других вариантов
решения этой "проблемы" с невозможностью настроить ротацию логов,
кроме как использовать SIGUSR1 вместо SIGHUP для ротации логов nginx.
>> С моей точки зрения более важным является обеспечение более высокой
>> надежности работы системы, чтобы логи не терялись в процессе записи,
>> чем экономия свободного места на диске и экономия ресурсов NVMe SSD.
>>
>> Поэтому с моей точки зрения - я не могу признать решение
>> через syslog и unix socket более оптимальным, чем вариант
>> записи логов напрямую в файлы и ротации логов через SIGUSR1.
>>
>> а ротацию логов можно делать и чаще, чем раз в 30 секунд,
>> например, раз 15, или раз в 10 или даже раз в 5 секунд,
>> если хочется уменьшить отставание статистики по времени.
>>
>> По сути - лог-файл на диске - это можете воспринимать примерно,
>> как то же самое, что и unix socket, только с буфером не в памяти,
>> а в виде файла на диске и без существенных ограничений по размеру
>> такого буфера, что будет лучше сглаживать всплески нагрузки
>> и может позволить большую асинхронность между процессом
>> записи информации в лог и процессом чтения информации
>> из лога. А во всем остальном - никакой существенной
>> разницы нет, учитывая только что запись логов в файлы
>> меньше грузит процесор и использует немного больше
>> свободного места на диске.
>>
>> Но мне например, лучше чтобы процессор был немного свободнее,
>> чем проистаивающее и никак не используемое место на диске.
>>
>> Но самое главное - что запись логов в файлы не приводит к потере
>> данных, а запись логов в unix socket может приводить к потерям
>> даных, если читатель будет не успевать забирать данные из unix
>> socket.
>>
>> Более надежное и более простое решение, и более экономно
>> расходующее процесор сервера - и будет более оптимальным.
> пока я наблюдал скорее проблему "писатель не успевает записывать",
> а не "читатель не успевает забирать".
видимая Вами проблема "писатель не успевает записывать"
вызвана именно тем, что "читатель не успевает забирать".
Потому что когда у Вас был всего один читатель - он не успевал
читать данные из syslog и поэтому у nginx не было никаких других
вариантов, кроме как дропать часть сообщений. После того как вместо
одного читателя Вы сделали 10 читателей - они начали успевать читать
данные из syslog и проблема с потерей сообщений стала быть Вам не видна.
> Эта же проблема и при файлах присутствует -- NVME не у всех всегда везде.
> Система дисковая как ни крути - общий ресурс, и если ее интенсивно нагрузить
> чем-то еще логи тоже могут получить проблему читатель-писатель.
На frontend-сервере, сеть может быть загружена на 100% передачей данных,
и процессор может быть загружен на 100% шифрованием/расшифровской TLS.
Дисковая подсистема может использоваться только для записи логов.
нагружать дисковую подсистему чем-либо еще, крмое записи логов
- нерационально, имеет смысл даже полностью выключить использование
диска при проксировании, чтобы не было блокирования nginx на операциях
дискового ввода-вывода и чтобы не было увеличения latency, когда этого
можно очень просто ибежать:
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_max_temp_file_size 0;
По поводу того, что сейчас NVMe есть не у всех и не всегда
- это Вы мне сейчас из какого года свое сообщение пишете ?
> Единственный плюс прямой записи в файл -- это длительное хранение данных, чего лично мне вот вообще не требуется.
У Вас очень специфически задачи. Потому что как правило логи нужны.
Потому что если логи не нужны - их просто выключают для 1хх, 2хх
и 3хх статусов и логгируют только 4хх и 5хх ошибки, так что размер
лог-файлов получается очень небольшим и никаких проблем создать не может.
map $status $loggable {
~^[45] 1;
default 0;
}
access_log /path/to/access.log combined if=$loggable;
>> Вот как я уже говорил, задача построения VPN - если взять все множество
>> таких задач, то в части случаев для построения VPN более оптимальным
>> вариантом будет использование WireGuard, а в части случаев - OpenVPN.
>> Именно потому, что WireGuard обладает некоторыми свойствами
>> и качествами, которые отсутствуют в OpenVPN, и наоборот,
>> потому что OpenVPN обладает некоторыми свойствами и качествами,
>> которые отсутствуют в WireGuard. И поэтому в части случаев
>> оказывается более оптимальным и целесообразным построение
>> VPN с использованием WireGuard, а в некоторых случаях
>> - более оптимальнныи и целесообразным оказывается
>> построение VPN с использованием OpenVPN.
>>
> И в части случаев оба они окажутся в равной степени не пригодны...
> Да и там, где пригодны, далеко не всегда оптимальны по каким-то критериям.
> VPN технологий существуют десятки. Но вы почему-то в этом посте ограничились 2-мя.
> А как же "все множество путей" ?
> Эти 2 достаточно удобны для решения большого круга задач -- это да, но это не отменяет достоинств других VPN-ов.
Я рассматриваю только те реализации VPN, которые доступны
в виде open source, и которые доступны для использования,
без необходимости покупать лицензию на право использования
программы.
Все другие варианты Open Source VPN имеет смысл рассматривать
только в том случае, если они имеют какие-то преимущества,
по сравнению с WireGuard и OpenVPN. Если у них никаких
преимуществ нет - тогда их можно и не рассматривать.
Еще есть Shadowsocks, если необходимо обходить
блокировки WireGuard и OpenVPN через DPI,
но это очень специфическая задача.
WireGuard и OpenVPN - это две наиболее надежные
по качеству кода и наиболее проверенные аудитами
реализации VPN. По этому парметру - все остальные
реализации и варианты VPN - значительно хуже.
Например, в самом протоколе IPsec или в его популярных реализациях
могут быть закладки от NSA, поэтому IPsec лучше не использовать.
https://en.wikipedia.org/wiki/IPsec#Alleged_NSA_interference
>> Так ведь свободное место на разделе есть, с этим же нет проблем.
> Есть проблема.
> В исходной постановке (когда сия задача встала передо мной) задачи было пожелание обойтись имеющимся ресурсом.
> Я задачу решил именно в этих начальных условиях.
Как правило, свободное место на диске - это самый дешевый ресурс.
И экономить место на диске, увеличивая нагрузку на процессор,
или теряя часть сообщений - это не самое лучшее решение.
>>> с моей точки зрения менять одну проблему на другую смысла нет
>>
>> использование места на диске - это не проблема, это необходимая плата
>> за то, что запись в логи будет происходить без потерь информации,
>> и что чтения и обработка информации из логов не обязаны быть
>> такими синхронными и производительными, как в случае с unix
>> socket`ами.
>>
> Обязаны! и синхронными и производительными.
> Если статистика будет накапливаться быстрее, чем обрабатываться, то данные никогда не будут актуальны.
> Т.е. я сегодня увижу статистику за вчера, а за сегодня-- только через 2 дня, а к концу года буду видеть уже с отставанием в месяц??
> И кому это будет интересно??
Вы меня не поняли.
Если использовать unix socket - при переполнении буфера
в памяти происходит потеря части сообщений. Если в условиях
постановки задачи важно не терять сообщения - тогда читатель
сообщений должен быть таким же производительным и как писатель.
Иногда, во время DDoS-атак приходит огромное количество запросов,
так что процессор может быть занят на 100% и просто не остается
на сервере процессорных мощностей для того, чтобы читатель
с другой стороны unix socket`а успевал бы считывать данные
с такой же скоростью, с какой их будет писать туда nginx.
А это означает, что такая ситуация неизбежно приведет
к потере части сообщений, которые nginx будет вынужден
дропать потому что читатель не успевает их читать
с другой стороны unix socket`а.
Мне такое нестабильно работающее и ненадежное решение не нужно,
которое вроде бы нормально работает под небольшой нагрузкой,
но начинает глючить и терять сообщения, когда нагрузка возрастает.
Если же nginx пишет логи в файл - тогда такой высокой степени
синхронности читателя и писателя логов не нужно, пототому что
нет буфера в памяти, который очень быстро может переполниться,
а есть просто файлы на диске, и читатель логов может читать их
с постоянной скоростью, например, 1 мегабайт в секунду, и даже
если будут всплески нагрузки на сервер и в какие-то моменты
nginx будет писать логи со скоростью 10 или 100 мегабайт в секунду
- это все равно не будет приводить к потере сообщений, потому что
в этом случае нет небольшого буфера в оперативной памяти, а роль
буфера выполняет фактически все свободное место на диске сервера.
И пиковые всплески нагрузки на сервер будут сглаживаться с помощью
очень большого "буфера" на диске, и потери сообщений тогда не будет.
То есть, при всех прочих условиях, более надежная и более устойчивая
к всплескам нагрузки система обработки логов nginx которая не теряет
сообщения является более предпочтительной, чем та система, которая
теряет часть сообщений в процессе работы при всплесках нагрузки.
В большинстве случаев потери сообщений недопустимы
или крайне нежелательны, поэтому запись сообщений
напрямую в лог-файлы, без дополнительных костылей
через syslog и unix socket`ы практически всегда
будет более предпочительным вариантом.
Тем более, что работающее решение для ротации логов nginx
при 200-250 тысячах подключений в секунду и интервале ротации
раз в 30 секунд можно очень легко получить, заменив SIGHUP на SIGUSR1.
Это есть ответ на тот Ваш вопрос о решении Вашей настоящей проблемы X,
который приведен в самом начале этого сообщения.
> Итоги разных экспериментов:
> Исходные данные - CPU Xeon E5-26xx v4 CPU 2.2GHz
> Для наглядности привожу данные по 1 вычислительному ядру.
> Итак, на 1 вычислительное ядро
> --- Существующий на данный момент бекэнд, куда nginx у меня проксирует запросы -- максимум около 2000 в секунду на одно ядро (вообще не моя епархия, но там точно НЕ php).
> --- NGINX для теста, на который отзеркалированы запросы, вся его функция -- выдать ответ "200" и сообщение в лог записать, все, никакого проксирования или отдачи контента,
> никаких вычислений и т.д. Голый "200" + строка в лог-файле средствами nginx-а, ротация 10 секунд с удалением результата. --- максимум примерно 10 000 в секунду на 1 ядро
> --- парсинг данных из лога, накопленного за 60 секунд из расчета нагрузки 400тыс/сек, т.е. 24млн строк. -- на одном ядре от 8 минут. в зависимости от нагрузки на дисковую подсистему 8-9 минут. т.е. при среднем 500секунд 48 000 в секунду на одно ядро.
> --- Обработка через юникс-сокет "на лету" python3.9 скриптом -- 43 000 в секунду на одно ядро 100% соответствие результатов, около 89-92% занятость ядра CPU.
>
> Итого технически "самый быстрый" -- парсинг лога, но тянет за собой запись-чтение-удаление при относительном преимуществе 9-12% и
> зависимости результата от файлового ввода-вывода.
парсинг лога не только самый быстрый, он еще и самый надежный,
потому что в этом варианте нет потери сообщений. - Собственно,
о чем я Вам и говорил, что это есть самый оптимальный вариант.
нагрузку на сеть можно уменьшить, включив HTTP/1.1 и keepalive
при подключении к backend`у - это если делать обработку логов
именно через mirror на специально выделенный для этой задачи сервер.
Вы же не рассмотрели вариант, когда nginx сам пишет логи напрямую
в файл, например, блоками по 1 мегабайту, делая всего один системный
вызов для записи одного такого блока информации. Насколько
я понимаю, при N рабочих процессах nginx для этого потребуется
дополнительно всего лишь только N мегабайт оперативной памяти.
Но в результате - получим значительное уменьшение расходования
процессора на запись логов и значительно меньшее количество
операций переключения контекста, ведь по умолчанию вызывается
операция записи для каждой строчки лога.
> Таким образом единственный сколь-нибудь существенный бонус - потенциальная полнота данных для обработки перестает быть существенным, когда считаем
> усредненные данные на миллионных выборках.
полнота даных для обработки - как правило это важно.
если Вам нужны усредненные данные на милионных выборках -
тогда с технической точки зрения, самым оптимальным вариантом
будет написать модуль для nginx, который будет делать эту работу
на лету и практически мгновенно и практически с 0 затратами ресурсов.
> Не знаю насколько эффективен будет Go.
Go создан достаточно умными людьми,
такими как Роб Пайк, один из создателей кодировки UTF-8.
Go позволяет сделать concurrency используя goroutines и channels,
и этот язык программирования, созданный в Google практически
идеально подходит для работы в состоянии высоких нагрузок,
позволяя быстро писать быстрый, качественный и надежный код,
который легко справляться даже с очень высокими нагрузками.
Если производиельности которую дает Go будет не хватать,
тогда остается только Rust, C++ и C, но обычно - дешевле
и проще будет просто горизонтальное масштабирование,
путем увеличения количества серверов для вебсайта.
Если нет highload, тогда удобнее и приятнее Python,
и скорость написания кода будет выше, но скорость
работы кода будет ниже - вот такой тут trade-off.
> Он должен на порядок превосходить какой-нибудь php
Он превосходит. Поэтому практически весь highload делают
сейчас именно на Go а не на PHP, если есть возможность выбора
и нет необходимости работать с большим количеством legacy кода.
--
Best regards,
Gena
Подробная информация о списке рассылки nginx-ru