最大CloudQueueMessage有效负载大小问题

时间:2011-07-06 12:09:50

标签: c# azure-storage azure-queues

根据MSDN,消息有效负载最多可扩展到8KB(8192字节):

  

AddMessage方法将消息添加到队列的后面。   消息最大可达8 KB。其内容必须采用可以使用UTF-8编码的格式。

但是,在将消息添加到队列中时,我收到的有效负载小于8192字节的消息的异常,魔术区域似乎大约为6500字节。我发送的数据是纯字符串,其大小从.Length成员和源检索到的长度进行验证(对于CRLF分隔符,存在恒定的2字节差异)。 / p>

所以我的问题是双重的:

1)是否有任何隐藏数据附加到消息有效负载上会导致其大小或导致这种奇怪的行为? (例如限制作为一个整体应用于对象,而不仅仅是它的有效载荷,但即便如此,它如何能够为每条消息占1.5KB?)

2)我如何可靠地检查有效载荷是否确实低于8192?

以及一些额外的信息:我正在使用Azure SDK 1.4和VS 2010 Ultimate,通过计算和运行存储模拟器(我还没有部署这个应用程序)使用SQLExpress(2008年我认为)。

还通过代码确认最大大小为8192字节(如果有一些额外的系统强制限制):

Trace.WriteLine("Max Queue Message Size: " + CloudQueueMessage.MaxMessageSize, "CloudQueueMessage");
  

CloudQueueMessage:最大队列邮件大小:8192

1 个答案:

答案 0 :(得分:9)

.NET存储客户端库(Microsoft.WindowsAzure.StorageClient.dll)base-64编码队列消息内容,因此当您使用时,有效限制为8192 * .75 = 6144 字节.NET客户端库。 (那是因为base 64编码会增加1/3的开销。)

(请注意,你没有 以64位编码。这恰好是这个库确保队列消息的内容可以安全地嵌入XML中的方式,这就是要求队列服务放置在消息上。)


编辑:这是使用Microsoft.WindowsAzure.StorageClient.Protocol命名空间将原始文本(不是base 64编码)放入队列消息(并随后检索它)的示例代码:

using System;
using System.Net;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.StorageClient.Protocol;

class Program
{
    static void Main(string[] args)
    {
        var q = CloudStorageAccount.Parse("UseDevelopmentStorage=true").CreateCloudQueueClient().GetQueueReference("testqueue");
        q.CreateIfNotExist();

        var req = QueueRequest.PutMessage(new Uri(q.Uri, q.Name + "/messages"), 30, null);
        var body = QueueRequest.GenerateMessageRequestBody("hello world");
        req.ContentLength = body.Length;
        q.ServiceClient.Credentials.SignRequest(req);
        using (var stream = req.GetRequestStream())
        {
            stream.Write(body, 0, body.Length);
            stream.Close();
        }
        req.GetResponse();

        req = QueueRequest.GetMessages(new Uri(q.Uri, q.Name + "/messages"), 30, 32, null);
        q.ServiceClient.Credentials.SignRequest(req);
        using (var response = (HttpWebResponse)req.GetResponse())
        {
            using (var msgResponse = QueueResponse.GetMessages(response))
            {
                foreach (var msg in msgResponse.Messages)
                {
                    Console.WriteLine("MESSAGE: " + msg.Text);
                    q.DeleteMessage(msg.Id, msg.PopReceipt);
                }
            }
        }

        q.Delete();
    }
}