利用 Amazon Web Services 集成企业应用程序--使用 Amazon SQS 发送 XML 消息

探索如何利用 XML 和 Amazon Web Services 集成企业应用程序,以及使用Microsoft® .NET (C#) 和 Java 平台构建跨平台应用程序集成功能。

队列 是用于存储等待处理的消息的临时数据结构。Amazon Simple Queue Services (Amazon SQS) 是一个支持 Web 服务的高可用性可伸缩消息队列。Amazon SQS 的主要益处包括:

基于云的解决方案。由 Amazon 管理,不需使用私有基础设施,也不需要专业支持知识。 基于 Internet。任何连接到 Internet 的客户端都可以通过 Web 服务访问该服务,因此支持业务到业务(B2B)集成。 冗余。该服务在多个服务器上存储所有消息,以提供高可用性和容错。 多个并发读/写。Amazon SQS 支持多个进程同时读写一个队列,以及在处理窗口时锁定消息,以避免两个客户端同时处理一条消息。 可配置。通过使用 Amazon SQS 服务,您可以根据存储在队列中的消息的处理需求设计和锁定窗口。锁定窗口能够阻止两个队列读取器同时处理同一个队列项。对于处理时间更长的队列项,则需要更长时间地锁定窗口。锁定窗口由可见性超时参数控制,您可以给每个队列配置该参数。 易于使用的 API。它为常见的语言(包括 Java 和 Microsoft .NET 平台)提供 API 包装器,以支持快速开发并无缝地集成到现有应用程序中。 低成本的解决方案。公司仅需为它们的 HTTP 请求使用的带宽付费;Amazon SQS 不收取其他额外的费用。

在开始 Amazon SQS 开发之前,了解它的一些特征是非常有帮助的。如果不了解这些特征,您刚开始使用 Amazon SQS 时可能会碰到挫折,或感到困惑。

首先,Amazon 不能保证队列项的处理顺序。这意味着先进先出(first-in-first-out,FIFO)处理不得到保证,这在很多消息队列实现中都很常见。Amazon 仅保证所有消息都分发出去。

Amazon SQS 的第二大特征是最终一致性。大型数据库系统的主要特征是一致性、高可用性和可伸缩性。Amazon 不是关注所有 3 个特征,而是主要关注高可用性和可伸缩性,然后再以此为基础提供最终的一致性。这意味着 Amazon 通过将所有消息发送到多个服务器来实现高可用性和可伸缩性。Amazon 保证最终会将所有消息分发出去,但不保证什么时候分发它们。从实用的角度看,这意味着假如您向一个队列发送 3 条消息,当下次尝试接收这些消息时,不一定能收到所有 3 条消息。您可能在一个 Read 中收到所有 3 条消息,或在第一个 Read 中收到前两条消息,在第二个 Read 中收到第三条消息。如果您持续地轮询该队列,最终肯定能收到所有 3 条消息。

为了开始使用 Amazon SQS,您必须根据自己使用的语言获取 Amazon SQS 的 API 库。Amazon 为所有常见的语言都提供了一个库,比如 Perl、Microsoft Visual Basic®.NET、C#、Java 和 PHP。这些库是开源的,并且易于使用。参考资料小节提供这些库的下载链接。

通过 Java 语言使用 Amazon SQS

现在您首先学习如何使用 Java 语言创建队列、发送消息和接收消息。第一步是创建一个 Amazon SQS 队列。清单 1 中的代码显示了如何为 Amazon SQS 创建 HTTP 客户端、实例化 CreateQueueRequest 对象和调用队列创建请求。Access Key ID(由 20 个字母和数字组成)是请求身份验证或读取队列项所需的密匙。为了创建或操作队列项,您需要使用 Secret Access Key(由 40 个字母和数字组成)。注册 Amazon 时就会收到这些密匙
清单 1. 创建 Amazon SQS 队列

String queueName = "TestQueue";// create http clientAmazonSQS service = new AmazonSQSClient(accessKeyId, secretAccessKey);// instantiate create queue requestCreateQueueRequest request = new CreateQueueRequest();request.setQueueName(queueName);request.setDefaultVisibilityTimeout(30);// execute create queue operation and get the server responseSystem.out.print("Creating Queue: " + queueName); CreateQueueResponse response = service.createQueue(request);if (response.isSetCreateQueueResult()) { System.out.print("Create Queue Result:"); CreateQueueResult createQueueResult = response.getCreateQueueResult(); if (createQueueResult.isSetQueueUrl()) { System.out.print("Queue Url: " + createQueueResult.getQueueUrl()); }}

下一步是向最新创建的队列发送一条消息。清单 2 中的代码显示了如何为 Amazon SQS 创建 HTTP 客户端,以及如何向队列发送一个简单的消息。

清单 2. 向队列发送消息

String queueName = "TestQueue";// create http clientAmazonSQS service = new AmazonSQSClient(accessKeyId, secretAccessKey);// instantiate send message requestSendMessageRequest request = new SendMessageRequest();request.setQueueName(queueName);request.setMessageBody("Test SQS Message");// execute the send message operation and get the server responseSendMessageResponse response = service.sendMessage(request);if (response.isSetSendMessageResult()) { System.out.print("Send Message Result: "); SendMessageResult sendMessageResult = response.getSendMessageResult(); if (sendMessageResult.isSetMessageId()) { System.out.print("\tMessageId: " + sendMessageResult.getMessageId()); }}

现在,我们尝试从队列接收消息。清单 3 显示了如何为 Amazon SQS 创建 HTTP 客户端,以及如何从队列接收消息。Message 包含来自队列的消息并公开几个关键方法:

getMessageId。返回消息的唯一标识符。您可以使用 isSetMessageId 确定消息 ID 是否已设置。 getReceiptHandle。将句柄返回给消息。句柄用于删除消息。您可以使用 isSetReceiptHandle 确定消息句柄是否已设置。 getBody。以字符串的形式返回消息体。消息可以是纯文本或 XML,您可以使用 isSetBody 确定消息体是否已设置。

清单 3. 从队列接收消息

String queueName = "TestQueue";// create http clientAmazonSQS service = new AmazonSQSClient(accessKeyId, secretAccessKey);// instantiate the receive message requestReceiveMessageRequest request = new ReceiveMessageRequest();request.setQueueName(queueName);// the following two parameters are optionalrequest.setMaxNumberOfMessages(10); // set maximum number of messages to receiverequest.setVisibilityTimeout(30); // set visibility window // execute the receive messages operation and get server responseReceiveMessageResponse response = service.receiveMessage(request);System.out.print("Receive Message Response:");if (response.isSetReceiveMessageResult()) { ReceiveMessageResult receiveMessageResult = response.getReceiveMessageResult(); java.util.List<Message> messageList = receiveMessageResult.getMessage(); for (Message message : messageList) { if (message.isSetMessageId()) { System.out.print("MessageId: " + message.getMessageId()); } if (message.isSetReceiptHandle()) { System.out.print("ReceiptHandle: " + message.getReceiptHandle()); } if (message.isSetBody()) { System.out.print("Body: " + message.getBody()); }}

通过 C# 使用 Amazon SQS

现在,您将使用 C# 将一个对象系列化到 XML,并将其作为 Amazon SQS 消息发送。

第一步是创建一个将被系列化的业务对象;清单 4 显示了一个 Product 对象。公共属性被控制 XML 系列化的属性修饰。C# 属性类似于 Java 注释,定义属性如何映射到 XML 元素或 XML 属性。此外,这个类包含将对象实例系列化到 XML 的 ToXml() 方法。

清单 4. 创建用于系列化的业务对象

namespace Stewart.Test{/// <summary>/// Product/// </summary>[XmlRoot(ElementName="Product")]public class Product{ /// <summary> /// Product Name /// </summary> [XmlElement("ProductName")] public string ProductName; /// <summary> /// Product Price /// </summary> [XmlElement("ProductPrice")] public decimal ProductPrice; /// <summary> /// Quantity in stock /// </summary> [XmlElement("InStock")] public bool InStock; /// <summary> /// Product Id /// </summary> [XmlAttributeAttribute(AttributeName = "Id", DataType = "integer")] public string Id; /// <summary> /// Initializes a new instance of the <see cref="Product"/> class. /// </summary> public Product() { } /// <summary> /// Initializes a new instance of the <see cref="Product"/> class. /// </summary> /// <param name="productName">Name of the product.</param> /// <param name="productPrice">The product price.</param> public Product(string productName, decimal productPrice) { this.ProductName = productName; this.ProductPrice = productPrice; } /// <summary> /// Converts to XML. /// </summary> /// <returns></returns> public String ToXml() { StringBuilder output = new StringBuilder(); // no name space XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); // settings to omit xml declaration XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; // finally serialize to string XmlWriter writer = XmlTextWriter.Create(output, settings); XmlSerializer serializer = new XmlSerializer(typeof(Product)); serializer.Serialize(writer, this, ns); // return string containing XML document return output.ToString(); }}

接下来,发送 XML 消息。用于 Amazon SQS 的 Amazon C# API 在功能上类似于 Java API。清单 5 中的代码显示了如何使用 C# 发送消息。

清单 5. 使用 C# 发送消息

Product prod = new Product("Widget", 1.5M);string accessKeyId = ConfigurationSettings.AppSettings["AmazonAccessKeyID"];string secretAccessKey = ConfigurationSettings.AppSettings["AmazonSecretAccessKey"];AmazonSQS service = new AmazonSQSClient(accessKeyId, secretAccessKey);SendMessageRequest request = new SendMessageRequest();request.MessageBody = prod.ToXml();request.QueueName = "TestQueue";SendMessageResponse response = service.SendMessage(request);if (response.IsSetSendMessageResult()){ Console.WriteLine("Send Message Response: "); SendMessageResult sendMessageResult = response.SendMessageResult; if (sendMessageResult.IsSetMessageId()) { Console.WriteLine(String.Format("MessageId {0}", sendMessageResult.MessageId)); } if (sendMessageResult.IsSetMD5OfMessageBody()) { Console.WriteLine(String.Format("MD5OfMessageBody: {0}", sendMessageResult.MD5OfMessageBody)); }}

图 1 显示了 清单 5 的输出结果。

图 1. 发送 XML 消息的输出

最后一步是从队列接收 XML 消息,并反系列化实例。清单 6 显示了将 XML 消息反系列化到 Product 实例的代码。

清单 6. 反序列化 XML 消息

Product prod = null; string accessKeyId = ConfigurationSettings.AppSettings["AmazonAccessKeyID"];string secretAccessKey = ConfigurationSettings.AppSettings["AmazonSecretAccessKey"];AmazonSQS service = new AmazonSQSClient(accessKeyId, secretAccessKey);ReceiveMessageRequest request = new ReceiveMessageRequest();request.QueueName = "TestQueue";ReceiveMessageResponse response = service.ReceiveMessage(request);if (response.IsSetReceiveMessageResult()){ Console.WriteLine("Receive Message Result:"); ReceiveMessageResult receiveMessageResult = response.ReceiveMessageResult; List<Message> messageList = receiveMessageResult.Message; foreach (Message message in messageList) { if (message.IsSetMessageId()) { Console.WriteLine(String.Format("MessageId: {0}", message.MessageId)); } if (message.IsSetBody()) { Console.WriteLine(string.Format("Body: {0}", message.Body)); String xml = message.Body; StringReader sr = new StringReader(xml); XmlSerializer serializer = new XmlSerializer(typeof(Product)); prod = (Product) serializer.Deserialize(sr); Console.WriteLine(string.Format("Id: {0}", prod.Id)); Console.WriteLine(string.Format("Name: {0}", prod.ProductName)); Console.WriteLine(string.Format("Price: {0}", prod.ProductPrice)); } }}

图 2 显示了 清单 6 的输出结果。

图 2. 接收 XML 消息输出

尽管以上的例子非常简单,但是它们是非常强大的,因为您可以系列化一个对象,并向另一个不局限于本地物理网络的应用程序发送消息。这里没有复杂的防火墙限制或安全性考虑事项。此外,不需要用相同的语言编写消息的发送器和接收器,甚至不需要使用相同的平台。

技术概述和设计

这个示例解决方案包含需要集成业务流程的分销商和制造商。分销商 从制造商 处购买商品并出售给客户。

当客户需要商品时,分销商使用 C# WinForm 客户端提交一个客户订单。订单提交程序将订单细节存储在一个本地 MySQL 数据库中。该客户端还允许用户浏览库存、查看订单和 Amazon SQS 队列。

一般而言,分销商的库存能够满足客户的订购需求。如果库存不足的话,分销商会及时向制造商发送一个购买订单。然后,当物品已经发出时,制造商发送回一个订单汇总。所有这些通信都使用 Amazon SQS 来完成。

分销商的 Order Fulfillment 和 Inventory Management 服务也是使用 C# 构建的,它轮询进入的商品和待处理的客户订单。当处理客户订单时发现商品库存少于订购数量,那么将使用 Amazon SQS 向制造商发送一个购买订单。队列项的消息体是一个包含购买订单的 XML 文档。

制造商的 Order Processing Service 是基于 Java 平台构建的,它处理购买订单队列。当物品已经发出时,它将使用 Amazon SQS 向分销商回复一条消息。该消息的消息体是包含订单汇总的 XML 文档。

图 3 显示了涉及到的系统。

图 3. 解决方案概图

创建 XML 模式

第一步是为在分销商和制造商之间发送的消息定义 XML 模式。您需要两个模式:一个购买订单和一个订单汇总。

清单 7 显示了购买订单的模式。

清单 7. 购买订单模式

<?xml version="1.0" encoding="utf-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="PurchaseOrder"> <xs:complexType> <xs:sequence> <xs:element name="Id" type="xs:string" minOccurs="0" /> <xs:element name="OrderDate" type="xs:string" minOccurs="0" /> <xs:element name="Company" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="CompanyName" type="xs:string" minOccurs="0" /> <xs:element name="StreetAddress" type="xs:string" minOccurs="0" /> <xs:element name="City" type="xs:string" minOccurs="0" /> <xs:element name="State" type="xs:string" minOccurs="0" /> <xs:element name="ZipCode" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Vendor" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="CompanyName" type="xs:string" minOccurs="0" /> <xs:element name="StreetAddress" type="xs:string" minOccurs="0" /> <xs:element name="City" type="xs:string" minOccurs="0" /> <xs:element name="State" type="xs:string" minOccurs="0" /> <xs:element name="ZipCode" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Items" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="Item" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="Id" type="xs:string" /> <xs:attribute name="Name" type="xs:string" /> <xs:attribute name="Quantity" type="xs:string" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Purchase Order XML 模式包含下列关键元素:

表 1. 购买订单模式中的关键元素

关键元素

描述

Id

包含 Purchase Order 的唯一标识符的字符串

OrderDate

包含 Purchase Order 日期的字符串

Company

包含分销商的关键地址信息,包括公司名称、街道地址、城市、州和邮政编码

Vendor

包含制造商的关键地址信息,包括公司名称、街道地址、城市、州和邮政编码

Items

包含订购商品的所有信息,包括商品 ID、商品名称和数量

清单 8 显示了订单汇总的模式。

清单 8. 订单汇总模式

<?xml version="1.0" encoding="utf-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="OrderSummary"> <xs:complexType> <xs:sequence> <xs:element name="OrderId" type="xs:string" minOccurs="0" /> <xs:element name="ReferenceId" type="xs:string" minOccurs="0" /> <xs:element name="OrderDate" type="xs:string" minOccurs="0" /> <xs:element name="CompanyAddress" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="CompanyName" type="xs:string" minOccurs="0" /> <xs:element name="StreetAddress" type="xs:string" minOccurs="0" /> <xs:element name="City" type="xs:string" minOccurs="0" /> <xs:element name="State" type="xs:string" minOccurs="0" /> <xs:element name="ZipCode" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="CustomerAddress" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="CompanyName" type="xs:string" minOccurs="0" /> <xs:element name="StreetAddress" type="xs:string" minOccurs="0" /> <xs:element name="City" type="xs:string" minOccurs="0" /> <xs:element name="State" type="xs:string" minOccurs="0" /> <xs:element name="ZipCode" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Items" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="Item" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="ItemId" type="xs:string" /> <xs:attribute name="ItemName" type="xs:string" /> <xs:attribute name="Quantity" type="xs:string" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Order Summary XML 模式包含下列关键元素:

表 2. 订单汇总模式中的关键元素

Id

包含 Order Summary 的唯一标识符的字符串

ReferenceId

包含初始 Purchase Order 的 ID 的字符串

OrderDate

包含 Order Summary 日期的字符串

时间: 2024-08-30 09:23:52

利用 Amazon Web Services 集成企业应用程序--使用 Amazon SQS 发送 XML 消息的相关文章

利用Amazon Web Services集成企业应用程序

队列 是用于存储等待处理的消息的临时数据结构.Amazon Simple Queue Services (Amazon SQS) 是一个支持 Web 服务的高可用性可伸缩消息队列.Amazon SQS 的主要益处包括: 基于云的解决方案.由 Amazon 管理,不需使用私有基础设施,也不需要专业支持知识. 基于 Internet.任何连接到 Internet 的客户端都可以通过 Web 服务访问该服务,因此支持业务到业务(B2B)集成. 冗余.该服务在多个服务器上存储所有消息,以提供高可用性和容

利用Amazon Web Services(AWS)构建可扩展的WebApp应用

在上次(2008.01.10)简单了写了一篇<RubyOnRails + S3 + EC2 = ? >至今已经有段时间了,经过一段时间的发展,Amazon Web Services到今天已经相当成熟了,一整套的解决方案可以给Web App带来很多的便利,再一系列的改进措施后,AWS基本上是成熟了. 上面这个图片来源于slideshare上的一个PPT"Using Amazon SimpleDB with Ruby on Rails",正如我上面截取的这个图片说的: 静态文件

用 Amazon Web Services 进行云计算,第 1 部分: 简介

学习基本的 Amazon SimpleDB (SDB) 概念,研究 boto(一个用于与 SDB 交互的开放源码 Python 库)提供的一些功能.在这个 "用 Amazon Web Services 进行云计算" 系列中,学习如何使用 Amazon Web Services 进行云计算.了解这些服务如何为设计和构建可伸缩.可靠的应用程序提供一种可选方案.第一篇文章解释虚拟基础设施的构建块的特性.学习如何使用 Amazon Web Services 构建 Web 范围的系统. 什么是云

Amazon Web Services市场:API驱动型生态系统

API驱动型业务的概念近年来逐步兴起.事实上,人们发现在数字化业务领域,应用程序编程接口与产品间的界线正变得愈发模糊. 其基本概念确实非常强大:发布API.允许客户参与.最终利用其实现价值交换. 为了切实完成这项目标,我们当然需要具备一定规模的严肃业务以及与之相匹配的技术架构.举例来说,API最好得到严格定义,否则您的业务可能遭遇意想不到的影响.另外,API必须易于使用,否则将带来噩梦般的客户体验.另外,API必须能够进行成功整合,从而通过切实起效以实现对接.监控及获利. Amazon Web

用 Amazon Web Services 进行云计算,第 2 部分: 用 Amazon Simple Storage Service (S3) 在云中存储数据

学习基本的 Amazon SimpleDB (SDB) 概念,研究 boto(一个用于与 SDB 交互的开放源码 Python 库)提供的一些功能.在这个 "用 Amazon Web Services 进行云计算" 系列中,学习如何使用 Amazon Web Services 进行云计算.了解这些服务如何为设计和构建可伸缩.可靠的应用程序提供一种可选方案.本文讨论 Amazon Simple Storage Service (S3) 提供的可伸缩.高响应性的服务.了解用于与 S3 交互

在NetBeans中运行Amazon Web Services

Amazon提供了一个富web服务接口来访问他们的在线内容.为了帮助您理解如何使用这 些Web服务.Amazon还提供了一个全面的示例应用来展示如何使用所有被暴露出的操作.通 过一步步的操作,本文向您展示如何在NetBeans IDE中修改.构建.运行以及调试mazon的 示例应用程序.进而让您了解所有NetBeans的优点,比如代码补全.代码链接以及集成的 Javadoc帮助.还有调试程序的功能,尽管是单步的但监控的变量能够让您深入了解Amazon web服务的运行机制. 配置环境 安装Jav

用 Amazon Web Services 进行云计算,第 3 部分: 用 EC2 根据需要提供服务器

学习基本的 Amazon SimpleDB (SDB) 概念,研究 boto(一个用于与 SDB 交互的开放源码 Python 库)提供的一些功能.在这个 "用 Amazon Web Services 进行云计算" 系列中,学习如何使用 Amazon Web Services 进行云计算.了解这些服务如何为设计和构建可伸缩.可靠的应用程序提供一种可选方案.本文介绍 Amazon Elastic Compute Cloud (EC2) 提供的虚拟服务器.了解 EC2 如何帮助动态地配置应

Java 与 .NET 的基于 WS-Security的Web Services集成实现(上)

services|web Java 与 .NET 的基于 WS-Security的Web Services集成实现 rottenapple 本文适用读者: Web Services开发人员 应具备的知识: 使用过VS.NET2003 +WSE开发过Web Services,会使用Jbuilder9开发简单的java应用程序. 一:内容简介 WS-Security描述通过消息完整性,消息机密性和单独消息认证提供保护质量的SOAP消息传递增强.适用于下列场合: 1. 客户必须能够确定消息来自哪个人并

Java 与 .NET 的基于 WS-Security的Web Services集成实现(下)

services|web Java 与 .NET 的基于 WS-Security的Web Services集成实现(下) rottenapple 4. 打开Jbuilder9 ,新建一个java 类,命名为TestNetService.并将axis-wsse-1.0的jar包添加到Jbuilder的jdk中(Tools->configions jdks->class tab->add)代码如下: package MyWebServiceJavaClient; import java.ut