Вышел Nginx 1.9.11 с поддержкой динамических модулей

b4d4f213c23d4b148f8acacbb9b60413.png9 февраля состоялся выпуск nginx 1.91.11 с долгожданной поддержкой динамических модулей, которую анонсировали разработчики nginx на Хабре в апреле 2015 г.

Список изменений

  • Добавление: теперь resolver поддерживает TCP.
  • Добавление: динамические модули.
  • Исправление: при использовании HTTP/2 переменная $request_length не учитывала размер заголовков запроса.
  • Исправление: в модуле ngx_http_v2_module.


Динамические модули компилируются как отдельные файлы .so и подгружаются в процессе работы nginx, в любой момент. Не нужно заново компилировать nginx каждый раз при добавлении модуля.

В документации сказано, что не каждый статичный модуль можно конвертировать в динамический. Не следует делать такую конвертацию для модулей, которые патчат исходный код nginx, они не будут работать. И рекомендуют использовать только те вызовы API, которые непосредственно предназначены для модулей.
Вдобавок, если модули должны были устанавливаться в определённом порядке, то для динамических модулей нужно будет указать значение ngx_module_order.

API остались одинаковыми как для оригинальных статичных модулей, так и для динамических.

Компиляция динамического модуля


Появилась новая опция в конфиге для добавления модуля в качестве динамического. Вместо использования --add-module пишем --add-dynamic-module. Например:

$ ./configure --add-dynamic-module=/opt/source/ngx_my_module/


После компиляции будет создан бинарный модуль в файле .so (Shared Object). Этот файл затем переносится в поддиректорию modules в папке установки nginx.

589f5f48659243f0a2dc8c91a53f8362.png

Загрузка динамического модуля


Модули можно загружать в nginx с помощью новой директивы load_module. Например:

load_module modules/ngx_my_module.so;


По умолчанию установлен максимальный лимит в 128 одновременно загружаемых динамических модулей. Это значение можно изменить в переменной NGX_MAX_DYNAMIC_MODULES в исходном коде nginx.

Преобразование конфигурационного файла


Ниже пример конфига в старом стиле для стороннего модуля ngx_http_response_module:

ngx_addon_name=ngx_http_response_module
HTTP_MODULES="$HTTP_MODULES ngx_http_response_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_response_module.c"


Теперь для настройки многих вещей используется скрипт сборки auto/module, так что новые конфиги подходят и для статичных, и для динамических модулей. Для того же ngx_http_response_module будет выглядеть следующим образом:

ngx_addon_name=ngx_http_response_module

if test -n "$ngx_module_link"; then
    ngx_module_type=HTTP
    ngx_module_name=ngx_http_response_module
    ngx_module_incs=
    ngx_module_deps=
    ngx_module_srcs="$ngx_addon_dir/ngx_http_response_module.c"
    ngx_module_libs=

    . auto/module
else
    HTTP_MODULES="$HTTP_MODULES ngx_http_response_module"
    NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_response_module.c"
fi


Как видим, в него включён старый файл config, поэтому старые версии nginx будут совместимы с этим модулем.

Более подробно о новом формате конфига см. здесь.

Пример сложного модуля


Наконец, в документации nginx приводится пример сложносоставного модуля, которые в реальности вмещают несколько модулей в одном пакете. Их немного сложнее конвертировать. Такие модули придётся разбить на несколько модулей при компиляции в качестве статичных модулей, но можно оставить единым файлом .so при компиляции в качестве динамических модулей. Вот пример модуля ngx_rtmp_module, который содержит модули CORE и HTTP.

Результат преобразования выглядит следующим образом:

ngx_addon_name="ngx_rtmp_module"
RTMP_CORE_MODULES="                                         \
                ngx_rtmp_module                             \
                ngx_rtmp_core_module                        \
                ngx_rtmp_cmd_module                         \
                ngx_rtmp_codec_module                       \
                ngx_rtmp_access_module                      \
                ngx_rtmp_record_module                      \
                ngx_rtmp_live_module                        \
                ngx_rtmp_play_module                        \
                ngx_rtmp_flv_module                         \
                ngx_rtmp_mp4_module                         \
                ngx_rtmp_netcall_module                     \
                ngx_rtmp_relay_module                       \
                ngx_rtmp_exec_module                        \
                ngx_rtmp_auto_push_module                   \
                ngx_rtmp_notify_module                      \
                ngx_rtmp_log_module                         \
                ngx_rtmp_limit_module                       \
                ngx_rtmp_hls_module                         \
                ngx_rtmp_dash_module                        \
                "
RTMP_HTTP_MODULES="                                         \
                ngx_rtmp_stat_module                        \
                ngx_rtmp_control_module                     \
                "
