9 февраля состоялся выпуск 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.



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


Модули можно загружать в 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 изначально поддерживал динамические модули, для этого он и создавался, потому что фича очень нужная.

Комментарии (19)