Файловый AIO в nginx

    В последних версиях nginx (начиная с 0.8.11) появилась поддержка асинхронного файлового ввода-вывода. Потенциально, эта фича способна устранить одно из узких мест веб-сервера — полную блокировку процесса при файловом IO.

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

    Раньше, эта проблема решалась увеличением количества процессов-воркеров. Теперь есть альтернативное решение. :) Однако, перед тем, как включать файловый AIO, стоит учесть ряд нюансов.

    Во-первых, хочу обратить ваше внимание, что не стоит ожидать от новых версий значительного увеличения производительности. Это возможно только при очень специфической нагрузке — когда один и тот же сервер одновременно отдаёт несколько небольших статических файлов, и очень большое количество больших файлов.

    Во-вторых, файловый AIO работает только на FreeBSD 4.3 и выше, либо в Linux, с версии ядра 2.6.22 и выше.

    В-третьих, AIO во FreeBSD имеет смысл включать только в версиях FreeBSD-6.4 STABLE, FreeBSD 7, или новее. В более ранних версиях, при включении AIO, сетевая подсистема начинает использовать Giant Lock, что означает невозможность одновременного выполнения какого-то другого системного вызова. Другими словами, почти никаких выгод от асинхронности мы не получим.

    Ну и наконец, при использовании AIO под Linux надо также включать directio. Также, если я всё понял правильно, в линукс пока невозможно использовать AIO для подгрузки данных для sendfile, поскольку включение directio отключит использование sendfile автоматически.

    Если вы по-прежнему считаете, что оно вам нужно, AIO включается очень просто. Для Linux, фрагмент конфига будет выглядеть примерно так:

    aio on; # включаем AIO
    directio 512; # включаем O_DIRECT для файлов, размером 512 байт или больше
    output_buffers 128 512k; # зная размер и примерное количество одновременно отдаваемых файлов, можно подобрать более подходящие значения


    Ссылки:
    Описание AIO в документации на Nginx
    Changelog
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 63

      +2
      Ура! Наконец-то дождались!
        0
        Ага, у меня первая реакция тоже была такая. :) А потом я потестировал новую версию с включенным AIO и без, и немного приуныл. Пользы от файлового AIO на большинстве реальных задач не очень много, реальный выигрыш заметен только при нагрузке, характерной для файл-хостеров, хранилищ фото, видео, и так далее. :)
          0
          Ну так мне для статики и надо
          Фотохостинг на nginx самое оно
            0
            Я попытался потестировать AIO в разных сценариях нагрузки, и с разными настройками, под Linux. Я предположил, что если настроить nginx на отдачу файлов из каталога /usr и подготовить тестовый файл с url-ами для siege, можно получить достаточно похожую на файл-хостинг нагрузку. Включая по-очереди directio, sendfile и aio в разных комбинациях, можно было бы получить довольно интересную табличку результатов…

            Но, дело в том, что тест я проводил на собственном десктопе, где одновременно была запущена целая KDE, так что воспроизводимость результатов теста оказалась… не на высоте. Я надеюсь, у меня когда-нибудь окажется достаточно свободного времени, чтобы провести это же тест в более подходящих условиях. :)
        0
        Отличная это штука — aio_*, роскошные даёт результаты :)
          0
          > Раньше, эта проблема решалась увеличением количества процессов-воркеров. Теперь есть альтернативное решение. :)

          А многопоточности там нет что ли? Тогда AIO в конечном итоге все равно потребует увеличения к-ва процессов-воркеров.
            0
            А вы предлагаете на каждый запрос поток создавать?
              0
              Нет. Вместо процессов-воркеров создавать потоки-воркеры (в Windows например спец-средства для этого есть).

              Кстати, в создании потоков тоже ничего страшного нет. Только не на каждый запрос, а на каждый коннект. В HTTP/1.1 активно используется Keep-Alive (по умолчанию), в одном коннекте к одному сайту могут десятки/сотни http-запросов передаваться. Для небольших сайтов это наиболее экономный режим — если запросов мало, то никакие воркеры память не занимают.
                0
                Это концепции нгинкса противоречит. Да и ресурсы в случае ддоса или 5к онлайна беречь никто не будет
                  0
                  Как бы есть системы, где было около 1 тысячи рабочих процессов.

                  Для linux как-то пофигу, для системы, переключаться между тысячью тредов или тысячью процессов, ибо все есть task.

                  А концепция nginx простая, крути там, где ты думаешь что тормозит.
                    +1
                    Я говорю о том, что уход от создания отдельного потока на каждое соединение — один из столпов нгинкса. А про то чем ворочить системе вопрос не ставлю.
                      0
                      Кстати, я сторонник мысли о том, что один поток на одно соеденение не так уж и плох. Но тут надо тестится :)
                        +1
                        Для этого есть апач и все его воркеры с префорком =)
                          0
                          Какие-то вы категоричные.
                            0
                            Ну вы объясните преимущества применения вашей идеи в нгинксе — может быть перестанем. Пока мой опыт и знания говорят о том что ни к чему хорошему такие реализации в тех сферах где используется нгинкс не приведут
                              0
                              Я пока вижу траты на возвращение fsm в исходное положение, когда, у вас большой pool соеденений то вы можете дешево переключаться между ними.

                              Я не постулирую, надо смотреть и пробовать.
            • UFO just landed and posted this here
                0
                Собственный шедулинг все равно должен как-то накладываться на ядерный (т.к. у ОС другого нет :). И не факт, что два шедулера лучше одного. В винде (начиная с Win2000) есть такая штука как IO completion port, который может использоваться как для асинхронного в/в, так и для создания пула рабочих потоков, т.е. эти вещи в общем случае взаимосвязаны и в системном планировщике.
                  +1
                  Собственный шедулинг гораздо дешевле ядерного, как минимум, по причине многократного сокращения времени на переключение контекстов, и вообще, на вход и выход в режим ядра, и обратно.
                    0
                    А вы уверены что вот в момент T любимая ОС не перестанет обрабатывать ваше бизнес приложение, а начнет на что-то другое, важное, по ее мнению, тратить ресурсы?
                  0
                  Его еще надо правильно написать. И правильно развивать. Но ядерный шедулер не денется никуда. Он всегда может обидеть, так что ой. И что бы не обижал нужны честный rt системы.
                0
                Объясните, а почему aio вообще нужен одновременно с sendfile

                Мне как-то админ объяснял, что sendfile() вообще не работает с чтением «в обычном» виде, это что то ближе к mmap(), но при этом все это происходит в адресном пространстве ядра, причем файл мапится сразу в TCP буфера. И при этом, используется механизм подкачки, а не чтения типа read().

                Что тут не так/что я не понял?
                  +1
                  Потому что sendfile — не асинхронный вызов. При «обычной» передаче данных вы копируете данные сначала из файла, к себе, в адресное пространство процесса, а потом ещё раз — в адресное пространство ядра, когда отправляете их «в сеть». sendfile позволяет избавиться от лишнего копирования в адресное пространство вашего процесса, но вам всё-равно придётся ждать, пока не закончится файловая операция.
                    0
                    В винде вместо sendfile есть аналогичная функция TransmitFile. Так вот она асинхронная, т.е. возвращает управление сразу после вызова, и далее работает где-то в системных воркерах. Т.е. ждать ничего не надо. Знаю точно, использую несколько лет. Для отдачи статических файлов хорошо подходит.
                      0
                      А sendfile в linux не может быть совмещена с aio ибо это самое aio там с боку.
                    0
                    Как давно ждал. Ну что ж, погоняем тесты сегодня :)
                      0
                      А можете потом результаты тестов опубликовать? Было бы очень интересно посмотреть.
                        0
                        Ну, это скорее не тест, а визуальная оценка, у меня как раз есть сервер, раздающий много больших файлов одновременно с маленькими файлами и проксированием на одном nginx. Запустил сейчас, буду смотреть, как жить будет :)
                          0
                          Технически вы должны будете убрать точку блокировки за syscall в work queue aio.

                          А не могли бы вы мне написать? Моя почта/xmpp: catap@catap.ru. У меня сейчас нет под рукой linux машинки на которой я могу провести что-то подобное. Я бы вопросы по задавал…
                            +1
                            Визуально ничего почти не изменилось, меньше тормозов стало, но и появились баги 0.8.14, периодически стал получать 503 без причины, кроме того, nginx скушал всю оперативку (оно и не мудрено, порядка 600 клиентов в онлайне качают, многие в несколько потоков, да еще и 400 человек по сайту бродят), настройки остальные не трогал, оставил только:

                            sendfile on;
                            directio 1m;
                            aio on;
                            output_buffers 1 1m;

                            В итоге load average упал в среднем в 2 раза, iowait чуть меньше стал, сайт открывается резвее. На полную мощность пока проверить не могу, со вчерашнего дня в датацентре перебои с сетью, периодически линк падает :( Пока еще наблюдаю за ситуацией.
                              0
                              Готов потестить на нагруженном сервере под linux или freebsd, только надо уточнить, что именно вы хотите получить в результатах?
                                0
                                Интересен linux. Интересно еще ядра поменять. Готовы? Если да — пишите.
                            0
                            Отрубил пока что aio. Один воркер стал жрать 100% проца, второй периодически падал.
                            Эх, сыровата еще 0.8.x…
                              0
                              Вы бы это, написали мне, мы чего бы придумали.
                                0
                                accept_mutex off;

                                  0
                                  [emerg]: unknown directive «accept_mutex» in /etc/nginx/nginx.conf:67
                                  configuration file /etc/nginx/nginx.conf test failed
                                    0
                                    ты это в event положил?
                            0
                            «Во-вторых, файловый AIO работает только на FreeBSD 4.3 и выше, либо в Linux, с версии ядра 2.6.22 и выше.»
                            Не правда вообще-то. Он работает даже на древней SCO Unix v.5
                            Ну и у его деток. И особенно хорош aio на нормальных дисковых контролерах, а не на [I]diotic [D]isk [E]mulator ;)
                              0
                              Речь в этой фразе идёт именно об Nginx. И я пока не слышал о случаях установки Nginx на SCO Unix.
                                0
                                Извините, но я трактовал эту фразу, что вообще aio доступно на этих ядрах.
                                0
                                22 ядро linux нужно, ибо до, не было eventfd.
                                +1
                                Замечание про:
                                output_buffers 128 512k;

                                Это какое-то странное и очень большое значение. Ведь это же настройка для одного клиента, зачем ему одному 128 буферов по полметра?
                                Для раздачи больших файлов, где от sendfile тормоза (есть у меня такие конфигурации) очень хорошо помогает много памяти на сервере и такая настройка с буферами для клиента:
                                output_buffers 1 2m;
                                  0
                                  Вы правы. Дело в том, что эти значения просто выбраны «от балды», для примера. Конечно, в продакшн не надо такого писать. :)
                                  –5
                                  Пока Nginx AIO не заработает на RHEL/CentOS в линуксе пользы от него мало.
                                    +1
                                    Ну конечно, другие дистрибутивы вообще никто не использует=)
                                      +1
                                      Скорее уж тогда «пока РедХат не слезет с замшелого ядра 2.6.18». Хотя, если вы ставите все пакеты только из репозитория CentOS, то откуда у вас, вообще Nginx? Тем более, новый… :)
                                        –2
                                        Не «замшелое», а стабильное. Стабильное в понимании серьезных серверов, а не десктопов.
                                        Да и собрать самому Nginx это не тоже самое что пересобрать ядро на боевом сервере, работающем годами без ребутов.
                                          0
                                          А одно другому не мешает. 2.6.18 вышло 20 сентября 2006 года, то есть, ему скоро исполнится три года. За это время столько всего произошло… :)

                                          Хотя, я вас, в принципе, понимаю, я сам бы не стал бы трогать ядро на полностью рабочей системе без необходимости. Но это плата за стабильность — задержка в получении bleeding edge-технологий.
                                            +1
                                            Сударь, 2.6.18 от kernel.org и 2.6.18 в RHEL это очень разные ядра. И, RedHat-у, как крупнейшему маинтейнеру ядра, я думаю всё-таки виднее какое ядру лучше подходит к их дистрибутиву.
                                              0
                                              Ну, кстати, возможно, имеет смысл попробовать собрать последний nginx на системе с ядром от РедХат. Они действительно накладывают довольно много патчей, так что всё может и завестись.

                                              Единственное, лучше подождать nginx 0.8.15, потому что в 0.8.14 (последнем на сегодня) уже точно есть как минимум одна ошибка, приводящая в определённых обстоятельствах к сегфолту под линуксом.
                                                +1
                                                На CentOS 5.3 не работает, потому что eventfd2 не портирован. Да и после 0.8.10 до 0.8.12 точно в nginx забавно «работает» keepalive — страницы «залипают». Выключение keepalive не спасает — советую работать на последнем из стабильной ветки 0.7.
                                                  0
                                                  Залипание запросов в 0.8.14 вроде исправили. Хотя, да, под Linux пока лучше использовать версию 0.8.10 или 0.7.61, как минимум, до выхода 0.8.15.
                                      +2
                                      Вы бы добавили фразу из мануала: «Поскольку directio в Linux можно использовать только для чтения блоков, выравненных по 512 байт (или 4К для XFS), то невыравненный конец файла будет читаться блокировано
                                        0
                                        Ну… мне это не показалось уж очень критичным. Время блокировки на чтение одного сектора в 512 байт должно быть достаточно мало, чтобы этого никто не заметил. :)
                                          +1
                                          Для XFS это уже 4КБ.
                                            0
                                            Туда же до кучи «То же относится к запросам части ответа byte-ranges и к запросам FLV не с начала файла: чтение невыровненных начала и конца ответа будет блокирующимся.»

                                            Заметят. Всего-то нужно каждому воркеру уйти в блокирующее чтение пусть даже 512ти байт — запросы приниматься и обрабатываться в это время не будут.
                                        +1
                                        Это черезвучайно итересная фича я думаю. А может кто ни будь ответить на наивный вопрос на пальцах?
                                        для машины раздающей большие статические файлы какие _именно_ радости принесет эта фича? Можно будет ставить меньше воркеров? Уменьшиться нагрузка на CPU? И может быть даже можно надеяться на небольшое увеличении скорости отдачи файлов?
                                          0
                                          Почти никаких радостей, кроме возможного уменьшения количества воркеров. Если производительность отдачи файлов nginx ограничена производительностью жёсткого диска, то, в любом случае, сколько-то заметного ускорения отдачи файлов не будет. Впрочем, я надеюсь ещё провести более тщательный тест. Если найдётся время, напишу об этом отдельный пост.
                                            +1
                                            Спасибо за ответ. просто для лайти (судя по этому посту ) использование AIO дало просто какой то фантастический эффект. Не знаю даже как это объяснить :)
                                              0
                                              Ну, мне кажутся условия теста не совсем честными, но, вообще, интересно. Я постараюсь закончить со своими тестами до конца недели, может быть даже попробую сравнить производительность lighttpd и nginx на одинаковых нагрузках.
                                                0
                                                Оооооо, очень вас прошу! :) Я думаю было бы интересно не только мне.
                                            • UFO just landed and posted this here
                                              0
                                              Эта фича служит только для одного, вынести точки ожидания открытия файла за syscall

                                            Only users with full accounts can post comments. Log in, please.