私は、ユーザーリクエストを処理し、ミドルウェアと話し合い、応答を送信するnettyに実装されたサーバーを持っています。 I/Oは、ミドルウェアへのラウンドトリップに比べて無視できると予想されるため、ブロックを最小限に抑えるため、OrderedMemoryAwareThreadPoolExecutorの上にあるパイプラインにExecutionHandlerがあります。これまでのところ問題はありません。ThreadPoolExecutorsでのNettyタスクの優先順位付け
負荷の高い状態でのサーバーの動作を見ています。私たちのプロトコルの過去の経験から、私たちは偶発的なDOS攻撃に悩まされがちです。ほとんどの場合、ユーザのスクリプトは無限ループに似ています。理想的には、チャンネルが特定の使用率しきい値を超えたときに優先順位を解除し、他のユーザーのサービスに影響を与えないようにすることができます。
私は、PriorityBlockingQueueを使用する単純なThreadPoolExecutorを実装し、独自のSessionクラス(ChannelHandlerのコンテキストに添付)から抽出されたデータに基づいて優先順位を設定します。もう一度、これまでのところ問題はありません。
Nettyの組み込みThreadPoolExecutorsの順序付けとメモリ認識を利用しようとすると、問題が発生します。理想的には、MyThreadPoolExecutorは、OrderedMemoryAwareThreadPoolExecutorを拡張して、優先順位のキューに入れることができます。悲しいことに、プライベートとファイナルの2つの理由からこれは不可能です。より詳細には:
A)ThreadPoolExecutor.workQueueはそのコンストラクタで設定することができますが、LinkedTransferQueueとしてMemoryAwareThreadPoolExecutorがハードコードこの、およびその子にこれを公開しないOrderedMemoryAwareThreadPoolExecutor(すなわちMyThreadPoolExecutorを設定するためのアクセス権を持っていませんそれ)。必要に応じて、これは反射ベースのプライベートフィールド調整の醜いビットで克服することができます。
b)MyThreadPoolExecutor.doUnorderedExecute()をオーバーライドして、優先処理を挿入して必要なオブジェクトを構築できるようにしたいと思いますが、final宣言しました。それを呼び出すコードは変更する必要はありません。
解決済みの点は、すてきなネットフィーチャを保つことですが、優先度キューを使用すると、OrderedMemoryAwareThreadPoolExecutorとMemoryAwareThreadPoolExecutorの両方をコピーして、それぞれの行を調整してそこから拡張する必要があります。これは良いコーディング練習として私を攻撃しない!それを考慮しても、警鐘を放つ。今、いくつかの質問に
:
1)私が間違っている問題を解決するだろうか?私が達成したいことを間違った木全体を吠えるか?
2)そうでない場合は、上記の方法よりも良い方法がありますか?
3)上記のアプローチでは、サーバーの負荷の合計が一貫して不足している優先度の低いタスクでは、枯渇する危険性があります。私は「いたずらな」ユーザーのためにこれを容認する用意ができていますが、通常の状態に戻ったらすぐに既存のタスクは飢えていて、順序を保持するために新しい優先度の高いタスクを追加する必要があります。これに対処する最良の方法についての推奨事項はありますか? (禁止のユーザーはビジネスで許可されていません)
4)半分質問です。 OrderedMemoryAwareThreadPoolExecutorのnettyドキュメントには、スレッドXの便利な図があります& Y - おそらくこれらはThreadPoolExecutorにプールされ、I/Oワーカースレッドではないスレッドですか?これをもっと明確にする価値があります。また、ExecutionHandlerを使用しない場合、各チャネルは単一のI/Oワーカースレッドにバインドされます.ExecutionHandlerの背後にある場合でもこれが当てはまりますか?つまり、チャネルに到着した順序と同じになることが保証されたExecutionHandlerにタスクが追加される順序ですか?この場合、MemoryAwareThreadPoolExecutorのドキュメントのスレッドXがイベント1よりも前にイベント2を処理する方法がわかりません - ここでは別のスレッドが任意の順序で作業を完了できますが、その作業がどのようにできるかはわかりません順番に同じスレッドに割り当てられます(workQueueからポップします)。 ExecutionHandlerのドキュメントでは、このことについてヒントがありますが、もう少し詳しくお話してください。
お読みいただきありがとうございました。ご協力いただければ幸いです。
このサーバーはまだ開発中ですが、置き換えられる(C++)サーバーは強くデータベースにバインドされています。私たちは、ワーカースレッドのプールが限られているため、データベースの負荷が高い(悪いニュース)可能性を解決しましたが、これは、1人の空腹のユーザーがすべてのワーカーをチャンプ化し、他の人のサービスを悪化させる可能性を認めました維持するために非常にタイトなSLA)。古いサーバーでのこの問題に対する私たちの解決策は、ネットの下に保持されていない仮定に基づいていたので、何か良い点を考え出す必要があります。私たちはまだプールのサイズを心配していません! – Liche