忙しいプロジェクトのWebアラート

最新のWEBデザインでは、イベントについてユーザーに通知する必要がある場合にタスクが頻繁に発生します:新しいメッセージが到着した、為替レートまたは注文ステータスが変更された、ビデオコンテンツが変換された、または病気の祖母の体温が急上昇した。



このクラスの問題を解決するには、いくつかのオプションがあります。 最も最適で一般的なソリューションは、イベントをサブスクライブすることです。 これは忙しいプロジェクトでどのように実装されていますか?



数千の顧客にサービスを提供する証券会社のサービスを開発しているとします。 証券取引所での株価の状態を調べるため、またはホテル内の無料の場所の数を調べるために、1つ以上の外部サービスを利用する必要があります。 外部サービスは遅延して応答し、何千人もの顧客がいるため、WEBアプリケーションから直接サービスを要求し、サービスからの応答を待つと、結果としてすべてがハングします。



したがって、いわゆる保留中の要求を行う必要があります。 WEBアプリケーションは、生成されたHTMLページを結果なしですぐにユーザーに返します。これにより、リクエストが実行されていることを示すスクリーンセーバーが表示され、結果が実行されると少し遅れて表示されます。 これはどうですか?



HTMLページの形成を開始する前に、Webアプリケーションはデータをキューに入れます。 デーモン、またはクラウンによって呼び出されるタスクは、キューを調べて、そこからデータを取得します。 さらに、このデータに基づいて、彼女はリクエストを作成し、それを外部サービスに送信します(写真1)。



画像



このスキームのすべてが良いようです-遅滞なく動作します。 しかし、フィードバックが必要であり、エンドユーザーは彼が要求した情報が必要です。 そして今、私たちはクラウンスクリプトでこの情報を得ました。 次に、ユーザーに転送する必要があります。



ここでは、Publisher-Subscriberパターンが役立ちます。 JavaScriptを使用する多くの人がこのパターンを知っています:



サブスクライバーは特定のチャネルをサブスクライブし、イベントが発生すると、プロデューサーはこのチャネルにメッセージを送信します。 このような通知メカニズムとして、Redis、RabbitMQ、Tarantool、MsMQ、ZMQ、Kafka(メッセージブローカー)など、さまざまなソリューションを使用できます。 Redisに関連付けられた多くのサービスが既にあるため、新しいエンティティを導入しないことにしました。



これをどのように使用しますか? ここにはいくつかのオプションがありますが、専門家はすぐに「Webページとサーバーを接続するにはWebsocketを使用する必要がある」と宣言します。 はい、今日、これはWEBクライアントとサーバーの即時通信のための最も先進的な技術であるとは言いません。 サーバー側を検討してください。



ここ数年、nginxがWebsocketをプロキシすることができたという秘密を誰にも教えません。 php-fpmをバックエンドとして使用する場合、実行中のWEBクライアントごとに、PHPプロセスを実行する必要があります。 ここで、10Kプロセスが10Kリクエストでハングすると、10K問題が発生します。 トライトは十分なメモリではありません。 1つのオプションとして、node.jsを使用できます。 これはまさに彼のクラスのタスクであり、そこでは長時間プレイするノンブロッキング接続が使用されます。



彼なしでできますか? 結局のところ、新しいエンティティを導入したくはないので、非常に単純なタスクをそれに割り当てます。 アーキテクチャが複雑になるほど、障害点が増え、稼働時間の可能性が低くなります。 nginx-luaモジュールの実装については、すでに積極的な経験があります(nginx-luaの詳細については、 こちらこちらをご覧ください )。 そして、彼はこれらの機能を実行できますか? 一般的に、結果はそのような画像です(画像2):



画像



これはそれほど難しくないことがわかります。 lua-nginx-moduleに加えて、 lua-resty-redislua-resty-websocketを接続します。 このため、lua-nginx-moduleとは異なり、何も収集する必要はありませんが、libディレクトリーにあるモジュールのすべてのソースコードをフォルダーにコピーするだけです:/ usr / share / nginx / lua / lib(httpのコンテキストでディレクティブに接続します( nginx.conf構成ファイル):



http { lua_package_path "/usr/share/nginx/lua/lib/?.lua;;"; ... }
      
      





次に、nginx.conf構成ファイル(または仮想ホストのプラグイン構成)で、場所/ wsを決定します。



 location /ws { content_by_lua_file /path/to/file/websocket_server.lua; }
      
      





websocket_server.luaファイル自体はそれほど複雑ではないので、ここに一部を記載します。理由はわかりません。 そのフルバージョンはgithubにあります。



検証のために、異なるタイムアウトで数千のインスタンスでファイナライズおよび実行でき、実際に検証できるテストコンソールクライアントがあります。 このバージョンのクライアントは対話型であり、チャネルの名前はコンソールから入力され、パブリケーションがチャネルに送信されると、すぐにクライアントに到着します。 クライアントのタイムアウトは5分です。



この機能が誰かに役立つことを願っています。



All Articles