我正在使用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中的一个辅助角色中计划的,所以我不能这样做。
我有其他功能可以插入表服务,它们的运行速度同样快但没有任何问题。看起来几乎像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.");
}
答案 0 :(得分:2)
Cloud [Blob | Table | Queue]客户端不维护状态,可以在多个对象中使用。
此问题与ServicePointManager变得过载有关。队列压力场景往往会加剧这种行为,因为它们执行许多小请求(在你的情况下是一个非常小的guid)。您可以采取一些缓解此问题的缓解措施
另外,关于表示实体没有显示相同行为的注释,表服务支持的当前有线协议是Atom / Pub,它可能非常繁琐(xml等)。因此,简单的实体插入比简单的队列guid消息大得多。基本上由于大小差异,表流量利用其下面的TCP层做得更好,所以这不是真正的苹果对比。
如果这些解决方案对您不起作用,那么获取有关您帐户的更多信息会很有帮助,以便我们在后端查看。
乔
答案 1 :(得分:0)
我怀疑是因为CloudQueueClient并不适合您进行多线程(异步)访问。
尝试在此{/ 1}}中重新创建CloudQueue
SendMessages
我在很多论坛上都看到CloudXXClient只能使用一次并处理掉。该校长可能适用于此。
没有太多的效率,因为客户端的ctor没有向队列发送请求并且存在线程问题。
答案 2 :(得分:0)
现在,Storage Client Library 2.0.5.1已经解决了这个问题。
或者,还有一种解决方法:卸载KB2750149。