10:40カテゴリ:nginxnginxの記事を書くのは久しぶりの滝澤です。Object)(DSO)のような機能が欲しいと思っていた人も多いでしょう。秘伝のタレのようなビルド用のスクリプト(実際はRPMパッケージのSPECファイル)を保守し続けるのは辛いなと思っていました。そのような方々に朗報です。Modules)がサポートされました。ServerのDSOと比べると、現時点ではまだ制約があります。本記事ではnginx-1.9.11における動的モジュールの説明と制約について説明します。2017年2月22日にフォローアップ記事「nginxの動的モジュールの最新状況(2017年2月版)」を公開しましたのでこちらもご覧ください。動的モジュールnginxは多数のモジュールから構成されており、nginxをビルドするときにモジュールがnginxバイナリに静的に組み込まれます。追加したいモジュールがあるときにも、同様にnginxのビルド時にそのモジュールを指定することによりnginxバイナリにそのモジュールが静的に組み込まれます。このようにnginxのモジュールを追加したり変更したりするたびにnginxバイナリ自体をビルドし直す必要があり、運用が煩雑でした。nginx-1.9.11で動的モジュールがサポートされ、動的モジュールを利用時(nginxの起動時やリロード時)に組み込むことができるようになりました。次のように、設定ファイルにload_moduleディレクティブの値として動的モジュールの共有オブジェクトファイルのパスを指定して、nginxを起動あるいはリロードすると動的モジュールを利用できるようになります。"modules/foo_module.so";nginxの標準モジュールすべてが動的モジュールとして利用できるわけではありません。現バージョンでは次のモジュールが動的モジュールとして利用することができます。(ngx_stream_module)また、サードパーティモジュールも動的モジュールとして利用可能になりますが、configスクリプトの修正が必要となるため、動的モジュールへの対応をサポートしているモジュール以外はそのままでは利用できません。設定ファイルへの記述方法について説明します。動的モジュールを読み込ませるためには、設定ファイルにload_moduleディレクティブの値に動的モジュールの共有オブジェクトファイルのパスを指定します。"modules/ngx_stream_module.so";load_moduleディレクティブの記述場所はmainコンテキストです。mail)より前に記述する必要があります。動かない例も示します。次のようにeventsブロックより後にload_moduleディレクティブを記述したとします。{以下略この場合は、次のようなメッセージが出力され、動きません。現バージョンでは動的モジュール単体だけをビルドすることはできません。動的モジュールをビルドするためには、nginxバイナリをビルドする手順とほぼ同じ手順を行う必要があります。将来のバージョンではモジュール単体をビルドできるようにする計画があるようです。compiled.configureスクリプトのオプションまず、configureスクリプトの実行時にいくつかオプションを指定します。configureスクリプトの動的モジュール関連のオプションとしては次のようなものがあります。moduleそれぞれ見ていきましょう。動的モジュールのインストール先の指定--modules-pathの値に動的モジュールの共有オブジェクトファイルをインストールするパスを指定します。デフォルトでは--prefixで指定したディレクトリ下のmodulesディレクトリになります。--modules-path=PATH/usr/local/nginx/modulesにインストールする場合は次のように指定します。--modules-path=/usr/local/nginx/modules動的モジュールの指定(標準モジュールの場合)nginxの標準モジュールの場合はオプションの値に"dynamic"を指定します。--with-stream=dynamic動的モジュールの指定(サードパーティモジュールの場合)サードパーティモジュールの場合は--add-dynamic-moduleの値にそのソースコードのディレクトリを指定します。--add-dynamic-module=/path/to/foo_moduleconfigureスクリプトの実行configureスクリプトのオプションの指定が完了したら、実行します。threads以下略configureスクリプトの実行が成功したら、makeを実行してnginxバイナリと一緒にビルドします。makeが完了するとobjsディレクトリに動的モジュールが拡張子soの共有オブジェクトのファイルとして生成されます。installを実行すると、nginxバイナリはsbinディレクトリに、動的モジュールはmodulesディレクトリにコピーされます。/usr/local/nginx/{sbin,modules}/usr/local/nginx/modules:foo_module.songx_stream_module.so/usr/local/nginx/sbin:nginxなお、すでに同じ環境でビルドされたnginxバイナリがインストール済みの場合は、objsディレクトリに生成された動的モジュールのファイルをmodulesディレクトリに手動で配置しても利用できます。/usr/local/nginx/modules/ただし、ビルド環境のライブラリとAPIの有無およびビルドオプションが異なる場合は、後述するsignatureの問題でうまく動かないこともあります。上述した内容にも制約がありますが、以下に述べるような制約もあります。nginxバイナリとモジュールのバージョンが異なると動作しないnginxバイナリとモジュールのバージョンが異なると動作しません。これは、nginxバイナリだけバージョンアップして、動的モジュールはそのままのバージョンの場合は、バージョンが異なるため動作しなくなるということになります。このことについて説明します。nginxのビルド時に、nginxバイナリおよび各モジュールのバイナリにバージョン番号から生成される整数値が埋め込まれます。nginx-1.9.11の場合は"1009011"になります。nginxはモジュールの追加時にモジュールのバージョン番号の整数値がnginxバイナリが持っているものと同じかを確認します。異なる場合は次のようなメッセージが出力されます。/usr/local/nginx/conf/nginx.conf:8なお、バージョン番号の整数値はソースコードsrc/core/nginx.h内のnginx_versionに定義されています。nginxバイナリとモジュールのsignatureが異なると動作しないnginxバイナリと異なる環境でビルドされた動的モジュールを組み合わせて動かすことはできません。これにより困ることの例としては、公式サイトやディストリビューションからnginxのRPMパッケージをインストールした環境に、その環境でビルドした動的モジュールを利用することができません。このことについて説明します。nginxのビルド時に、ビルド環境のライブラリとAPIの有無およびビルドオプションからsignatureの文字列が生成され、nginxバイナリおよび各モジュールのバイナリに埋め込まれます。X86_64)のnginx-1.9.11のnginxバイナリのsignatureの文字列は次のようになっています。8,4,8,001011111101001111111111110110111nginxはモジュールの追加時にモジュールのsignatureがnginxバイナリが持っているものと同じかを確認します。signatureが異なる場合は次のようなメッセージが出力されます。/etc/nginx/nginx.conf:8そのため、nginxバイナリと異なる環境でビルドされたモジュールを組み合わせて動かすことは基本的にはできません。ビルド環境のライブラリとAPIの有無およびビルドオプションがすべて同じであればsignatureも同じになるため、この場合は動作します。開発者向けのメーリングリストでもsignatureの問題は提起されているため、将来、何らかの改善が行われると思われます。signatureがどのような条件で構成されているかを確認してみたい方は、ソースコードsrc/core/ngx_module.h内のNGX_MODULE_SIGNATUREの定義を見てみてください。2017年2月22日にフォローアップ記事「nginxの動的モジュールの最新状況(2017年2月版)」を公開しましたのでこちらもご覧ください。株式会社ハートビーツの技術情報やイベント情報などをお届けする公式ブログです。こちら「みんな仲良く」「プライドを持って」「変化を楽しむ」という企業理念に共感していただけるエンジニアを募集しています。