Lapis:Nginx構成のLuaのサイト

ラピスopenresty、lua、nginx



Tl; dr Lapis(Lua)= RoR(Ruby)= Django(Python)





エントリー





画像

LuaはCと非常に簡単に統合できる強力で高速なスクリプト言語です。PUC-Rio(ブラジル)で開発されました。



ルアジット

LuaJITは、実際の芸術作品であるLua(JITコンパイラー)の最速の実装です。 いくつかの推定によると、標準のLuaインタープリターよりも6倍の利点があり、 多くの テストで V8に勝っています。 開発者Mike Pall(ドイツ)。



また、LuaJITは(Cバインディングを作成せずに)Lua側でCの関数と構造をバインドできます。

local ffi = require("ffi") ffi.cdef[[int printf(const char *fmt, ...);]] ffi.C.printf("Hello %s!\n", "wiki")
      
      







Nginx

Nginxは、Igor Sysoevが開発した最も効率的なWebサーバーの1つです。 多くの大規模なサイトはNginxを使用しています。 バージョン0.8以降、Lua言語直接埋め込むこと可能になりました。 LuaはNginxプロセス自体で実行され、他の言語の場合のように別のプロセスに入れられません。 NginxコンテキストのLuaコードは、Webアプリケーションによって生成されたデータベースクエリや外部HTTP要求(たとえば、別のサイトのAPIへの要求)を含む、非ブロックモードで実行されます。



オプレンレスト

OpenRestyは、人気のあるデータベースへのノンブロッキングアクセスを含む、多くのサードパーティモジュールを備えたNginxアセンブリです。 最近のバージョンではLuaJITを使用してLuaを実行します。 開発者Yichun Zhang(米国、勤務地:CloudFlare、lua-nginx-moduleのメイン開発者)。



MoonScript

Sailor MoonScriptは、Luaに翻訳するスクリプト言語です。 構文糖を追加し、リスト式などのいくつかのスペルを単純化します。 継承を使用してクラスを実装します。 Lua用のMoonScriptはJavaScript用のCoffeeScriptと言えます。 開発者Leaf Corcoran(アメリカ)。



ラピス

Lapisは、OpenResty内にあるLuaおよびMoonScript Webアプリケーションを作成するためのWebフレームワークです。 開発者Leaf Corcoran(アメリカ)。



LuaはNginxでどのような利点がありますか?



Tl; dr高レベル言語のすべての機能と高負荷下でのリソースの効率的な使用



答えとして、すべてのサイトがApache Webサーバーによって提供されていた遠い過去に戻りましょう。

アパッチ

遅延は、グラフの赤いノードとエッジによって発生します。 同じマシンにある黄色の影付きコンポーネント。



Apacheは、要求を読み取り、処理し、結果をユーザーに送信する別のオペレーティングシステムスレッドを割り当てました。 (現代のApacheは、これを行わないように教えることができます。)アクティブな要求の数、非常に多くのOSスレッド、そしてそれらが高価であることがわかります。 このようなスキームのフローライフタイムの大部分は、要求の処理ではなく、ユーザーのインターネット速度によって制限されるネットワーク上のデータ伝送に費やされます。



Nginx

これに対処する方法は? ネットワークが次のタスクを完了したときにのみWebサーバーが動作できるように、データ転送を監視するようオペレーティングシステムに指示する必要があります。 このアプローチは、 ノンブロッキング入出力と呼ばれ、最新のオペレーティングシステムのほとんどに実装されています。 Nginx Webサーバーはこの機能を使用します。そのため、1つのOSスレッドのみを使用して、数万の同時リクエストを処理できます。



Nginx、PHP

したがって、ブラウザーとWebサーバー間のデータ転送を最適化しましたが、OSスレッドがアイドル状態である別のボトルネックがあります:データベースと外部リソース(たとえば、別のサイトのHTTP-API)での作業。 これは、データベース自体または外部APIの避けられない遅延に関するものではなく、Webアプリケーションが応答を受信するまでアイドル状態であることを理解することが重要です。



