当前位置: 首页 > news >正文

Azure 基础:Queue Storage

Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob、Queue、File 和 Table。

笔者在前文中介绍了 File Storage 的基本用法,本文将介绍 Queue Storage 的主要使用方法。

Queue Storage 是什么?

Azure Queue Storage 是一个存储大量消息的存储服务,这些消息可以在任何地方通过 HTTP/HTTPS 访问。每条消息最大 64K,消息的数据量几乎不受限制 (除非超出了您的 Storage Account 的总容量) 。

下面是 Queue Storage 典型的应用场景:
1.    创建未处理任务的队列,以便异步的处理这些任务。
2.    把消息从 web role 传递给 worker role 进行处理。

Azure Queue Storage的结构

下图描述了 Queue Storage 的基本组织结构:

Azure Storage Account:

Storage Account 是用来管理 Azure Storage 的一个命名空间,主要用来控制存储数据的访问权限和计费。对 Blob、Queue、File 和 Table 这些 Azure 提供的存储服务的访问控制都是通过 Storage Account 来进行的,所以要想使用 Queue Storage,需要先创建你的 Storage Account。

Queue:

每个 Queue 都是一组消息的集合。每一条消息都必须属于一个 Queue。Queue 名称中的字符必须是小写。

Message:

每条 Message 的最大长度为 64KB,Message 在 Queue 中停留的最长时间为 7 天。

URL format:

Queue 的 URL 地址格式为:

http://<storage account>.queue.core.windows.net/<queuename>

下面是个更真实的例子:

http://nickstorage.queue.core.windows.net/app1tasks

如果您还不熟悉 Azure Storage Account 的使用,以及如何通过 WindowsAzure.Storage 库访问 Azure Storage,请参考前文《Azure Table storage 基本用法》中的介绍,这里就不重复了。

为了方便查看 C# 代码执行的结果,本文使用了 MS 发布的一个 Azure Storage 客户端工具:Microsoft Azure Storage Explorer,文中简称为 Storage Explorer。下面是 Queue Storage 的一个截图:

接下来我们通过 C# 代码来介绍如何操作 Queue Storage。

创建 Queue

我们先来创建一个名为 "app2tasks" 的 Queue:

复制代码
// CloudStorageAccount 类表示一个 Azure Storage Account,我们需要先创建它的实例,才能访问属于它的资源。
// 注意连接字符串中的xxx和yyy,分别对应Access keys中的Storage account name 和 key。
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=xxx;AccountKey=yyy");

// CloudQueueClient 类是 Windows Azure Queue Service 客户端的逻辑表示,我们需要使用它来配置和执行对 Queue Storage 的操作。
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
// CloudQueue 表示一个 Queue 对象, 绝大多数的操作都是通过这个对象完成的。
CloudQueue queue = queueClient.GetQueueReference("app2tasks");
// 如果不存在就创建名称为 "app2tasks" 的 Queue。
queue.CreateIfNotExists();
复制代码

执行上面的代码,然后在 Storage Explorer 中查看结果:

把消息插入 Queue

现实的应用场景中肯定有一个或多个程序产生 Message 并插入到 Queue 中,接下来我们看看用 C# 如何实现:

string current = DateTime.Now.ToString();
// 把消息插入到队列中。
CloudQueueMessage message = new CloudQueueMessage("Hello, World. -- " + current);
queue.AddMessage(message)

调用几次上面的代码看看结果如何:

我通过三次调用向 Queue 中加入了三条消息,请注意插入它们的时间,分别是 11:33:45,11:33:57,和 11.34:16。在接下来的描述中我分别称它们为第一条消息、第二条消息和第三条消息。

查看 Queue 中的消息

既然是队列,肯定有队头和队尾,消息从队头出队从队尾入队。那么能不能查看一下队头的消息 (也就是下一条要处理的消息,此处只是查看并不是要处理) 呢?当然可以:

// 总是取到队头的消息,没有消息出队。
// 消息在队列中的位置、可见状态也没有发生变化。 
CloudQueueMessage peekedMessage = queue.PeekMessage();

PeekMessage 方法总是取到处于队头位置的那条消息,并且不改变队列的状态!

为了帮助小伙伴们更深刻地理解 PeekMessage 方法的内涵,笔者从网上找了一张解释 peek 一词的图片,请注意图片中的黄色线条:

(本图片来自于互联网,如有版权问题请与笔者联系。)

查看 Queue 的长度

经常的查看 Queue 的长度是个不错的注意,因为你需要避免一些由于 Queue 过长带来的问题:

// 获取 Queue 的属性。
queue.FetchAttributes();
int? cachedMessageCount = queue.ApproximateMessageCount;

更新 Queue 中的消息

如果一条消息已经被添加到 Queue 中了,但是又需要更新其内容该怎么办?我们可以找到这条消息然后更新它的内容:

