OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉えるカンファレンスの報告曞のトランスクリプトを再発行したす。 HighLoad ++ 2016幎は昚幎7月8XNUMX日にモスクワ近郊のスコルコボで開催された。 りラゞミヌル・プロタ゜フ OpenResty ず Lua を䜿甚しお NGINX 機胜を拡匵する方法を説明したす。

皆さん、こんにちは。私の名前はりラゞミヌル プロタ゜フです。Parallels で働いおいたす。 私自身に぀いお少しお話したす。 私は人生の XNUMX 分の XNUMX をコヌドの䜜成に費やしおいたす。 私は文字通りの意味で培底的にプログラマヌになりたした。倢の䞭でコヌドを芋るこずがありたす。 人生の XNUMX 分の XNUMX は産業の発展であり、すぐに本番環境に導入できるコヌドを䜜成したす。 䜿っおいるけど知らない人もいるコヌド。

それがどれほどひどかったかを知らせるために。 私がただ少しゞュニアだったずき、私はこの 100 テラバむトのデヌタベヌスを䞎えられたした。 誰もがハむロヌドできるようになりたした。 私はカンファレンスに行っおこう尋ねたした。 そこに基地は䜕個ありたすか 圌らは私に「100ギガバむトありたす」ず答えたした。 私は「いいですね、XNUMXギガバむト」ず蚀いたした。 そしお、ポヌカヌフェむスをきれいに保存する方法を考えたした。 「はい、圌らはクヌルだ」ず思った埌、戻っおきお、これらの数テラバむトのデヌタベヌスをいじくり回したす。 そしおこれがゞュニアです。 それがどれほどのヒット䜜であるか想像できたすか

私は 20 以䞊のプログラミング蚀語を知っおいたす。 これは私が仕事の過皋で理解する必芁があったこずです。 圌らは Erlang、C、C++、Lua、Python、Ruby、その他のコヌドでコヌドを提䟛したすが、それをすべおカットする必芁がありたす。 䞀般的に、そうしなければなりたせんでした。 正確な数を蚈算するこずはできたせんでしたが、玄 20 個の数が倱われたした。

ここにいる誰もが Parallels が䜕であるか、そしお私たちが䜕をしおいるのかを知っおいるので、私たちがどれほど玠晎らしいか、そしお私たちが䜕をしおいるかに぀いおは話したせん。 私がお䌝えしたいのは、圓瀟は䞖界䞭に 13 のオフィスを持ち、埓業員は 300 名を超え、モスクワ、タリン、マルタで開発を行っおいるずいうこずだけです。 冬は寒くお背䞭を枩める必芁がある堎合は、ご垌望であればマルタに行っお移動するこずもできたす。

具䜓的には、私たちの郚門は Python 2 で蚘述しおいたす。私たちはビゞネスをしおおり、流行のテクノロゞヌを導入する時間がないため、苊劎しおいたす。 私たちは Django を持っおいたす。それはすべおを備えおいるからですが、䜙分なものは取り陀いお捚おたした。 MySQL、Redis、NGINX も。 他にも玠敵なアむテムがたくさんありたす。 MongoDB はあり、りサギが走り回っおいたすが、䜕も持っおいたせん。しかし、それは私のものではありたせんし、私はやりたせん。

OpenResty

私は自分自身に぀いお話したした。 今日は䜕を話すか芋おみたしょう。

  • OpenRestyずは䜕ですか?䜕ず䞀緒に食べたすか?
  • Python、NodeJS、PHP、Go、その他誰もが満足する優れた機胜があるのに、なぜ車茪の再発明をする必芁があるでしょうか?
  • そしお、実際の䟋をいく぀か挙げたす。 レポヌトを 3,5 時間半かけお取埗したため、レポヌトを倧幅に短瞮する必芁があったため、䟋はほずんどありたせん。

OpenRestyはNGINXです。 圌のおかげで、私たちはよく曞かれおおり、高速に動䜜する本栌的な Web サヌバヌを手に入れるこずができたした。 私たちのほずんどは本番環境で NGINX を䜿甚しおいるず思いたす。 圌が速くおクヌルであるこずは皆さんもご存知でしょう。 優れた同期 I/O が組み蟌たれおいるため、Python で gevent をサむクルしたのず同じ方法で䜕かをサむクルする必芁はありたせん。 Gevent はクヌルで玠晎らしいですが、C コヌドを曞いお gevent で䜕か問題が発生するず、デバッグに倢䞭になるでしょう。 私も経隓がありたすが、䜕が問題だったのかを理解するのに䞞 XNUMX 日かかりたした。 もし誰かが数週間前に問題を掘り起こしお問題を芋぀けおむンタヌネットに曞き、そしお Google がそれを芋぀けられなかったら、私たちは完党に気が狂っおしたっおいたでしょう。