RTMP_DEPS="                                                 \
                $ngx_addon_dir/ngx_rtmp_amf.h               \
                $ngx_addon_dir/ngx_rtmp_bandwidth.h         \
                $ngx_addon_dir/ngx_rtmp_cmd_module.h        \
                $ngx_addon_dir/ngx_rtmp_codec_module.h      \
                $ngx_addon_dir/ngx_rtmp_eval.h              \
                $ngx_addon_dir/ngx_rtmp.h                   \
                $ngx_addon_dir/ngx_rtmp_version.h           \
                $ngx_addon_dir/ngx_rtmp_live_module.h       \
                $ngx_addon_dir/ngx_rtmp_netcall_module.h    \
                $ngx_addon_dir/ngx_rtmp_play_module.h       \
                $ngx_addon_dir/ngx_rtmp_record_module.h     \
                $ngx_addon_dir/ngx_rtmp_relay_module.h      \
                $ngx_addon_dir/ngx_rtmp_streams.h           \
                $ngx_addon_dir/ngx_rtmp_bitop.h             \
                $ngx_addon_dir/ngx_rtmp_proxy_protocol.h    \
                $ngx_addon_dir/hls/ngx_rtmp_mpegts.h        \
                $ngx_addon_dir/dash/ngx_rtmp_mp4.h          \
                "
RTMP_CORE_SRCS="                                            \
                $ngx_addon_dir/ngx_rtmp.c                   \
                $ngx_addon_dir/ngx_rtmp_init.c              \
                $ngx_addon_dir/ngx_rtmp_handshake.c         \
                $ngx_addon_dir/ngx_rtmp_handler.c           \
                $ngx_addon_dir/ngx_rtmp_amf.c               \
                $ngx_addon_dir/ngx_rtmp_send.c              \
                $ngx_addon_dir/ngx_rtmp_shared.c            \
                $ngx_addon_dir/ngx_rtmp_eval.c              \
                $ngx_addon_dir/ngx_rtmp_receive.c           \
                $ngx_addon_dir/ngx_rtmp_core_module.c       \
                $ngx_addon_dir/ngx_rtmp_cmd_module.c        \
                $ngx_addon_dir/ngx_rtmp_codec_module.c      \
                $ngx_addon_dir/ngx_rtmp_access_module.c     \
                $ngx_addon_dir/ngx_rtmp_record_module.c     \
                $ngx_addon_dir/ngx_rtmp_live_module.c       \
                $ngx_addon_dir/ngx_rtmp_play_module.c       \
                $ngx_addon_dir/ngx_rtmp_flv_module.c        \
                $ngx_addon_dir/ngx_rtmp_mp4_module.c        \
                $ngx_addon_dir/ngx_rtmp_netcall_module.c    \
                $ngx_addon_dir/ngx_rtmp_relay_module.c      \
                $ngx_addon_dir/ngx_rtmp_bandwidth.c         \
                $ngx_addon_dir/ngx_rtmp_exec_module.c       \
                $ngx_addon_dir/ngx_rtmp_auto_push_module.c  \
                $ngx_addon_dir/ngx_rtmp_notify_module.c     \
                $ngx_addon_dir/ngx_rtmp_log_module.c        \
                $ngx_addon_dir/ngx_rtmp_limit_module.c      \
                $ngx_addon_dir/ngx_rtmp_bitop.c             \
                $ngx_addon_dir/ngx_rtmp_proxy_protocol.c    \
                $ngx_addon_dir/hls/ngx_rtmp_hls_module.c    \
                $ngx_addon_dir/dash/ngx_rtmp_dash_module.c  \
                $ngx_addon_dir/hls/ngx_rtmp_mpegts.c        \
                $ngx_addon_dir/dash/ngx_rtmp_mp4.c          \
                "
RTMP_HTTP_SRCS="                                            \
                $ngx_addon_dir/ngx_rtmp_stat_module.c       \
                $ngx_addon_dir/ngx_rtmp_control_module.c    \
                "
ngx_module_incs=$ngx_addon_dir
ngx_module_deps=$RTMP_DEPS
ngx_module_libs=

if [ $ngx_module_link = DYNAMIC ] ; then
    ngx_module_name="$RTMP_CORE_MODULES $RTMP_HTTP_MODULES"
    ngx_module_srcs="$RTMP_CORE_SRCS $RTMP_HTTP_SRCS"
    . auto/module
elif [ $ngx_module_link = YES ] ; then
    ngx_module_type=CORE
    ngx_module_name=$RTMP_CORE_MODULES
    ngx_module_srcs=$RTMP_CORE_SRCS
    . auto/module
    ngx_module_type=HTTP
    ngx_module_name=$RTMP_HTTP_MODULES
    ngx_module_incs=
    ngx_module_deps=
    ngx_module_srcs=$RTMP_HTTP_SRCS
    . auto/module
fi

USE_OPENSSL=YES


Значение $ngx_module_link установлено DYNAMIC для динамического модуля и YES для статического модуля. Во втором случае скрипт сборки auto/module вызывается дважды.

P.S. Кстати, один из форков Tengine изначально поддерживал динамические модули, для этого он и создавался, потому что фича очень нужная.

© Habrahabr.ru