私は、オファーを受け取り、「手を差し伸べる」ことに応答可能なWCFサービスを持っており、本質的に外部APIである潜在的なバイヤーのX人(通常は15〜20人)にこのオファーを動的に提供します。
現在、各購入者は 35 秒以内に応答を返すか、オファーを購入できなくなります。
これを達成するために、私は次のコードを用意しました。これは 8 か月間運用されており、かなりうまく機能し、スケーリングされています。
最近、さらに拡張できるように改善に多くの時間を費やしているため、このタスクを達成するためのより良いオプションがあるかどうかに関心がありました. 今のところうまく機能しているので変更をためらっていますが、集中できるうちに追加のパフォーマンスを引き出すことができるかもしれません.
次のコードは、バイヤーへのアウトバウンド リクエストを作成するタスクを作成します。
IBuyer[] buyer = BuyerService.GetBuyers(); /*Obtain potential buyers for the offer*/
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
Tasks = new Task<IResponse>[Buyers.Count];
for(int i = 0; i < Buyers.Count;i++)
{
IBuyer buyer = Buyers[i];
Func<IResponse> makeOffer = () => buyer.MakeOffer()
Tasks[i] = Task.Factory.StartNew<IResponse>((o) =>
{
try
{
var result = MakeOffer();
if (!token.IsCancellationRequested)
{
return result;
}
}
catch (Exception exception
{
/*Do Work For Handling Exception In Here*/
}
return null;
}, token,TaskCreationOptions.LongRunning);
};
Task.WaitAll(Tasks, timeout, token); /*Give buyers fair amount of time to respond to offer*/
tokenSource.Cancel();
List<IResponse> results = new List<IResponse>(); /*List of Responses From Buyers*/
for (int i = 0; i < Tasks.Length; i++)
{
if (Tasks[i].IsCompleted) /*Needed so it doesnt block on Result*/
{
if (Tasks[i].Result != null)
{
results.Add(Tasks[i].Result);
}
Tasks[i].Dispose();
}
}
/*Continue Processing Buyers That Responded*/
平均すると、このサービスは 1 日あたり 400K ~ 900K の範囲で呼び出され、1 秒あたり最大 30 ~ 40 回呼び出されることもあります。
パフォーマンスを調整するために多くの最適化を行いましたが、このコードに目立った問題がないことを確認したいと思います。
TaskScheduler のパワーと、SynchronizationContext をいじって非同期で動作することについて多くのことを読みましたが、それをどのように適合させることができるか、改善する価値があるかどうかはわかりません。