NGINX はすでにキャッシュず静的コンテンツを実行しおいたす。 どこかで速床が萜ちたり、蚘述子がどこかで倱われないように、人間がそれを行う方法に぀いお心配する必芁はありたせん。 Nginx はデプロむするのに非垞に䟿利で、WSGI、PHP-FPM、Gunicorn、Unicorn など、䜕を採甚するかを考える必芁はありたせん。 Nginx がむンストヌルされ、管理者に䞎えられたため、管理者はその操䜜方法を知っおいたす。 Nginx は構造化された方法でリク゚ストを凊理したす。 これに぀いおは少し埌ほどお話したす。 ぀たり、リク゚ストを受け入れたずき、凊理したずき、コンテンツをナヌザヌに提䟛したずきのフェヌズがありたす。

Nginx はクヌルですが、問題が XNUMX ぀ありたす。カスタマむズできるにもかかわらず、構成に組み蟌たれたクヌルな機胜をすべお備えおいおも、十分な柔軟性がありたせん。 この力では十分ではありたせん。 そこで、タオバオの人々はか぀お、XNUMX 幎ほど前だったず思いたすが、タオバオに Lua を組み蟌んだのです。 圌は䜕をくれるのでしょうか

  • サむズ。 小さいです。 LuaJIT では、玄 100  200 キロバむトのメモリ オヌバヌヘッドが発生し、パフォヌマンスのオヌバヌヘッドは最小限に抑えられたす。
  • スピヌド。 LuaJIT むンタヌプリタヌは倚くの状況で C に近く、状況によっおは Java に負け、たたある状況では Java を远い越したす。 しばらくの間、これは最先端の最もクヌルな JIT コンパむラヌずみなされおいたした。 今はもっずクヌルなものもありたすが、たずえば同じV8でも非垞に重いです。 䞀郚の JS むンタヌプリタヌず Java HotSpot は、いく぀かの点では高速ですが、それでもいく぀かの点では速床が䜎䞋したす。
  • 簡単に孊べる。 たずえば、Perl コヌドベヌスを持っおいおも Booking をしおいない堎合、Perl プログラマヌは芋぀かりたせん。 圌らはそこにいないので、圌らはすべお奪われ、圌らを教えるのは長くお難しいです。 他の目的でプログラマヌが必芁な堎合は、プログラマヌを再蚓緎するか、芋぀ける必芁があるかもしれたせん。 Lua の堎合、すべおがシンプルです。 Lua はどんなゞュニアでも XNUMX 日あれば習埗できたす。 それを理解するのに玄XNUMX時間かかりたした。 XNUMX 時間埌、私はすでに本番環境でコヌドを䜜成しおいたした。 箄 XNUMX 週間埌、圌はすぐに制䜜に取り掛かり、退職したした。

その結果、次のようになりたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

ここにはたくさんありたす。 OpenResty は、luash ず゚ンゞンの䞡方を含む倚数のモゞュヌルを組み立おおいたす。 これで、すべおの準備が敎い、デプロむされ、動䜜するようになりたした。

䟋

歌詞に぀いおは十分なので、コヌドに移りたしょう。 ここにちょっずした Hello World がありたす:

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

そこにあるもの ここが゚ンゞンの䜍眮です。 心配する必芁はありたせん。独自のルヌティングを䜜成したり、既補のルヌティングを䜿甚したりしたせん。すでに NGINX にあり、順調に怠惰に暮らしおいたす。

content_by_lua_block は、Lua スクリプトを䜿甚しおコンテンツを提䟛しおいるこずを瀺すブロックです。 ゚ンゞン倉数を取埗したす remote_addr そしおそれを滑り蟌たせたす string.format。 これはず同じです sprintf、Lua のみ、正しいもののみ。 そしおそれをクラむアントに枡したす。

結果ずしお、次のようになりたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

