Расскажу о вчерашних моих изысканиях.
Предыстория: На мудакторе есть один фронтэнд и куча бэкэндов. Все запросы идут на фронтэнд (где стоит nginx), там на сервере большой кэш картинок. То, что нет в кэше картинок и хтмл-страницы отправляются на один из бэкэндов.
Симптомы: время от времени весь nginx подвисает на 1-3 секунды.
Проблема: nginx читает с жёсткого диска данные и из-за сильной пиковой нагрузки на диск его блокирует на время чтения. Вот пример strace:
20:38:49.834933 open("/mnt/ssd/joyreactor/d4/9c/c2a4cb245d73e4c6b348ad8f73769cd4", O_RDONLY|O_NONBLOCK) = 2351
...snip...
20:38:51.883163 pread(2351, "E\244\232\241"..., 32768, 4194650) = 32768
20:39:05.764386 --- SIGALRM (Alarm clock) @ 0 (0) ---
Можно видеть,что файл открывается с флагом O_NONBLOCK - то есть, чтение должно быть не блокирующее. И при запуске этого неблокирующего чтения, тред блокируется на 15 секунд - с 20:38:51 до 20:39:05
Лезу в поиск. Нахожу, что "не блокирующий" в терминах линукса вполне может быть заблокирован на любое количество времени. Он не блокируется от всяких локов. А от сильной нагрузки на хард - вполне себе блокируется. Но есть асинхронное i/o (AIO). Это ахуенно продвинутая вещь и была реализована в линуксе пару лет назад! Позволяет делать запросы к диску полностью без блокировок. Но при этом не используются никакие дисковые кэши. То есть, надо в программе реализовывать всю дисковую подсистему, если хочешь работать с этим AIO. Заебись! Но нахуй такое нужно? Всё просто - эту систему реализовывали прогеры из IBM и Oracle. Они её делали для СУБД. А в СУБД итак дисковая подсистема своя написана и они на хард пишут напрямую.
А теперь самое интересное - во FreeBSD эта фича была реализована по-нормальному с кэшами в версии 4.3. Эта версия была выпущена 20 Апреля 2001 года... и нафиг я 7 лет назад с бзди пересаживался на линукс?!
Предыстория: На мудакторе есть один фронтэнд и куча бэкэндов. Все запросы идут на фронтэнд (где стоит nginx), там на сервере большой кэш картинок. То, что нет в кэше картинок и хтмл-страницы отправляются на один из бэкэндов.
Симптомы: время от времени весь nginx подвисает на 1-3 секунды.
Проблема: nginx читает с жёсткого диска данные и из-за сильной пиковой нагрузки на диск его блокирует на время чтения. Вот пример strace:
20:38:49.834933 open("/mnt/ssd/joyreactor/d4/9c/c2a4cb245d73e4c6b348ad8f73769cd4", O_RDONLY|O_NONBLOCK) = 2351
...snip...
20:38:51.883163 pread(2351, "E\244\232\241"..., 32768, 4194650) = 32768
20:39:05.764386 --- SIGALRM (Alarm clock) @ 0 (0) ---
Можно видеть,что файл открывается с флагом O_NONBLOCK - то есть, чтение должно быть не блокирующее. И при запуске этого неблокирующего чтения, тред блокируется на 15 секунд - с 20:38:51 до 20:39:05
Лезу в поиск. Нахожу, что "не блокирующий" в терминах линукса вполне может быть заблокирован на любое количество времени. Он не блокируется от всяких локов. А от сильной нагрузки на хард - вполне себе блокируется. Но есть асинхронное i/o (AIO). Это ахуенно продвинутая вещь и была реализована в линуксе пару лет назад! Позволяет делать запросы к диску полностью без блокировок. Но при этом не используются никакие дисковые кэши. То есть, надо в программе реализовывать всю дисковую подсистему, если хочешь работать с этим AIO. Заебись! Но нахуй такое нужно? Всё просто - эту систему реализовывали прогеры из IBM и Oracle. Они её делали для СУБД. А в СУБД итак дисковая подсистема своя написана и они на хард пишут напрямую.
А теперь самое интересное - во FreeBSD эта фича была реализована по-нормальному с кэшами в версии 4.3. Эта версия была выпущена 20 Апреля 2001 года... и нафиг я 7 лет назад с бзди пересаживался на линукс?!
Еще на тему
2. Не привлекай к себе внимания
3. Установи линукс
4. Не брейся
5. Не мойся
6. Радуйся стиму на линуксе
7. (Самое важное) Найди одного из нас и устрой за ним слежку
я бы предложил cdn, но это наверняка выбивается за пределы бюджетов =)
Описал бы полноценно, какие нагрузки, размеры кешей, что за железо. Всегда интересно было, как реактор устроен.
Ну и задай себе вопрос зачем один сервер, задача которого просто роутить запросы еще и кешем занимается, ага.
Когда никакой сервак, за разумную цену, и это не будет выдерживать, будешь искать балансировщик на базе ДНС.
про бсд вполне может сказать, но у него бузинесс и данная проблема не думаю, что она одиночная.
У меня какое-то хреновое чувство, что что-то не так с настройкой.
При таких крешах, ОЗУ забита полностью?
Ну и очевидное решение из этого - делим nginx на две части. Одна роутит всё без использования хардов. Вторая - отдаёт кэш с хардов. Вторая может подвисать - ну и фиг с ней, если картинки немного дольше будут загружаться никто не заметит =).
Ну и тюнинг ФС и ОС пора делать
ssd используется для кэша первого уровня.
ещё предложения, кэп? =)
А ssd уже сейчас стоят достаточно дёшево.
Про ссд поищи на хабере была статья амарао, где он поносил дешевые ссд (это те которые ставят обычно в хезнер :йоба:)
И вообще, если статики до 256 гб, то стоит вообще взять пару серваков с таким сумарным объемом ОЗУ и все в память положить.
Статью амарао видел и общался с ним в комментах к другому посту. Его система оценки ссд меня немного удивила - он мерил скорость 4k random write и из-за плохих результатов говорил, что они говно. Возможно ему, как хостеру, правильно оценивать worst case, ибо конечные пользователи - вагинозрячие дурачки. Но я балансирую так, чтобы запись на ссд буфферизовалась. Зная как работает ссд можно легко понять, что 4k random write быстро убьют его.
У меня ссд замечательно работает. Хотя тюнил его достаточно долго - везде написанно, как делать элементарые вещи и очень сложно найти инфу по тонкой настройке. Сейчас по соотношению цена/скорость чтения ссд явно первый.
Всей статики сильно больше 256Гб. Да и сервера с 256Гб памяти будут очень не мало стоить. Я думаю хранить самые частоиспользуемые картинки в 1Гб кэша в памяти - туда попадёт то, что на главную вышло за день-два. А длинный хвост пусть дальше отдаётся с ссд+хдд
Первый запрос начинает читать диск и блочит нафиг весь тред. Остальные 9 запросов зависают, пока тред не разблочится.
1) как ты в nginx вынесешь чтение диска в отдельный тред?
2) если каждое чтение выносить в тред - может случится пипец. Ибо чтений очень дофига и много чтений попадают в файловый кэш, который отдастся моментально из памяти.
Для этого и существует aio.
Если апачем отдавать картинки, то всё умрёт крайне быстро.
Выше уже согласились, что самым правильным будет nginx разделить на две части - одна только роутит запросы, а вторая - отдаёт статику с диска.
2. poll/select/epoll_wait
.... ждём....
3. -> readable
... м.б. опять ждём....
4. pread (xxx)