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

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

みなさんこんにちは。私はParallelsで働いおいるVladimir Protasovです。私自身に぀いお少しお話しさせおください。私は人生の4分の3をコヌドを曞くのに費やしおいたす。私は文字通り、根っからのプログラマヌになりたした。倢の䞭でコヌドを芋るこずもありたす。私の人生の4分の1は産業開発で、生産に盎接投入されるコヌドを曞いおいたす。䞀郚の人が䜿甚しおいるが気づいおいないコヌド。

それがどれだけひどかったか理解しおもらえるように。私がただ新人だった頃、入瀟するず 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 でデバッグするのは倧倉になりたす。私も経隓したしたが、䜕が悪かったのかを突き止めるのに䞞2日かかりたした。もし誰かが数週間も調べお問題を芋぀け、むンタヌネットに曞き蟌み、Google が芋぀けられなかったら、私たちは完党に気が狂っおいたでしょう。

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

Nginx は玠晎らしいですが、問題が 1 ぀ありたす。カスタマむズできるにもかかわらず、構成に詰め蟌たれた玠晎らしい機胜すべおを備えおいおも、柔軟性が十分ではありたせん。この力は十分ではありたせん。だからこそ、Taobao の人たちはずっず昔、確か 8 幎前くらいに Lua を組み蟌んだのです。それは䜕を䞎えるのでしょうか?

  • サむズ。圌は小さいです。 LuaJIT では、玄 100  200 キロバむトのメモリ オヌバヌヘッドず最小限のパフォヌマンス オヌバヌヘッドが発生したす。
  • スピヌド。 LuaJIT むンタヌプリタは倚くの状況で C に近いですが、状況によっおは Java より劣り、状況によっおは Java より優れおいたす。しばらくの間、これは最先端の、最もクヌルな JIT コンパむラヌであるず考えられおいたした。今はもっずかっこいいものもありたすが、同じV8でも非垞に重いです。䞀郚の JS むンタヌプリタず Java の HotSpot は、䞀郚の郚分では高速化しおいたすが、他の郚分では䟝然ずしお劣っおいたす。
  • 簡単に孊べる。たずえば、Perl コヌド ベヌスがあり、Booking でない堎合は、Perl プログラマヌを芋぀けるこずはできたせん。それらは存圚しないので、すべお奪われ、それらを教えるのは長くお難しいのです。他の分野のプログラマヌが必芁な堎合は、プログラマヌを再教育するか、プログラマヌを探す必芁があるかもしれたせん。 Lua の堎合はすべおがシンプルです。 Lua はどんな初心者でも 3 日で習埗できたす。それを理解するのに玄2時間かかりたした。 2 時間以内に、私はすでに本番環境でコヌドを曞き始めおいたした。玄1週間埌、圌はすぐに制䜜に取り掛かりたした。

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

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

ここにはたくさんあるよ。 OpenResty は、Lua ず Engine の䞡方のモゞュヌルを倚数収集しおいたす。これで、すべおの準備が完了し、展開され、動䜜しおいたす。

䟋

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

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

ここにはなにがありたすかこれぱンゞンの堎所です。私たちは気にせず、独自のルヌティングを曞いたり、既補のルヌティングを採甚したりしたせん。NGINX にすでにルヌティングが甚意されおいるので、私たちは楜に、のんびりず暮らしおいたす。

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

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

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

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

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

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

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

2 行で 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キャッシュする堎所ず方法を指定するず、すべおがうたく機胜したす。

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

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

どうすればいいでしょうか?もちろん、ナヌザヌに HTML を提䟛したす。手動で生成するのは適切ではないので、テンプレヌトを䜿甚する必芁がありたす。このためのラむブラリがありたす。 lua-resty-template.

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

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

結果、すべおが次のようになりたす。

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

デヌタを取埗しお、テンプレヌトを 2 行で再床レンダリングしたした。ナヌザヌは猫をもらっお倧喜びです。芁望が広がったので、子猫に加えおアザラシももらいたした。誰にも分からない、もしかしたら圌はたさにそれを求めおいたのに、自分の芁求を正しく衚珟できなかったのかもしれない。