通常の解決策 :Webアプリケーション自体で、Webサーバーで正常に削除されたストリームを生成します。 効果的なソリューション :Webアプリケーションとデータベースが非ブロッキングで通信するようにします。 Webアプリケーションは要求をデータベースに送信し、すぐにユーザーからの次の要求に進みます。 データベースは結果を返すとみなし、Webアプリケーションは、空きがある場合、このクエリをデータベースに生成したユーザーからのリクエストの処理に戻ります。 このアプローチは、たとえばnode.jsで使用されます。

node.js

データベースおよび外部APIは、遅延を引き起こす可能性があるため、依然として赤で網掛けされています。 このアプローチの利点は、Webアプリケーションがそれらを待つだけでなく、この時点で他のリクエストを処理することです。



いいね! 次に、node.jsで外部HTTPリクエストがどのようにプログラムされているかを見てみましょう。



 var request = require("request"); request.get("http://www.whatever.com/my.csv", function (error, response, body) { if (!error && response.statusCode == 200) { console.log("Got body: " + body); } });
      
      





URLでファイルをダウンロードし、それを使って何かをしたいとします。 結果は、ラムダ関数で処理する必要があります。 不便ですか? これはやむを得ない非同期料金ですか? 幸いなことに、これはそうではありません。 Lapisで同様のコードを見てみましょう。



 local http = require("lapis.nginx.http") local body, status_code, headers = http.simple("http://www.whatever.com/my.csv") if status_code == 200 then print(body) end
      
      





Lapisのコードを記述するのは、あたかも同期的であるかのように便利ですが、裏では完全に非同期的に実行されます。 これは、 コルーチンコルーチングリーンスレッド 、およびLuaの用語では単にスレッド )の積極的な使用により可能です。 ユーザーからのリクエストを処理するすべてのコードは個別のコルーチンで実行され、コルーチンは特定の場所で停止および続行できます。 この例では、そのような場所はhttp.simple関数の呼び出し内にありました。



コルーチンはなぜOSスレッドよりも効率的ですか? すべてのオーバーヘッドをアプリにドラッグしましたか? 実際、コルーチンとOSスレッドの主な違いは、コルーチンが眠って目を覚ますプログラマーの自由です。 (OSスレッドの場合、決定はOSによって行われます。)データベースへのクエリを開始しました-クエリを生成したコルーチンを書き留めます。 データベースから答えが返ってきました-コルーチンを起こし、実行を続けます。 1つのOSスレッドで同時に多くのタスクを実行します!



ご注意 同様のメカニズム 、node.js 登場しようとしています。



ご注意 C ++のコンテキストでのコルーチンに関する素晴らしい記事を読むことをお勧めします。 記事の最後に、非同期コードが作成され、同期として作成されました。すべてコルーチンのおかげです。 C ++コルーチンは、一般に受け入れられている手法よりもハッキングされる可能性が高いのは残念です。



さらに、LapisはNginxで直接実行されるため、NginxとWebアプリケーション間で情報を転送するオーバーヘッドがなくなります。 もちろん、node.jsはNginxなしでメインWebサーバーとして使用できますが、Nginxのさまざまな機能を使用する機能はなくなります。



ラピス



一方、メインのNginxでLuaコードを直接実行することを全員が決定するわけではありません。 この場合、切り捨てられた権限を持つ個々のユーザーに代わってLuaで別のNginxを起動し、基本的にNginxプロキシを規定します。



ラピス2



Lapisの有効性は、10ギガビットのベンチマークで確認されています 。 Lapisは、言語C ++およびJavaのレベルでトップの位置を占めています。



ラピス



2014年4月1日、エイプリルフールの記事「nginxのLUA:インラインphpスタイルヌードル」がHabréで公開されました。 この記事では、LuaでPHPのようなテンプレートを実装するコミックコードを取り上げました。 同じ記事へのコメントで、ラピスが言及されました 。 私はHabréでラピスに関する他の参照を見つけなかったので、自分でそれを書くことにしました。



