9 февраля состоялся выпуск nginx 1.91.11 с долгожданной поддержкой динамических модулей, которую анонсировали разработчики nginx на Хабре в апреле 2015 г.
Список изменений
Динамические модули компилируются как отдельные файлы .so и подгружаются в процессе работы nginx, в любой момент. Не нужно заново компилировать nginx каждый раз при добавлении модуля.
В документации сказано, что не каждый статичный модуль можно конвертировать в динамический. Не следует делать такую конвертацию для модулей, которые патчат исходный код nginx, они не будут работать. И рекомендуют использовать только те вызовы API, которые непосредственно предназначены для модулей.
Вдобавок, если модули должны были устанавливаться в определённом порядке, то для динамических модулей нужно будет указать значение
API остались одинаковыми как для оригинальных статичных модулей, так и для динамических.
Появилась новая опция в конфиге для добавления модуля в качестве динамического. Вместо использования
После компиляции будет создан бинарный модуль в файле
Модули можно загружать в nginx с помощью новой директивы
По умолчанию установлен максимальный лимит в 128 одновременно загружаемых динамических модулей. Это значение можно изменить в переменной
Ниже пример конфига в старом стиле для стороннего модуля ngx_http_response_module:
Теперь для настройки многих вещей используется скрипт сборки
Как видим, в него включён старый файл
Более подробно о новом формате конфига см. здесь.
Наконец, в документации nginx приводится пример сложносоставного модуля, которые в реальности вмещают несколько модулей в одном пакете. Их немного сложнее конвертировать. Такие модули придётся разбить на несколько модулей при компиляции в качестве статичных модулей, но можно оставить единым файлом
Результат преобразования выглядит следующим образом:
Значение
P.S. Кстати, один из форков Tengine изначально поддерживал динамические модули, для этого он и создавался, потому что фича очень нужная.
Список изменений
- Добавление: теперь 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 изначально поддерживал динамические модули, для этого он и создавался, потому что фича очень нужная.