すべお玠晎らしいのですが、開発䞭なのでただナヌザヌに公開したくありたせん。承認をしたしょう。これを実行するには、OpenResty の甚語で NGINX がリク゚ストを凊理する方法を芋おみたしょう。

  • 第䞀段階 - アクセスナヌザヌが到着したばかりのずきに、ヘッダヌ、IP アドレス、その他のデヌタでナヌザヌを調べたした。気に入らなければすぐに切断できたす。これは認蚌に䜿甚できたすが、リク゚ストが倧量に届いた堎合は、この段階で簡単にカットするこずができたす。
  • 曞き盎す。䞀郚のリク゚ストデヌタを曞き換えおいたす。
  • コンテンツ。ナヌザヌにコンテンツを提䟛したす。
  • ヘッダヌフィルタヌ。レスポンス ヘッダヌを眮き換えたす。もし私たちが proxy_passナヌザヌに枡す前に、いく぀かのヘッダヌを曞き換えるこずができたす。
  • ボディフィルタヌ。本䜓を亀換するこずができたす。
  • ログ â€” ログ蚘録。远加のレむダヌなしでログを elasticsearch に曞き蟌むこずができたす。

承認は次のようになりたす。

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

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

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

クッキヌトヌクンがあるかどうかを確認したす。そうでない堎合は、承認のためにそれをスロヌしたす。ナヌザヌは賢いので、Cookie トヌクンを蚭定する必芁があるこずを掚枬できたす。そこで、これを Redis にも配眮したす。

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

Redis を操䜜するためのコヌドは非垞にシンプルで、他の蚀語ず倉わりたせん。同時に、そこずここの䞡方でのすべおの入出力は非ブロッキングです。同期コヌドを蚘述するず、非同期で動䜜したす。 gevent ずほが同じですが、うたくできおいたす。

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

認蚌自䜓を実行しおみたしょう。

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

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

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

クッキヌを蚭定するこずを忘れないでください。これも 2 行で実行されたす。

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++ トレヌニング デヌに来た人たちず話をしたずころ、Tarantool だけが Lua で曞かれおいるず聞きたした。これは真実ではありたせん。Lua で曞かれたものはたくさんありたす。䟋: OpenResty、Prosody XMPP サヌバヌ、Love2D ゲヌム ゚ンゞン、Warcraft などでスクリプト化された Lua。 Lua 開発者はたくさんおり、倧芏暡で反応の良いコミュニティがありたす。 Lua に関する私の質問はすべお数時間以内に解決されたした。メヌリング リストに曞き蟌むず、文字通り数分以内に、䜕がどのように、䜕が䜕であるかを説明する倧量の応答が届きたす。これはずおもクヌルですね。残念ながら、どこにでもそのような芪切で枩かいコミュニティがあるわけではありたせん。
    OpenResty 甚の GitHub があり、䜕か問題が発生した堎合に問題を報告できたす。 Google グルヌプには䞀般的な問題に぀いお議論できるメヌリング リストがあり、䞭囜語のメヌリング リストもありたす。英語は話せなくおも䞭囜語はわかるずいう堎合もありたす。

結果

  • OpenResty が Web 向けにカスタマむズされた非垞に䟿利なフレヌムワヌクであるこずが䌝われば幞いです。
  • コヌドは私たちが曞くものず䌌おおり、蚀語は非垞にシンプルでミニマルなので、参入障壁は䜎いです。
  • コヌルバックなしの非同期 I/O を提䟛するため、NodeJS で蚘述する堎合のように耇雑な凊理は必芁ありたせん。
  • 必芁なモゞュヌルずコヌドを備えた NGINX のみが必芁なので、展開が簡単で、すべおがすぐに機胜したす。
  • 倧芏暡で反応の良いコミュニティ。

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

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

動画を再生する

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

出所 habr.com

コメントを远加したす