バックグラウンド
私はr2d2を通じてディーゼルを使用して、actix-webアプリケーションに取り組んでおり、非同期クエリを最適に作成する方法がわかりません。妥当と思われる3つのオプションを見つけましたが、どちらが最適かわかりません。
可能なソリューション
俳優の同期
一例として、actixの例を使用することができますが、それは非常に複雑であり、構築するにはかなりの量のボイラープレートが必要です。より合理的な解決策が存在することを願っています。
Actix_web::web::block
別のオプションとしてactix_web::web::block
、クエリ関数を将来にラップするためにを使用することもできますが、これがパフォーマンスに与える影響はわかりません。
クエリは同じTokioシステムで実行されていますか?ソースで見つけたものから、それは基礎となるactix-web threadpoolにスレッドを作成します。問題ありますか?
コードを正しく読んだ場合、r2d2は接続を取得するときにそのスレッドをブロックします。これにより、コアのactix-webプールの一部がブロックされます。データベースクエリと同じです。これにより、そのプールにスレッドがあるよりも多くのクエリを実行した場合、すべてのactix-webがブロックされますか?もしそうなら、大きな問題。
先物-cpupool
最後に、不要なオーバーヘッドが生じる可能性のある安全な賭けは、futures-cpupoolです。主な問題は、これが私のプロジェクトに別のクレートを追加することを意味することですが、アプリケーション内で不必要に複数のcpu-poolが浮かんでいるという考えは好きではありません。
r2d2とディーゼルの両方がブロックするので、ここには驚くほど多くのトリッキーなことが存在します。
最も重要なのは、このcpupoolを同じr2d2プールを使用していないものと共有しないことです(作成されたすべてのスレッドは、r2d2接続の待機をブロックし、作業が存在する場合はプール全体をロックダウンする可能性があるため)。
2番目に(少し明らかに)、プール内のスレッドよりも多くのr2d2接続を使用しないでください。逆に、大きい接続はリソースを無駄にするため(接続が未使用/スレッドが常にブロックされているため)(おそらくもう1つのスレッド、おそらくより速く) cpupoolスケジューラーではなくOSスケジューラーによる接続のハンドオーバー)。
最後に、使用しているデータベースとそこにあるパフォーマンスに注意してください。単一の接続r2d2とプール内の単一のスレッドを実行することは、書き込みの多いsqliteアプリケーションで最適な場合があります(そのような場合は適切なデータベースをお勧めします)。
古い答え
機能する可能性のある古いソリューション
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
本質的に、Futures-cpupoolを推奨します。
将来のrsでブロッキングI / Oをカプセル化するための最良のアプローチは何ですか?
一般的な場合はFutures-cpupoolをお勧めします。
機能しない古いソリューション
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
古いactix-webバージョンの本当に素晴らしい修正。私が見つけることができるものから、リクエストにはもはやCPUプールがありません。
futures-cpupool
でのasync
サポートの欠如に対する推奨される回避策のようです。