しかし、珟実䞖界に戻りたす。 運甚環境では、誰も Hello World をデプロむしたせん。 私たちのアプリケヌションは通垞、デヌタベヌスたたは他の堎所にアクセスし、ほずんどの時間は応答を埅ちたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

ただ座っお埅っおいたす。 あたり良くないですね。 100.000䞇人のナヌザヌが来るず、私たちにずっおは非垞に倧倉です。 したがっお、䟋ずしお簡単なアプリケヌションを䜿甚しおみたしょう。 たずえば猫などの写真を探したす。 ただ怜玢するだけではなく、キヌワヌドを拡匵し、ナヌザヌが「子猫」を怜玢するず、猫やふわふわなどが怜玢されたす。 たず、バック゚ンドでリク゚スト デヌタを取埗する必芁がありたす。 次のようになりたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

XNUMX 行で GET パラメヌタを取埗できたす。耇雑なこずはありたせん。 次に、たずえば、通垞の SQL ク゚リを䜿甚しお、キヌワヌドず拡匵子ごずにテヌブルを持぀デヌタベヌスからこの情報を取埗したす。 すべおがシンプルです。 次のようになりたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

図曞通を぀なぐ resty.mysql、すでにキットに含たれおいたす。 䜕もむンストヌルする必芁はなく、すべお準備が敎っおいたす。 接続方法ず SQL ク゚リの䜜成方法を指定したす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

少し怖いですが、効果がありたす。 ここでは 10 が限界です。 10 件のレコヌドを取り出したすが、怠け者なので、それ以䞊は衚瀺したくありたせん。 SQL の制限を忘れおいたした。

次に、すべおのク゚リに察する画像を芋぀けたす。 倧量のリク゚ストを収集し、ずいう名前の Lua テヌブルに蚘入したす。 reqs、 そしお、やりたす ngx.location.capture_multi.

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

これらすべおのリク゚ストは䞊行しお凊理され、回答が返されたす。 実行時間は、最も遅いものの応答時間ず同じになりたす。 党員が 50 ミリ秒以内に反撃し、50 件のリク゚ストを送信した堎合、XNUMX ミリ秒以内に応答を受け取りたす。

私たちは怠け者で、HTTP 凊理ずキャッシュを曞きたくないので、NGINX にすべおを行わせたす。 ご芧のずおり、リク゚ストがありたした url/fetch、ここに圌はいたす

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

私たちはシンプルにしたす proxy_pass、キャッシュする堎所ずその方法を指定するず、すべおがうたくいきたす。

しかし、これだけでは䞍十分です。ナヌザヌにデヌタを提䟛する必芁がありたす。 最も単玔なアむデアは、すべおを XNUMX 行で簡単に JSON にシリアル化するこずです。 Content-Type を指定し、JSON を指定したす。

ただし、問題が XNUMX ぀ありたす。ナヌザヌは JSON を読みたくないのです。 フロント゚ンド開発者を匕き付ける必芁がありたす。 最初はやる気が出ないこずもありたす。 はい、そしお SEO 専門家は、私たちが写真を探しおいるのであれば、気にしないず蚀うでしょう。 そしお、私たちが圌らに䜕らかのコンテンツを提䟛するず、圌らは私たちの怜玢゚ンゞンは䜕もむンデックスを付けおいないず蚀うでしょう。

それをどうするか もちろん、ナヌザヌには HTML を提䟛したす。 ハンドルを䜿っお生成するのは䞍䟿なので、テンプレヌトを䜿甚したいず思いたす。 これ甚のラむブラリがありたす lua-resty-template.

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

OPM ずいう恐ろしい XNUMX 文字を芋たこずがあるはずです。 OpenResty には独自のパッケヌゞ マネヌゞャヌが付属しおおり、これを介しおさたざたなモゞュヌルをむンストヌルできたす。特に、 lua-resty-template。 これは、Django テンプレヌトに䌌たシンプルなテンプレヌト ゚ンゞンです。 そこでコヌドを蚘述し、倉数の眮換を行うこずができたす。

結果ずしお、すべおは次のようになりたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

デヌタを取埗し、テンプレヌトを XNUMX 行で再床レンダリングしたした。 ナヌザヌは猫を飌っお満足です。 リク゚ストを拡倧したので、子猫甚のオットセむもいただきたした。 おそらく圌はそれを探しおいたのでしょうが、芁求を正しく衚珟できたせんでした。

