RESTful スタイルの RPC (リモート プロシージャ コール) API を tomcat サーバーで実行しており、N ユーザーのデータを K スレッドで M タスクで処理しています。ほとんどの場合、1 人のユーザーが約 20 から 500 のタスクを持っています (ただし、M は 1 から 5000 の間である可能性があります)。1 つのタスクが完了するまでに約 10 秒から 20 秒かかりますが、1 秒から 20 分かかる場合もあります。現在、ほとんどのシステムには 1 人のユーザーがいて、時には 3 人までいますが、近い将来には同時に約 10 人のユーザーに増加します。サーバーには 10 個のコアがあるため、10 個のスレッドを使用したいと考えています。現時点では、すべてのユーザーが処理用に 5 つのスレッドを取得していますが、これは正常に機能しています。しかし、a) ほとんどの場合、マシンは 50% しか使用されず (針が「30 分」の範囲で待機することになります)、サーバーの負荷が最大 150% になることもあります。
ソリューションの要件:
- 常にサーバーが 100% 使用されている (タスクがある場合)
- スレッドの実行に関して、すべてのユーザーが同じように扱われる (他のすべてのユーザーと同じ量のスレッドが終了する)
- 新しいユーザーは、以前のユーザーのすべてのタスクが完了するまで待つ必要はありません (特に、user1 に 5000 のタスクがあり、user2 に 1 つのタスクがある場合、これは重要です)。
頭に浮かぶ解決策:
10 個のスレッドで FixedThreadPoolExecutor を使用するだけで、条件 3 に違反します
PriorityBlockingQueue を使用し、タスクに compareTo メソッドを実装します -> threadpoolExecutors submit メソッドを使用できません (したがって、送信されたタスクがいつ終了するかわかりません)
ブロッキング キューのような「ラウンド ロビン」を実装します。この場合、K 個のスレッド (この場合は 10 個) が N 個の内部キューからラウンド ロビン方式で新しいタスクを取得します -> タスクを適切なキューに配置できるようにするには、複数のパラメーターを取る「送信」メソッド (ThreadPoolExecutor も実装する必要があります)
ブロッキング キューのようなラウンド ロビンの意味を説明しようとしました (役に立たない場合は、自由に編集してください)。
-- -- -- -- -- -- queue task load, -- -- -- -- -- -- -- one task denoted by -- -- -- -- -- -- -- -- -- | Q1 | Q2 | Q3 | Q4 | Q5 | Q6 | Q7 | QN | | * ^ | | last| |next | | ------------- \ / \ | | | | | | T1 | T2 | T3 | T4 | TK |
この種の処理動作を実現するために、主に Java 標準 API (または他の広く普及している Java API) を使用するエレガントなソリューションはありますか? または、この問題に取り組む方法について他に何かヒントはありますか?