nginxのdynamic modules

http://nginx.org/en/CHANGES

以前から本家のブログ等でもアナウンスされていたnginxのモジュールの動的組み込みの仕組みが先日リリースされた1.9.11で入りました。昨年のnginx.confでも中の人による[Dynamic Modules Development](https://www.youtube.com/watch?v=KinJfCQ-WzY)という発表がありましたが、ほぼこちらに沿う形で導入されています。

## 追加されたconfigureオプション

以下はnginx-1.9.10と1.9.11での`configure --help`の差分です。

```diff
--- 1.9.10      2016-02-10 09:47:05.000000000 +0900
+++ 1.9.11      2016-02-10 09:47:18.000000000 +0900
@@ -3,6 +3,7 @@

   --prefix=PATH                      set installation prefix
   --sbin-path=PATH                   set nginx binary pathname
+  --modules-path=PATH                set modules path
   --conf-path=PATH                   set nginx.conf pathname
   --error-log-path=PATH              set error log pathname
   --pid-path=PATH                    set nginx.pid pathname
@@ -31,8 +32,12 @@
   --with-http_realip_module          enable ngx_http_realip_module
   --with-http_addition_module        enable ngx_http_addition_module
   --with-http_xslt_module            enable ngx_http_xslt_module
+  --with-http_xslt_module=dynamic    enable dynamic ngx_http_xslt_module
   --with-http_image_filter_module    enable ngx_http_image_filter_module
+  --with-http_image_filter_module=dynamic
+                                     enable dynamic ngx_http_image_filter_module
   --with-http_geoip_module           enable ngx_http_geoip_module
+  --with-http_geoip_module=dynamic   enable dynamic ngx_http_geoip_module
   --with-http_sub_module             enable ngx_http_sub_module
   --with-http_dav_module             enable ngx_http_dav_module
   --with-http_flv_module             enable ngx_http_flv_module
@@ -98,12 +103,14 @@
   --without-http-cache               disable HTTP cache

   --with-mail                        enable POP3/IMAP4/SMTP proxy module
+  --with-mail=dynamic                enable dynamic POP3/IMAP4/SMTP proxy module
   --with-mail_ssl_module             enable ngx_mail_ssl_module
   --without-mail_pop3_module         disable ngx_mail_pop3_module
   --without-mail_imap_module         disable ngx_mail_imap_module
   --without-mail_smtp_module         disable ngx_mail_smtp_module

   --with-stream                      enable TCP proxy module
+  --with-stream=dynamic              enable dynamic TCP proxy module
   --with-stream_ssl_module           enable ngx_stream_ssl_module
   --without-stream_limit_conn_module disable ngx_stream_limit_conn_module
   --without-stream_access_module     disable ngx_stream_access_module
@@ -117,7 +124,8 @@
   --with-google_perftools_module     enable ngx_google_perftools_module
   --with-cpp_test_module             enable ngx_cpp_test_module

-  --add-module=PATH                  enable an external module
+  --add-module=PATH                  enable external module
+  --add-dynamic-module=PATH          enable dynamic external module

   --with-cc=PATH                     set C compiler pathname
   --with-cpp=PATH                    set C preprocessor pathname
```

まず重要なのが以下の二つのオプション。

 * `--modules-path=PATH` -> 動的モジュールファイル(DSO)の配置パスを指定する
 * `--add-dynamic-module=PATH` -> サードパーティモジュールをDSOとして組み込む

`--modules-path=PATH`はnginxのインストール時に各動的モジュールのDSOファイルをインストールするパスです。デフォルトだと`/usr/local/nginx/modules`にインストールされます。

`--add-dynamic-module=PATH`はサードパーティモジュールを動的に組み込むためのオプションで、元からある`add-module=PATH`とは分けて使う感じですかね。また、nginx.comのwikiにサードパーティモジュールの動的ローディングへの対応方法がまとまっています↓

[Converting Static Modules to Dynamic Modules](https://www.nginx.com/resources/wiki/extending/converting/)


公式のモジュールについては今のところ上記の差分からも分かるように一部のモジュールのみで動的ロードディングが可能になっています。列挙すると以下の5つになります。

```
--with-http_xslt_module=dynamic         enable dynamic ngx_http_xslt_module
--with-http_image_filter_module=dynamic enable dynamic ngx_http_image_filter_module
--with-http_geoip_module=dynamic        enable dynamic ngx_http_geoip_module
--with-mail=dynamic                     enable dynamic POP3/IMAP4/SMTP proxy module
--with-stream=dynamic                   enable dynamic TCP proxy module
```

# streamモジュールを動的ロードする

試しにstreamモジュールを動的ロードしてみましょう。まずはnginx-1.9.11をビルドします。

```
wget http://nginx.org/download/nginx-1.9.11.tar.gz
tar zxvf nginx-1.9.11.tar.gz
cd nginx-1.9.11
./configure --modules-path=/usr/local/nginx/modules --with-stream=dynamic
make
sudo make install
```

上記の手順が完了したら`/usr/local/nginx/modules`に`ngx_stream_module.so`が出来ているはずです。あとはnginx.confに[`load_module`](http://nginx.org/en/docs/ngx_core_module.html#load_module)を使った設定をmainコンテキストに追加します。

```nginx:nginx.conf
load_module /usr/local/nginx/modules/ngx_stream_module.so;
```

ちなみに`load_module`はnginx.confのかなり前の行に書いておかないとnginxが起動しないことがあるので注意しましょう。例えば以下のようにeventsコンテキストの後で`load_module`を利用すると、

```nginx:nginx.conf
events {
    worker_connections 10000;
}

load_module /usr/local/nginx/modules/ngx_stream_module.so;
```

こんな感じで落ちました。

```
nginx: [emerg] "load_module" directive is specified too late in /etc/nginx/nginx.conf:11
```