ディーゼルを同期アクター、actix_web :: web :: blockまたはfutures-cpupoolを使用して実行する必要がありますか?


10

バックグラウンド

私は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サポートの欠如に対する推奨される回避策のようです。
Jmb

それはより一般的な解決策です。actixシステムを活用できるものを期待しています。それでもなお、今度はfutures-cpupoolを掘り下げて問題を探します。
logina

Stack Overflowへようこそ!あなたの質問は、将来のrsでブロックI / Oをカプセル化するための最良のアプローチ何ですか?。そうでない場合は、質問を編集して違いを説明してください。それ以外の場合は、この質問にすでに回答済みのマークを付けることができます。
Shepmaster

cpupoolはr2d2のブロッキング接続プールとも相互作用するため、それを最適に解決する方法がわかりません。私は自分で調べていますが、すぐに更新されます。
logina

回答:


3

futures-cpupoolを使用します。それは私の相互作用のブロッキングの性質による最良の解決策です。

actix_web :: web :: blockの使用は十分ですが、actixで共有スレッドプールを使用します(ブロッキング呼び出しのため、これを使用してスレッドプール全体をブロックし、actix_webに与えられた他のタスクを妨害することができます)。

データベースの相互作用のためだけに、futures-cpupoolを使用してデータベースごとに個別のスレッドプールを作成することをお勧めします。このようにして、相互に待機する必要があるすべてのタスク(接続よりもタスクが多い場合)を1つのプールにグループ化し、接続を必要としない他のタスクをブロックするのを防ぎ、スレッド数を接続の数(タスクがブロックされないときにのみスケジュールされるようにするため)。

1つのデータベース接続のみ(またはごくわずか)を使用したい場合は、同期アクターは非常に良いオプションです。これは、1つのスレッドを持つfutures-cpupoolのように動作し、すべてのタスクが一度に1つずつ実行されることを保証します。ただし、別個のスレッドではなく、actix-webの基盤となるスレッドの1つを使用します(したがって、接続数が非常に少ない場合にのみ有効です)。 。ただし、定型文は大きすぎて価値がありません。


6
上記の私の調査結果を読んだに関連してくださいプット情報- 答え答え、ない質問。
Shepmaster
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.