OpenResty背后的子项目
API7.ai
September 12, 2022
nginx.conf
からLuaコードを抽出し、読みやすく保守可能な状態に保つにはどうすればよいでしょうか?その解決策は非常にシンプルです。OpenRestyを使ってこれを実装する方法を見てみましょう。
まず、lua
というディレクトリを作成します。そして、すべての.lua
ファイルをその中に配置します。
$ mkdir lua
$ cat lua/hello.lua
ngx.say("hello, world")
次に、nginx.conf
ファイル内のcontent_by_lua_file
をcontent_by_lua_block
に置き換えます。
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location / {
content_by_lua_file lua/hello.lua;
}
}
}
最後に、OpenRestyのサービスを再起動して完了です!
$ sudo kill -HUP `cat logs/nginx.pid`
content_by_lua_file
を使用することで、nginx.conf
を更新する代わりにLuaファイルを直接更新できます。しかし、いくつかの疑問が生じます:
content_by_lua_file lua/hello.lua
セクションで相対パスを使用していますが、OpenRestyは実際のLuaファイルをどのように見つけるのでしょうか?- Luaコードを変更した後、OpenRestyを再起動して反映させる必要がありますが、効率的にデバッグする方法はあるのでしょうか?
- Luaファイルを含むディレクトリをOpenRestyの検索パスに追加するにはどうすればよいでしょうか?
これらの疑問について考えることをお勧めします。これらはすべて公式ドキュメントで回答できます。そのため、私は常にドキュメントの重要性を強調しています。
最初の質問について、相対パスが指定されている場合、OpenRestyが起動する際に、OpenRestyの起動コマンドライン引数にある-p PATH
をプレフィックスとして相対パスを絶対パスに連結します。これにより、OpenRestyはLuaファイルをスムーズに見つけることができます。
2番目の問題は、Luaコードが最初のリクエスト時にロードされ、デフォルトでキャッシュされることです。そのため、Luaソースファイルを変更するたびに、OpenRestyをリロードして反映させる必要があります。nginx.conf
でlua_code_cache
をオフにすることで、リロードを回避できます。ただし、この方法は開発とデバッグのためだけに一時的に使用する必要があります。本番環境でデプロイする場合は、必ずキャッシュを有効にしてください。そうしないと、パフォーマンスに大きな影響を与えます。
最後の質問について、OpenRestyはLuaモジュールの検索パスを設定するためのlua_package_path
ディレクティブを提供しています。例えば、lua_package_path
を$prefix/lua/?.lua;;
に設定できます:
$prefix
は起動パラメータの-p PATH
です。/lua/?.lua
は、.lua
サフィックスを持つLuaディレクトリ内のすべてのファイルを示します。- 最後の2つのセミコロンは、組み込みのコード検索パスを表します。
インストール後のディレクトリ構造
最初のHello Worldプログラムを理解した後、OpenRestyがインストールされた後のディレクトリ構造と、その中に含まれるファイルについて詳しく見ていきましょう。
まず、-V
オプションを渡して、OpenRestyがどこにインストールされているかを確認します。以下の結果では、多くのモジュールコンパイルパラメータを省略していますが、後で追加します:
$ openresty -V
nginx version: openresty/1.13.6.2
built by clang 10.0.0 (clang-1000.10.44.4)
built with OpenSSL 1.1.0h 27 Mar 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/local/Cellar/openresty/1.13.6.2/nginx ...
私はMacでbrewを使ってOpenRestyをインストールしました。パスは/usr/local/Cellar/openresty/1.13.6.2/nginx
で、環境によって異なる場合があります。このパスには、bin
、luajit
、lualib
、nginx
、pod
などのディレクトリが含まれています。これらのフォルダの意味を理解することは、OpenRestyをよりよく学ぶために重要です。それでは、一つずつ見ていきましょう。
まずは重要なbin
ディレクトリです。
$ ll /usr/local/Cellar/openresty/1.13.6.2/bin
total 320
-r-xr-xr-x 1 ming admin 19K 3 27 12:54 md2pod.pl
-r-xr-xr-x 1 ming admin 15K 3 27 12:54 nginx-xml2pod
lrwxr-xr-x 1 ming admin 19B 3 27 12:54 openresty -> ../nginx/sbin/nginx
-r-xr-xr-x 1 ming admin 62K 3 27 12:54 opm
-r-xr-xr-x 1 ming admin 29K 3 27 12:54 resty
-r-xr-xr-x 1 ming admin 15K 3 27 12:54 restydoc
-r-xr-xr-x 1 ming admin 8.3K 3 27 12:54 restydoc-index
これには、前のセクションで説明したOpenResty CLIのresty
と、コア実行ファイルであるopenresty
が含まれています。openresty
は実際にはnginxへのシンボリックリンクです。ディレクトリ内の他のツールは、resty
と同様に、すべてPerlスクリプトです。
その中で、opm
はパッケージ管理ツールで、さまざまなサードパーティパッケージを管理できます。これについては後ほどセクションで説明します。また、restydoc
は、OpenRestyが提供するドキュメントビューアで、OpenRestyとNGINXのドキュメントを閲覧できます。
$ restydoc -s ngx.say
$ restydoc -s proxy_pass
上記の2つの例は、それぞれOpenResty APIとNGINXコマンドを検索しています。restydoc
は、サーバーサイドエンジニアが開発に集中するための非常に役立つツールです。
bin
ディレクトリを閲覧した後、次にpod
ディレクトリに進みます。
まず、ここでのpod
はKubernetesのpodとは関係ありません。代わりに、pod
はPerlモジュールのドキュメントを書くために使用されるマークアップ言語です。このディレクトリには、OpenResty
、NGINX
、lua-resty-*
、LuaJIT
のドキュメントが含まれており、これらは先ほど説明したrestydoc
と結びついています。
次に、おなじみのNGINX
とluajit
ディレクトリです。これらは主にNGINXとLuaJITの実行ファイルと依存関係を格納しており、OpenRestyの基盤です。多くの人がOpenRestyはLuaに基づいていると言いますが、それは正確ではありません。上記で見たように、OpenRestyは実際にはLuaJITに基づいています。
実際、初期段階では、OpenRestyにはLuaとLuaJITの両方が含まれており、コンパイルオプションによってLuaまたはLuaJITを使用するかを決定できました。しかし、Luaは廃止されつつあり、現在はより高性能なLuaJITのみがサポートされています。
最後に、lualib
ディレクトリを見てみましょう。これには、OpenRestyで使用されるLuaライブラリが含まれており、主にngx
とresty
の2つのディレクトリに分かれています。
ngx
ディレクトリには、公式のlua-resty-coreプロジェクトからのLuaコードが含まれており、これはOpenResty APIのFFIベースの再実装です。なぜ再実装が必要なのかについては、後ほど特別な章で説明します。resty
ディレクトリには、さまざまなlua-resty-*
プロジェクトからのLuaコードが含まれており、これについては次に触れます。
このコースの慣例に従い、この時点でこれらのディレクトリのソースを提供します。これはオープンソースプロジェクトの楽しみの一つでもあります。もしあなたが「なぜ?」と追求するのが好きなら、常にさらに興味深いものを見つけることができます。
以下は、CentOS用のOpenRestyのパッケージングスクリプトで、上記のすべてのディレクトリが含まれています。
%files
%defattr(-,root,root,-)
/etc/init.d/%{name}
/usr/bin/%{name}
%{orprefix}/bin/openresty
%{orprefix}/site/lualib/
%{orprefix}/luajit/*
%{orprefix}/lualib/*
%{orprefix}/nginx/html/*
%{orprefix}/nginx/logs/
%{orprefix}/nginx/sbin/*
%{orprefix}/nginx/tapset/*
%config(noreplace) %{orprefix}/nginx/conf/*
%{orprefix}/COPYRIGHT
OpenRestyプロジェクトの概要
OpenRestyと言えば、lua-nginx-module
を思い浮かべるでしょう。確かに、このNGINX CモジュールはOpenRestyのコアですが、OpenRestyと同等ではありません。多くのエンジニアがOpenRestyをngx + lua
と呼んでいますが、これは技術カンファレンスで共有・出版された書籍でも使用されています。これは厳密ではなく、OpenRestyコミュニティでも推奨されていません。
なぜそうなのか、そしてlua-nginx-module
以外にOpenRestyにはどのような関連プロジェクトがあるのかについて説明します。
GitHubでOpenRestyのプロジェクトホームページを開くと、OpenRestyには68の公開プロジェクトがあり、それらはおおよそ以下の7つのカテゴリに分類されます。それぞれを簡単に紹介し、あなたが迅速に学べるようにします。
NGINX Cモジュール
OpenRestyのプロジェクト名は標準化されており、*-nginx-module
という名前のものはNGINX Cモジュールです。
OpenRestyには20以上のCモジュールがあり、このセクションの最初に使用したopenresty -V
でそれらを見つけることができます。
$ openresty -V
nginx version: openresty/1.13.6.2
built by clang 10.0.0 (clang-1000.10.44.4)
built with OpenSSL 1.1.0h 27 Mar 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/local/Cellar/openresty/1.13.6.2/nginx --with-cc-opt='-O2 -I/usr/local/include -I/usr/local/opt/pcre/include -I/usr/local/opt/openresty-openssl/include' --add-module=../ngx_devel_kit-0.3.0 --add-module=../echo-nginx-module-0.61 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.13 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../ngx_stream_lua-0.0.5 --with-ld-opt='-Wl,-rpath,/usr/local/Cellar/openresty/1.13.6.2/luajit/lib -L/usr/local/lib -L/usr/local/opt/pcre/lib -L/usr/local/opt/openresty-openssl/lib' --pid-path=/usr/local/var/run/openresty.pid --lock-path=/usr/local/var/run/openresty.lock --conf-path=/usr/local/etc/openresty/nginx.conf --http-log-path=/usr/local/var/log/nginx/access.log --error-log-path=/usr/local/var/log/nginx/error.log --with-pcre-jit --with-ipv6 --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v2_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_auth_request_module --with-http_secure_link_module --with-http_random_index_module --with-http_geoip_module --with-http_gzip_static_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-threads --with-dtrace-probes --with-stream --with-stream_ssl_module --with-http_ssl_module
ここで--add-module=
の後に続くのはOpenRestyのCモジュールです。コアとなるのはlua-nginx-module
とstream-lua-nginx-module
で、前者はレイヤー7のトラフィックを処理し、後者はレイヤー4のトラフィックを駆動します。
これらのCモジュールの中には、特別な注意が必要で、推奨されていないものもありますが、デフォルトでOpenRestyにコンパイルされています。例えば、redis2-nginx-module
、redis-nginx-module
、memc-nginx-module
は、RedisとMemcachedとの相互運用に使用されます。これらのCライブラリはOpenRestyの初期段階で推奨されていましたが、cosocket機能が追加された後、lua-resty-redis
とlua-resty-memcached
に置き換えられ、現在はメンテナンスされていません。
OpenRestyは今後、より多くのNGINX Cライブラリを開発するのではなく、cosocketベース
のLuaライブラリに焦点を当てる予定です。これが未来です。
lua-resty-* ライブラリ
公式のOpenRestyリポジトリには、18のlua-resty-*
ライブラリが含まれており、Redis、MySQL、Memcached、WebSocket、DNS、トラフィック制御、文字列処理、プロセス内キャッシュなどの標準ライブラリが含まれています。公式のものに加えて、さらに多くのサードパーティライブラリがあります。これらは非常に重要であり、次のセクションでこれらのライブラリについてさらに時間を割きます。
自己管理のLuaJITブランチ
OpenRestyは、独自のOpenSSLパッチに加えて、独自のLuaJITブランチを管理しています。2015年、LuaJITの作者であるMike Pallは、新しいLuaJITのメンテナーを見つけるために引退を発表しましたが、Mikeは適切なメンテナーを見つけることができませんでした。現在は主にバグ修正のメンテナンスを行っており、新機能の開発は停止しています。そのため、OpenRestyは独自のLuaJITブランチを管理しています。
Luaと比較して、LuaJITは多くの重要なユニークな機能を追加していますが、多くのエンジニアがそれらを知らないため、半ば隠れたスキルとなっています。これについては後ほど紹介します。
テストフレームワーク
OpenRestyのテストフレームワークはtest-nginxで、Perlで開発されています。名前からわかるように、これはNGINX関連のプロジェクトをテストするために特別に設計されています。OpenRestyの公式テストケースは、Cモジュールとlua-resty
ライブラリのすべてがtest-nginx
によって駆動されています。これは、一般的なアサーションベースのフレームワークとは異なり、はるかに強力で独立したシステムです。
一部のOpenRestyの貢献者もこのテストフレームワークを理解しておらず、複雑なCおよびLuaコードを含むPRを提出することがありますが、それに対応するテストケースを書くことにまだ恐れを感じています。そのため、OpenRestyプロジェクトの/t
ディレクトリ内のテストケースを見てまだ混乱している場合は、自分を疑わないでください。ほとんどの人は同じです。
test-nginx
に加えて、mockeagainプロジェクトは、低速なネットワークをシミュレートし、プログラムが1バイトずつ読み書きできるようにします。これはウェブサーバーにとって非常に便利なツールです。
デバッグツールチェーン
OpenRestyプロジェクトは、科学的かつ動的にコードをデバッグする方法に多くの努力を費やしています。
OpenRestyの2つのプロジェクト、openresty-systemtap-toolkitとstapxxは、systemtap
という動的デバッグおよびトレーシングツールに基づいています。systemtap
を使用する最大の利点は、ターゲットアプリケーションに対して完全に非侵襲的でありながら、生体内分析を可能にすることです。
例えば、systemtap
は病院に行ってCTスキャンを受けるようなもので、痛みもなく、知覚もありません。さらに良いことに、systemtap
はパフォーマンス分析のための視覚的なフレームグラフを生成できます。これについては後ほど説明しますが、ここではフレームグラフを見て感覚をつかんでください。
パッケージ
OpenRestyのパッケージングスクリプトは、さまざまなディストリビューションオペレーティングシステム(CentOS、Ubuntu、macOSなど)で手書きされており、より満足のいく制御性を実現しています。インストール後のディレクトリ構造を紹介した際に、これらのパッケージ関連のプロジェクト:openresty-packagingとhome-brewについてすでに説明しました。これに興味がある場合は、自分で学んでください。ここでは繰り返しません。
エンジニアリングツール
これらの大きなプロジェクトに加えて、OpenRestyにはいくつかのエンジニアリングツールがあり、ほとんどが隠されています。
例えば、openresty-devel-utilsは、OpenRestyとNGINXを開発するためのツールセットです。もちろん、これらもPerlで開発されており、ほとんどのツールはドキュメント化されていません。しかし、OpenResty開発者にとって、これらのツールは非常に便利です。いくつかを選んで簡単に紹介します。
- lj-relengは、シンプルで効果的なLuaJITコード検査ツールで、
luacheck
に似ており、グローバル変数の潜在的な問題を見つけることができます。 - reindexは、インデックスを再構築することを意味し、
test-nginx
テストケースをフォーマットし、テストケース番号を再配置し、余分な空白を削除するツールです。reindex
は、OpenResty開発者が毎日使用するツールの一つです。 - opsboyは、自動化されたデプロイメントを行うために使用されます。OpenRestyが各リリース前にAWS EC2クラスタで行う回帰テストをデプロイおよび駆動するために使用されます。詳細については、公式ドキュメントを参照してください。
opsboy
はPerlで実装されたDSLです。OpenRestyの作者は、問題を解決するためにさまざまなDSLを作成するのが好きです。
まとめ
今日は、OpenRestyのインストール後のディレクトリ構造と、その背後にあるいくつかのサブプロジェクトについて主に学びました。今日の内容を学んだ後、OpenRestyのプロジェクトについてさらに理解を深めてほしいと思います。OpenRestyは、NGINXのロードバランシングとリバースプロキシの範囲をはるかに超え、独自のエコシステムを実現しています。次回はこれについて詳しく話します。