問題タブ [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.
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 のドキュメントとリングのドキュメントを調べましたが、役に立ちませんでした。誰かが私を正しい方向に向けることができれば、私は感謝します。