C#スレッドプーリングHttp Web要求
-
05-07-2019 - |
質問
スレッドプーリングの例をいくつか読んで見ましたが、必要な方法を理解できないようです。私が何とか働けるようになったのは、本当に必要なものではありません。独自のスレッドで関数を実行するだけです。
public static void Main()
{
while (true)
{
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Process));
Console.WriteLine("ID has been queued for fetching");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
Console.ReadLine();
}
}
public static void Process(object state)
{
var s = StatsFecther("byId", "0"); //returns all player stats
Console.WriteLine("Account: " + s.nickname);
Console.WriteLine("ID: " + s.account_id);
Console.ReadLine();
}
私がやろうとしているのは、プレーヤーの統計情報を含むシリアル化されたphpデータを取得する約50のスレッド(おそらくそれ以上)を使用することです。ユーザー0から開始して、指定したユーザーID(300,000)まで。私の質問は統計を取得する方法についてではなく、統計を取得して読み取る方法を知っていますが、他のスレッドのつま先を踏まずに300,000番目のユーザーIDに達するまで統計を取得し続けるスレッドプールをどのように書くかデータベースに取得するときに統計を保存します。
解決
static int _globalId = 0;
public static void Process(object state)
{
// each queued Process call gets its own player ID to fetch
processId = InterlockedIncrement(ref _globalId);
var s = StatsFecther("byId", processId); //returns all player stats
Console.WriteLine("Account: " + s.nickname);
Console.WriteLine("ID: " + s.account_id);
Console.ReadLine();
}
これは最も簡単なことです。しかし、最適にはほど遠い。同期呼び出しを使用しており、ThreadPoolを使用して呼び出し速度を調整しています。失敗した呼び出しに対する再試行ポリシーはなく、アプリケーションはエラー状態(Web呼び出しが失敗した場合)で非常に悪い動作をします。
まず、WebRequestの非同期メソッドの使用を検討する必要があります。 BeginGetRequestStream (POSTでリクエスト本文がある場合)および/または BeginGetResponse 。これらのメソッドは非常に優れた拡張性を備えており、少ないCPUで高いスループットを得ることができます(バックエンドがもちろん対応できる場合)。
次に、自己投球を検討する必要があります。同様のプロジェクトで、保留中のリクエストカウントを使用しました。成功すると、各コールは、スロットルカウントを上限として、さらに2つのコールを送信します。失敗すると、呼び出しは何も送信しません。保留中の呼び出しがない場合、タイマーベースの再試行は1分ごとに新しい呼び出しを送信します。この方法では、サービスがダウンしているときに1分に1回だけ試行し、トラクションなしでスピンすることからリソースを節約し、サービスがアップしているときにスループットをスロットルキャップに戻します。
.Netフレームワークは、リソースに対して行う同時接続の数を制限することも知っておく必要があります。宛先 ServicePoint を見つけて変更する必要があります。 ConnectionLimit をデフォルト値(2 )スロットルするのをいとわない最大値まで。
データベースの更新部分については、多くの変数を使用する方法があり、有意義なアドバイスを提供するには情報が少なすぎます。いくつかの一般的なアドバイスは、データベース呼び出しで非同期メソッドを使用することです。あなたのスロットルキャップを可能にするためにyoru connecitonプールのサイズを変更し、異なるスレッドから同じレコードを更新する際にデッドロックしないように更新がプレーヤーIDをキーとして使用することを確認。
他のヒント
どのようにしてユーザーIDを決定しますか? 1つのオプションは、スレッドXが0〜NのIDを処理するようにすべてのスレッドをセグメント化することです。