Hello Worldの作成は退屈です。 代わりに、Lapisで簡単なWebプロキシを作成しましょう。



OpenRestyをインストールする



perl 5.6.1 +、libreadline、libpcre、およびlibsslをインストールし、ldconfigコマンドが使用可能であることを確認します(その親フォルダーがPATHにない場合があります)。

 $ wget http://openresty.org/download/ngx_openresty-1.7.4.1.tar.gz $ tar xzvf ngx_openresty-1.7.4.1.tar.gz $ cd ngx_openresty-1.7.4.1/ $ ./configure $ make # make install
      
      







Lapisをインストールする



まず、LuaRocks(メインディストリビューションで利用可能)をインストールする必要があります。



 # luarocks install lapis
      
      







Webアプリケーションを作成する



サイトのバックボーンを作成します。



 $ lapis new --lua wrote nginx.conf wrote mime.types wrote app.lua
      
      





--luaオプションを渡さなかった場合、MoonScriptのコアが作成されます。



ここで、アプリケーションのロジックをapp.luaに実装します。URLを入力するためのフォームがサイトのメインページに表示されます。 フォームは/ geturlに送信され、指定されたURLでページがロードされ、コンテンツがユーザーのブラウザーに転送されます。



 local lapis = require("lapis") local app = lapis.Application() local http = require("lapis.nginx.http") app:get("/", function(self) return [[ <form method="POST" action="/geturl"> <input type="text" value="http://ip4.me/" name="url" /> <input type="submit" value="Get" /> </form> ]] end) app:post("/geturl", function(self) local url = self.req.params_post.url local body, status_code, headers = http.simple(url) return body end) return app
      
      





メインページには、フォームと共にHTMLコードが表示されるだけです。 Luaの文字列の別の表記法は二重角括弧です。 / geturlページはフォームからPOSTリクエストを受け取り、ユーザーが入力したURLをフォームから取得し、http.simple関数を使用してこのURLのコンテンツをダウンロードし(OSストリームはブロックされません、上記を参照)、結果をユーザーに表示します。



http.simpleを機能させるには、nginx.confを変更する必要があります。



  location / { set $_url ""; default_type text/html; content_by_lua ' require("lapis").serve("app") '; } location /proxy { internal; rewrite_by_lua ' local req = ngx.req for k,v in pairs(req.get_headers()) do if k ~= "content-length" then req.clear_header(k) end end if ngx.ctx.headers then for k,v in pairs(ngx.ctx.headers) do req.set_header(k, v) end end '; resolver 8.8.8.8; proxy_http_version 1.1; proxy_pass $_url; }
      
      





このコードは、NginxでLuaが外部リクエストを行う場所/プロキシを作成します。 メインの場所にset $ _url ""を追加する必要があります。 詳細については、 ドキュメントを参照してください



Webプロキシを実行します。



 $ lapis server
      
      







ウェブプロキシ



「取得」ボタンをクリックします。 ip4.meサイトには、Lapisを実行しているサーバーのIPアドレスが表示されます。



Webプロキシの結果



URLにパスがない場合、/プロキシがパスとして使用されます。 どうやら、これはLapisのバグで、 レポートはすでにコンパイルされています。



おわりに



Lapis、Lua、およびNginxには、 Postgresデータベースとの非同期作業、データベースオブジェクトのラッパークラスHTML生成etluaの強力なテンプレート言語 、異なるNginx作業プロセス間の変数のキャッシュCSRFに対する保護など、他にも多くの興味深い機能がありますブラウザで直接テストおよびインタラクティブなLuaコンソール 。 記事で読者が見つかった場合は、他の記事でラピスに関する話を続けます。



間違いなく、ラピスはエイプリルフールのジョークのレベルを長く超えており、ウェブ開発コミュニティで急速に地位を獲得しています。 これらの有望な技術の楽しい研究をお祈りします!



参照資料






All Articles