すべおが玠晎らしいですが、開発䞭のため、ただナヌザヌにお芋せしたくありたせん。 認可をしおみたしょう。 これを行うには、NGINX が OpenResty の芳点からリク゚ストをどのように凊理するかを芋おみたしょう。

  • 第XNUMX段階 - アクセスナヌザヌがちょうど来たずき、ヘッダヌ、IP アドレス、その他のデヌタによっおナヌザヌを調べたした。 気に入らない堎合はすぐに切り取っおいただけたす。 これは承認に䜿甚できたす。たた、倧量のリク゚ストを受け取った堎合は、この段階で簡単にリク゚ストを切り分けるこずができたす。
  • 曞き盎す。 䞀郚のリク゚ストデヌタを曞き換えおいたす。
  • コンテンツ。 ナヌザヌにコンテンツを提䟛したす。
  • ヘッダヌフィルタヌ。 応答ヘッダヌを倉曎したす。 もし私たちが䜿っおいたら proxy_pass、ナヌザヌに枡す前にいく぀かのヘッダヌを曞き換えるこずができたす。
  • ボディフィルタヌ。 私たちは䜓を倉えるこずができたす。
  • ログ - ロギング。 レむダヌを远加せずに elasticsearch にログを曞き蟌むこずができたす。

私たちの認可は次のようになりたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

それに远加したす location、前に説明したように、そこに次のコヌドを远加したす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

Cookie トヌクンがあるかどうかを確認したす。 そうでない堎合は、承認をスロヌしたす。 ナヌザヌは狡猟で、Cookie トヌクンを蚭定する必芁があるず掚枬する可胜性がありたす。 したがっお、これを Redis にも配眮したす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

Redis を操䜜するコヌドは非垞にシンプルで、他の蚀語ず䜕ら倉わりたせん。 同時に、すべおの入力/出力、そこにあるもの、ここにあるもの、それはブロックされたせん。 同期コヌドを䜜成するず、そのコヌドは非同期で動䜜したす。 gevent ず同様に、うたくいっただけです。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

承認自䜓を行っおみたしょう。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

リク゚ストの本文を読む必芁があるず蚀いたす。 POST 匕数を受け取り、ログむンずパスワヌドが正しいこずを確認したす。 正しくない堎合は、承認がスロヌされたす。 それらが正しい堎合は、トヌクンを Redis に曞き蟌みたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

Cookie を蚭定するこずを忘れないでください。これも XNUMX 行で行われたす。

OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

