LuaルールとNGINX設定が競合した場合どうなるか?
API7.ai
October 13, 2022
1. OpenRestyの名前と言語
Q: OpenRestyという名前の由来が今まで理解できていませんでした。また、OpenRestyはLua言語を利用して飛躍していますが、なぜ他のスクリプト言語ではないのでしょうか?例えば、Shellなど。
A: OpenRestyはYahoo!の企業プロジェクトとして2007年10月に始まりました。「Open」という名前はOpenAPIから、「Resty」はrest APIから取られています。当初、OpenRestyはウェブサーバーや開発プラットフォームではなく、ウェブサイトのようなアプリケーションとしての利用を想定していました。
OpenRestyが10年以上前にオープンソース化された当時、同期非ブロッキングをサポートする言語は非常に少なかったです。現在でも、OpenRestyと同等のパフォーマンスを実現できるバックエンド言語は多くありません。現在、多くの開発者がAPIゲートウェイやソフトWAFでOpenRestyを使用しており、これは開発者にとって自然な選択です。
言語に関しては、OpenRestyはNGINXに他の開発言語を組み込む唯一のプロジェクトではありません。例えば、NGINXは公式にJSを組み込んでいますし、PHPをNGINXに組み込むオープンソースプロジェクトもあります。
通常、利用する言語の選択は、並行性、JIT、言語の人気などの要素に基づいています。OpenRestyにとって、2007年当時、Luaは確かに最良の選択でした。OpenRestyは最初のバージョンでLuaではなくperlを選択したことで少し遠回りをしました。
2. 設定の優先順位
Q: OpenRestyのLuaルールとNGINX設定ファイルが競合する場合、例えばNGINXがrewriteルールを設定し、同時にrewrite_by_lua_fileを参照している場合、これらの2つのルールの優先順位はどうなりますか?
A: 実際には、NGINX設定のrewriteルールがどのように書かれているかによります。break
かlast
かによって異なり、これはOpenRestyの公式ドキュメントに記載されています。サンプルコードは以下の通りです:
location /foo {
rewrite ^ /bar;
rewrite_by_lua 'ngx.exit(503)';
}
location /bar {
...
}
このサンプルコードの設定では、ngx.exit(503)
は実行されません。
しかし、以下のように書くと、ngx.exit(503)
が実行されます。
rewrite ^ /bar break.
ただし、私はNGINX設定ではなくOpenRestyを利用してrewriteを行うことをお勧めします。この曖昧さを避けるためです。NGINX設定の多くは比較的難解で、ドキュメントを繰り返し参照して理解する必要があります。
3. なぜ私のコードはエラーを出すのか?
Q: LuaJIT拡張のtable関数で、なぜ以下の2行のコードをLuaJITで実行すると「moudule not found」というエラーが出るのでしょうか?私はLuaJITバージョン2.0.5を使用しています。
local new_tab = require('table.new')
# or
require('table.clear')
# 実行するとエラーが出る
luajit: table_luajit.lua:1: module 'table.new' not found:
A: これらのコードはLuaJITバージョン2.1以上で実行する必要があります。ドキュメントはこちらにあります:https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218。これで確認できます。
前述したように、OpenRestyを使用する際には特定のバージョンのLuaJITが必要です。OpenRestyはLuaJIT 2.1ブランチに基づいており、LuaJITに対して多くの拡張を行っています。
したがって、このコラムのコードを実行する際には、公式のOpenRestyインストールを使用することを忘れないでください。もしNGINXの上にlua-nginx-module
を追加してコンパイルすると、多くの問題に遭遇するでしょう!
4. null値に関する混乱
Q: 私が遭遇した混乱の1つは、ngx.null
、nil
、null
、""
です。ウェブで検索すると、null
はngx.null
の定義であると書かれているのを見ました。Redisが返す際、返された結果がnullかどうかを判断することがよくありますが、判断する際にどの値と比較されるのでしょうか?これらの値の使用に関して他に注意すべき点はありますか?これらの値がよく理解できていません。
A: 質問に答える前に、以下のコードを使用してlua-resty-redis
でキーを検索することをお勧めします。
local res, err = red:get("dog")
これは、Luaのnilはテーブルの値として使用できないため、OpenRestyはテーブル内のnull値としてngx.null
を導入しています。
以下のコードでngx.null
とその型を出力できます。
# ngx.nullを出力
$ resty -e 'print(ngx.null)'
null
# 型を出力
$ resty -e 'print(type(ngx.null))'
userdata
ご覧の通り、ngx.null
はnil
ではなく、userdata
型です。
さらに、OpenRestyには多くのnull値があります。例えば、cjson.null
、cdata:NULL
などです。これらについては後で説明します。
OpenRestyで唯一の偽の値はnil
とfalse
です。したがって、if not res then
のようなコードを書く際には注意が必要で、明示的にif res ~= nil and res ~= false then
のように変更し、対応するテストケースでカバーすることが望ましいです。
5. APIゲートウェイとは何か?
Q: 記事で言及されているAPIゲートウェイとは何ですか?そしてNGINX、Tomcat、Apacheなどのウェブサーバーとはどう違うのですか?
A: APIゲートウェイは、サービスを統一管理するためのゲートウェイです。例えば、支払い、ユーザーログインなど、すべてAPIの形で提供されるサービスであり、それらを統一してセキュリティと認証を行うためのゲートウェイが必要です。
APIゲートウェイは、従来のNGINXやApacheを置き換えて南北トラフィックを処理するだけでなく、マイクロサービス環境で東西トラフィックを処理することもできます。これは、ビジネスに近いミドルウェアであり、基盤となるウェブサーバーではありません。
APIゲートウェイの紹介と実装についての詳細は、Apache APISIXを参照してください。Apache APISIXはOpenRestyを基盤に実装されています。