cloudQueue.BeginAddMessage と EndAddMessage を使用して多くのメッセージを送信しています。まだ返されていない開始の量を 500 に制限しています。それでも、コード 10048 (ソケットの枯渇を意味します) で例外が発生します。
Microsoft.WindowsAzure.Storage.StorageException: Unable to connect to the remote server ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted
レジストリを変更するようにすべてのアドバイスを検索した後に見つけた解決策ですが、これは Azure の worker ロールで計画されているため、それを行うことはできません。
テーブルサービスに挿入する他の機能があります。それらは同じように高速に動作しますが、問題はありません。EndAddMessage 関数が接続などを閉じていないようです (ソケットの理解が限られています)。
私の質問:ここで紺碧の側にバグはありますか? クロールへのメッセージの追加を人為的に遅くする以外に、これを修正するにはどうすればよいですか?
メッセージの送信に使用するテスト関数を次に示します。私の場合、約16500のメッセージが追加され、コールバックが適切に安定して終了した後、速度が低下し、しばらくすると前述の例外がスローされます。
長いコードで申し訳ありませんが、問題を再現するには、これをコピーして貼り付けてください。
から例外がスローされAsyncCallback endAddCallback
ます。
static void Main()
{
Console.SetBufferSize(205, Int16.MaxValue - 1);
// Set the maximum number of concurrent connections (12*6 in my case)
ServicePointManager.DefaultConnectionLimit = 12 * Environment.ProcessorCount;
//setting UseNagleAlgorithm to true reduces network traffic by buffering small packets of data and transmitting them as a single packet, but setting to false can significantly reduce latencies for small packets.
ServicePointManager.UseNagleAlgorithm = false;
//if true, "Expect: 100-continue" header is sent to ensure a call can be made. This uses an entire roundtrip to the service point (azure), so setting to false sends the call directly.
ServicePointManager.Expect100Continue = false;
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(__CONN_STRING);
CloudQueueClient client = storageAccount.CreateCloudQueueClient();
CloudQueue queue = client.GetQueueReference(__QUEUE_NAME);
queue.CreateIfNotExists();
List<Guid> ids = new List<Guid>();
for (Int32 i = 0; i < 40000; i++)
ids.Add(Guid.NewGuid());
SendMessages(queue, ids.Select(id => new CloudQueueMessage(id.ToString())).ToList().AsReadOnly());
}
public static void SendMessages(CloudQueue queue, IReadOnlyCollection<CloudQueueMessage> messages)
{
List<CloudQueueMessage> toSend = messages.ToList();
Object exceptionSync = new Object();
Exception exception = null;
CountdownEvent cde = new CountdownEvent(toSend.Count);
AsyncCallback endAddCallback = asyncResult =>
{
Int32 endedItem = (Int32)asyncResult.AsyncState;
try
{
queue.EndAddMessage(asyncResult);
Console.WriteLine("SendMessages: Ended\t\t{0}\t/{1}", endedItem + 1, toSend.Count);
}
catch (Exception e)
{
Console.WriteLine("SendMessages: Error adding {0}/{1} to queue: \n{2}", endedItem + 1, toSend.Count, e);
lock (exceptionSync)
{
if (exception == null)
exception = e;
}
}
finally { cde.Signal(); }
};
for (Int32 i = 0; i < toSend.Count; i++)
{
lock (exceptionSync)
{
if (exception != null)
throw exception;
}
//if number of added but not ended is larger than the MAX, yield and check again.
while (true)
{
Int32 currentOngoing = (i- (cde.InitialCount - cde.CurrentCount));
if (currentOngoing > 500)
Thread.Sleep(5);
else
break;
}
Console.WriteLine("SendMessages: Beginning\t{0}\t/{1}", i + 1, toSend.Count);
queue.BeginAddMessage(toSend[i], endAddCallback, i);
}
cde.Wait();
if (exception != null)
throw exception;
Console.WriteLine("SendMessages: Done.");
}