問題タブ [http-kit]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
http - clojure を使用した Heroku での HTTP ストリーミング / チャンク応答
チャンクされた HTTP 応答を使用してクライアントにデータをストリーミングする clojure Web アプリを作成しています。を使用してローカルで実行するとforeman
うまく動作しますが、Heroku にデプロイすると正しく動作しません。
この動作を示す最小限の例は、私の github here にあります。フロントエンド ( resources/index.html
) は AJAX GET 要求を実行し、応答チャンクが到着すると出力します。サーバーは http-kit を使用して、接続されたクライアントに毎秒新しいチャンクを送信します。設計上、HTTP 要求は決して完了しません。
同じコードが Heroku にデプロイされると、最初のチャンクが送信された直後に HTTP 接続がサーバーによって閉じられます。この切断が発生する原因となっているのは、Heroku のルーティング メッシュのようです。
これは、curl を使用して GET リクエストを実行することでも確認できます。
なぜこれが起こっているのか誰にも示唆できますか?HTTP ストリーミングは、Heroku の Cedar スタックでサポートされるはずです。を使用してコードが正しく実行されるという事実はforeman
、Heroku のルーティング メッシュの何かが壊れていることを示唆しています。
失敗したプロジェクトのライブ デモ: http://arcane-headland-2284.herokuapp.com/
clojure - clojure の http-kit を使用した同期 POST
約束を返す同期投稿を行うために、clojure で http-kit クライアント ライブラリを使用しようとしています。実際の投稿を行うスレッドの数を制限する方法はありますか?
組み込みのスレッド プールを使用して見つけたすべての例は、呼び出された下位レベルのプリミティブ関数を使用していますrequest
が、それらはすべて http/get 用でした。
ありがとう
clojure - Clojure のスケーラブルなチャット サーバー。プレゼンスとメッセージ到着の b/w 再接続に関する問題
Clojure でスケーラブルなチャット サーバーを構築しようとしています。http-kit、compojure、および redis pub/sub を使用して、異なるノード間で通信しています (ファンアウト アプローチ)。サーバーは、長いポーリングへのフォールバックを使用して、クライアントとサーバー間の接続に websocket を使用します。1 人のユーザーは、ブラウザのタブごとに 1 つの接続でチャットするために複数の接続を持つことができ、メッセージはすべての接続に配信される必要があります。
基本的に、ユーザーが接続すると、ランダムな uuid を持つアトムにチャネルを保存します。
メッセージは Websocket とロング ポーリング チャネルの両方の共通ルートに POST されます。メッセージ構造は次のようになります。
サーバーは、:from および :to ユーザー ID のアトム内のすべてのチャネルを見つけ、それぞれのユーザーの接続されたチャネルにメッセージを送信します。また、接続されたノードが格納されているチャネルを探す redis サーバーを介してメッセージを発行します。自分のアトムを作成し、それぞれのユーザーにメッセージを配信します。
したがって、私が直面している問題は、プレゼンスを適切に実装する方法です。基本的にhttp-kitは、チャネルが切断されたときにステータスを送信します。ステータスは「server-close」または「client-close」にすることができますが、サーバーの切断を処理できます(クライアントは自動的に再接続します)が、切断時に問題が発生していますたとえば、クライアント側から発生します。ユーザーは別のページに移動し、数秒後に接続します。クライアントが切断されたときに、ユーザーがオフラインになったことをどのように判断しますか? また、ロング ポーリング モードでのメッセージ到着の双方向再接続についても懸念しています (ロング ポーリング タイムアウトは 30 秒です)。
また、上記のアーキテクチャに適したプレゼンス メカニズムを提案してください。ありがとう。
さらに情報が必要な場合はコメントしてください。ありがとう
編集#1:
チャット サーバーにプレゼンスを実装するための優れたチュートリアル/資料をお勧めできますか?
私の現在の解決策 - >現在、特定のユーザーIDの接続チャネルのグローバルカウントと最後に接続されたタイムスタンプを維持しており、ユーザーが切断するとカウントが減少し、ユーザーが持っているかどうかを確認する10秒間のタイムアウトが実装されています再接続された場合 (つまり、最後に接続されたスタンプは 10 秒前で、カウントはまだゼロです)、そうでない場合、ユーザーはオフラインになったと言われます。この解決策をお勧めしますか。また、http-kit で timer/scheduled-task を使用していることに注意してください。これらのタイムアウトはパフォーマンスに大きな影響を与えますか?
http - core.async チャネルで http-kit ロング ポーリングを使用する
プロセスが終了したときに結果を含む core.async チャネルを返す長時間実行プロセスがあります。
ここで、HTTP-kit を使用したロング ポーリングを使用してその結果を返したいと思います。残念ながら、私はそうする正しい方法が何であるかについて少し混乱しています。
現在、処理呼び出しを開始し、完了時に結果を送信するハンドラー (ルートに接続) があります。
動作しますが、これが正しい方法かどうかはわかりません。
編集はブロックされているため<!!
、現在、ゴーループで非ブロックバリアントを試しています
clojure - http-kit と core.async を使用して、完全にノンブロッキングのバックエンド アプリケーションを作成できますか?
http-kit を使用して、完全に非ブロッキングの Clojure バックエンド Web アプリケーションを作成できるかどうか疑問に思っています。
(実際には、Ring 互換の http サーバーであればどれでも問題ありません。http-kit について言及しているのは、イベント駆動型のノンブロッキング モデルがあると主張しているためです)。
編集:TL;DR
この質問は、非ブロッキング/非同期/イベント駆動型システムの性質について私が持っていたいくつかの誤解の兆候です。あなたが私と同じ場所にいる場合に備えて、いくつかの説明があります。
(Node.js のように) ノンブロッキングであるというパフォーマンス上の利点を備えたイベント駆動型システムを作成するには、IO のすべて (たとえば、ほとんど) がゼロからノンブロッキングの方法で処理される場合にのみ可能です。つまり、すべての DB ドライバー、HTTP サーバーとクライアント、Web サービスなどは、最初に非同期インターフェイスを提供する必要があります。特に:
- データベース ドライバーが同期インターフェイスを提供している場合、それをノンブロッキングにする方法はありません。(あなたのスレッドはブロックされています。取得する方法はありません)。非ブロッキングが必要な場合は、別のものを使用する必要があります。
- core.async のような高レベルの調整ユーティリティでは、システムをノンブロッキングにすることはできません。ノンブロッキング コードの管理には役立ちますが、有効にしないでください。
- IO ドライバーが同期の場合、core.async を使用して非同期の設計上の利点を得ることができますが、パフォーマンス上の利点は得られません。スレッドは、各応答を待機する時間を無駄にします。
さて、具体的には:
- HTTP サーバーとしての http-kit は、非ブロッキングの非同期インターフェースを提供します。下記参照。
- ただし、多くの Ring ミドルウェアは本質的に同期であるため、このアプローチと互換性がありません。基本的に、返された応答を更新する Ring ミドルウェアは使用できません。
私が正しく理解していれば (私は専門家ではないので、間違った仮定で作業している場合は教えてください)、このような Web アプリケーションのノンブロッキング モデルの原則は次のとおりです。
- いくつかの超高速 OS スレッドで、CPU を集中的に使用するすべてのコンピューティングを処理します。これらは決して待ってはいけません。
- 多くの「弱いスレッド」で IO (データベース呼び出し、Web サービス呼び出し、スリープなど) を処理します。これらは主に待機するためのものです。
- 要求の処理に費やされる待機時間は通常、計算時間よりも 2 (ディスク アクセス) から 5 (Web サービス呼び出し) 桁大きいため、これは有益です。
私が見た限りでは、このモデルはPlay Framework (Scala) およびNode.js (JavaScript) プラットフォームでデフォルトでサポートされており、非同期をプログラムで管理するための promise ベースのユーティリティが用意されています。
Compojure ルーティングを使用して、Ring ベースの clojure アプリでこれを実行してみましょう。my-handle
関数を呼び出して応答を構築するルートがあります。
Clojure アプリケーションで非同期を管理する一般的に受け入れられている方法は、core.asyncライブラリを使用する CSP ベースであると思われますが、私はまったく問題ありません。したがって、上記のノンブロッキングの原則を採用したい場合は、次のように実装my-handle
します。
Core.async のこのビデオでTim Baldridge が示唆しているように、CPU を集中的に使用construct-my-response
するタスクは -block で実行されますがgo
、外部リソースの待機は -block で行われます(38'55'')thread
しかし、それだけではアプリケーションをノンブロッキングにするのに十分ではありません。どのスレッドが私のルートを通過してmy-handle
関数を呼び出しても、応答が構築されるのを待っていますよね?
この HTTP 処理をノンブロッキングにすることも (私が信じているように) 有益でしょうか?
編集
codemomentum が指摘したように、リクエストのノンブロッキング処理に欠けている要素は、http-kit チャネルを使用することです。core.async と組み合わせると、上記のコードは次のようになります。
これにより、実際に非同期モデルを採用できます。
これの問題は、Ring ミドルウェアとほとんど互換性がないことです。Ring ミドルウェアは、応答を取得するために関数呼び出しを使用します。これにより、基本的に同期が行われます。より一般的に言えば、イベント駆動型の処理は、純粋な関数型プログラミング インターフェイスと互換性がないように思われます。イベントをトリガーすると、副作用が生じるからです。
これに対処する Clojure ライブラリがあるかどうかを知りたいです。
tomcat - tomcat7 を使用した clojure / http-kit アプリケーションのデプロイ
短編小説: http-kitテンプレートhereでビルドされたアプリケーションを tomcat7 にデプロイしようとしていますが、3 番目のステップはコマンド ( sh java -jar target/lein-template-standalone.jar --profile prod --port 8000
) であり、どうすればよいかまったくわかりません。
長い話:シンプルな compojure アプリケーションの場合、次のことができます。
...そしてそれは機能します。http-kit テンプレートには、ここ ( https://github.com/http-kit/lein-template ) にデプロイの手順があり、かなり異なります。tomcat7/webapps のすべてを削除してから:
動作しませんが、エラーはありません。ローカル ホストは空白です。これはおそらく驚くべきことではありません。http-kit テンプレートの README には 3 つの手順があります。
- lein uberjar は、ターゲット ディレクトリにスタンドアロンの実行可能 jar ファイルを作成します。
- jar と public ディレクトリを本番サーバーにコピーします
- ```sh java -jar target/lein-template-standalone.jar --profile prod --port 8000
3番目のステップが何であるか、またはそのコマンドをどこに置くべきかはまったくわかりません。
http - clojure の http-kit と compojure、get url クエリの # 記号が失敗する
# 記号がクエリ文字列の一部であるため、http get クエリ プラムを取得できません。
理想的には、外部パーティがパラメータを URL エンコードする必要がありますが、そうではありません。
したがって、受信したリクエストで :query-string を呼び出すと、その時点までは正常に機能します。
この問題を軽減できる方法はありますか?
http-kit はリングの仕様に準拠しているため、http-kit のドキュメントとリングのドキュメントを調べましたが、役に立ちませんでした。誰かが私を正しい方向に向けることができれば、私は感謝します。
clojure - タイムアウトが原因で http-kit クライアント コールバックが呼び出されたことを特定するにはどうすればよいですか?
例えば:
「some-url」がダウンしている場合、タイムアウト時に「post-callback」が呼び出されます。しかし、コールバック関数内で、タイムアウトのために呼び出されたかどうかを確認する方法。そうする方法があれば教えてください。ありがとう。