复制代码
CloudQueueMessage message = queue.GetMessage();
// 执行 getmessage(), 队头的消息会变得不可见。
message.SetMessageContent("Updated contents.");
queue.UpdateMessage(message,
    TimeSpan.FromSeconds(60.0), 
    MessageUpdateFields.Content | MessageUpdateFields.Visibility);
// 更新完消息内容的60s 之后,该消息会重新可见,但是是在队尾。
复制代码

执行上面的代码后,我们发现在 Storage Explorer 中"第一条消息"不见了。过了 60 秒之后它又重新出现在 Storage Explorer 中,但是它的内容已经变化,位置也成了队尾:

此时我们也只能通过 ID 认出它是之前的"第一条消息",之前"第二条消息","第三条消息"的位置也发生了相应的变化。

处理 Queue 中的消息

如何处理 Queue 中的消息呢?我们的程序大体应该遵循下面的逻辑:
使用 GetMessage 方法取出队头的消息,此时该消息会在 Queue 中 30 秒不可见(这个时常用户可以设置,默认是 30 秒);
处理消息;
正常处理完成后,调用 Delete 方法删除消息;
如果没有正常处理消息 (没有调用 Delete 方法),此消息会在 30 秒后重新出现在队尾。
类似于下面的代码逻辑:

复制代码
// 执行 getmessage(), 队头的消息会变得不可见。
CloudQueueMessage message = queue.GetMessage();
try
{
    //处理消息
    // 如果在30s内你没有删除这条消息,它会重新出现在队尾。
    // 所以正确处理一条消息的过程是,处理完成后,删除这条消息
    queue.DeleteMessage(message);
}
catch //(消息处理异常)
{ }
复制代码

删除 Queue 中的消息

除了正常处理完消息后把消息从队列中删除,我们也可以找到一条消息,直接删除它。本质上和处理完再删除是一样的。

总结

Queue Storage 为应用之间的解耦提供了很好的解决方式。使得消息的产生者和消息的处理者可以互相不知道彼此的存在。为我们处理这类问题添加了一件有力的武器。


本文转自sparkdev博客园博客,原文链接:http://www.cnblogs.com/sparkdev/p/6505431.html,如需转载请自行联系原作者

相关文章:

  • 机器学习算法 Python R速查表
  • Nginx+Keepalived主备
  • Spotify模式并非“敏捷涅磐”
  • SQLServer存储过程返回值总结
  • 算法笔记--中国剩余定理
  • 创建Kafka0.8.2生产者与消费者
  • IDEA在编辑时提示could not autowire
  • linux 使用记录
  • 关于ashx不可重定向问题
  • 有关“树上剩余几只鸟”的问题的思考及解答
  • 可以放在页面任何地方de 天气插件
  • yum安装指定版本的软件包的方法
  • 探秘Spring AOP (三) Spring AOP 使用讲解 2
  • 基于java config的springSecurity(四)--启用全局方法安全
  • 黑客预警:搞瘫北美互联网?规模更大的僵尸网络现身
  • 【个人向】《HTTP图解》阅后小结
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • docker python 配置
  • Java比较器对数组,集合排序
  • JAVA之继承和多态
  • Laravel 菜鸟晋级之路
  • nginx 负载服务器优化
  • Vue2.x学习三:事件处理生命周期钩子
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 阿里云前端周刊 - 第 26 期
  • 大数据与云计算学习:数据分析(二)
  • 简单实现一个textarea自适应高度
  • 力扣(LeetCode)22
  • 如何在 Tornado 中实现 Middleware
  • 少走弯路,给Java 1~5 年程序员的建议
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 异步
  • 带你开发类似Pokemon Go的AR游戏
  • ​LeetCode解法汇总518. 零钱兑换 II
  • (16)Reactor的测试——响应式Spring的道法术器
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (ZT)薛涌:谈贫说富
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (四)JPA - JQPL 实现增删改查
  • .Net Web窗口页属性
  • .NET 材料检测系统崩溃分析
  • [1] 平面(Plane)图形的生成算法
  • [20171113]修改表结构删除列相关问题4.txt
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [EFI]Lenovo ThinkPad X280电脑 Hackintosh 黑苹果引导文件
  • [element-ui] el-dialog 中的内容没有预先加载,因此无法获得内部元素的ref 的解决方案
  • [HCTF 2018]WarmUp (代码审计)
  • [i.MX]飞思卡尔IMX6处理器的GPIO-IOMUX_PAD说明
  • [IE编程] IE 是如何决定Accept-Language 属性的
  • [iOS]GCD(一)
  • [JS]数据类型
  • [LeetCode]—Implement strStr() 寻找子串匹配第一个位置 (KMP)
  • [Linux] Boot分区满了的处理方法 The volume boot has only 0 bytes disk space remaining
  • [MYSQL]mysql常用操作命令