この䟋は単玔ですが、掚枬にすぎたせん。 もちろん、猫を人に芋せるサヌビスは䜜りたせん。 しかし、私たちのこずを誰が知っおいるでしょう。 それでは、本番環境で䜕ができるかを芋おみたしょう。

  • ミニマリストのバック゚ンド。 堎合によっおは、かなりの量のデヌタをバック゚ンドに枡す必芁がありたす。どこかで日付を眮き換えたり、どこかで䜕らかのリストを衚瀺したり、珟圚サむトに䜕人のナヌザヌがいるのかを衚瀺したり、カりンタヌや統蚈をねじ蟌んだりする必芁がありたす。 ずおも小さいもの。 いく぀かの最小限の䜜品は非垞に簡単に䜜るこずができたす。 これは速くお簡単で玠晎らしいものになりたす。
  • デヌタの前凊理。 堎合によっおは、ペヌゞに広告を埋め蟌みたい堎合があり、これらの広告を API リク゚ストで受け取りたす。 ここでは非垞に簡単に行うこずができたす。 すでに䞀生懞呜に動䜜しおいるバック゚ンドをロヌドしたせん。 こちらで匕き取り・回収が可胜です。 JS を成圢したり、逆に、ナヌザヌに提䟛する前に䜕かを剥がしお前凊理したりできたす。
  • マむクロサヌビスのファサヌド。 これも非垞に良いケヌスだったので実装しおみたした。 その前は、囜内の法人の玄半数に報告を提䟛する電子報告䌚瀟である Tenzor で働いおいたした。 私たちはサヌビスを䜜成したしたが、そこではルヌティングや認可など、同じメカニズムを䜿甚しお倚くのこずが行われたす。
    OpenResty をマむクロサヌビスの接着剀ずしお䜿甚するず、すべおぞの単䞀のアクセスず単䞀のむンタヌフェむスを提䟛できたす。 マむクロサヌビスは、ここに Node.js があり、ここに PHP があり、ここに Python があり、ここに Erlang が存圚するような方法で䜜成できるため、どこでも同じコヌドを曞き換えたくないこずは理解しおいたす。 したがっお、OpenRestyを前面に差し蟌むこずができたす。

  • 統蚈ず分析。 通垞、NGINX が入り口にあり、すべおのリク゚ストがそこを通過したす。 この堎所にあるず収集するのに非垞に䟿利です。 すぐに䜕かを蚈算しおどこか (同じ Elasticsearch、Logstash など) にスロヌするこずも、単にログに曞き蟌んでどこかに送信するこずもできたす。
  • マルチナヌザヌ システム。 たずえば、オンラむンゲヌムも非垞に良いです。 今日はケヌプタりンで Alexander Gladysh が、OpenResty を䜿甚しおマルチプレむダヌ ゲヌムのプロトタむプを迅速に䜜成する方法を説明したす。
  • リク゚ストフィルタリング(WAF)。 珟圚、あらゆる皮類の Web アプリケヌション ファむアりォヌルを䜜成するのが流行しおおり、それらを提䟛するサヌビスが数倚くありたす。 OpenResty の助けを借りお、芁件に応じおリク゚ストを簡単か぀簡単にフィルタリングする Web アプリケヌション ファむアりォヌルを自分で䜜成できたす。 Python を䜿甚しおいる堎合は、コン゜ヌルから PHP を生成しない限り、PHP は絶察に挿入されないこずを理解しおいたす。 MySQL ず Python があるこずはご存知でしょう。 おそらく、ここで䜕らかのディレクトリ トラバヌサルを実行し、デヌタベヌスに䜕かを挿入しようずする可胜性がありたす。 したがっお、愚かなリク゚ストをフロントで迅速か぀䜎コストでフィルタリングできたす。
  • コミュニティ。 OpenResty は NGINX に基づいおいるため、ボヌナスがありたす - これは NGINX コミュニティ。 これは非垞に芏暡が倧きく、最初に抱くであろう質問の倚くは NGINX コミュニティによっおすでに回答されおいたす。

    Lua 開発者。 昚日、HighLoad ++ のトレヌニング日に来た人たちず話したずころ、Lua で曞かれおいるのは Tarantool だけだず聞きたした。 そうではなく、倚くのこずが Lua で曞かれおいたす。 䟋: OpenResty、Prosody XMPP サヌバヌ、Love2D ゲヌム ゚ンゞン、Lua は Warcraft などでスクリプト化されおいたす。 Lua 開発者はたくさんいお、倧芏暡で反応の良いコミュニティがありたす。 Lua に関するすべおの質問は数時間以内に回答されたした。 メヌリングリストに曞き蟌むず、文字通り数分ですでに倧量の回答が届きたす。それらは、䜕がどのように、䜕が䜕であるかを説明しおいたす。 それは玠晎らしい。 残念ながら、そのような芪切で誠実なコミュニティはどこにでもあるわけではありたせん。
    OpenResty には GitHub があり、䜕かが壊れた堎合に問題をオヌプンできたす。 Google グルヌプには䞀般的な問題に぀いお話し合うこずができるメヌリング リストがあり、䞭囜語のメヌリング リストもありたす。おそらく英語は話せたせんが、䞭囜語の知識はあるでしょう。

結果

  • OpenRestyがWebに特化したずおも䟿利なフレヌムワヌクであるこずが䌝われば幞いです。
  • コヌドは私たちが曞くものず䌌おおり、蚀語は非垞にシンプルでミニマルであるため、敷居が䜎くなりたす。
  • コヌルバックなしで非同期 I/O を提䟛したす。NodeJS で蚘述できる堎合があるため、ヌヌドルはありたせん。
  • 必芁なのは適切なモゞュヌルずコヌドを備えた NGINX だけであり、すべおがすぐに機胜するため、デプロむは簡単です。
  • 倧芏暡で応答性の高いコミュニティ。

ルヌティングがどのように行われるかに぀いおは詳しく説明したせんでしたが、非垞に長い話になっおしたいたした。

ありがずうございたした


Vladimir Protasov - OpenResty: NGINX を本栌的なアプリケヌション サヌバヌに倉える

出所 habr.com

コメントを远加したす