面向服务的架构 - AMQP还是HTTP

65

一些背景。

非常庞大的 Django 应用程序。所有组件都使用相同的数据库。我们需要分离服务,这样我们就可以独立升级系统的某些部分而不影响其他部分。

我们使用 RabbitMQ 作为 Celery 的代理。

现在我们有两个选择:

  1. 使用 REST 接口的 HTTP 服务。
  2. 通过 AMQP 进行 JSONRPC 到事件循环服务

我的团队倾向于使用 HTTP,因为他们对此比较熟悉,但我认为使用 RPC 超过 AMQP 的优势远远超过了它。

AMQP 为我们提供了轻松添加负载平衡和高可用性的功能,并具有保证消息传递的能力。

而使用 HTTP,则必须创建客户端 HTTP 包装器以使用 REST 接口,必须放置负载均衡器并设置该基础架构才能具有 HA 等。

使用 AMQP,我只需生成服务的另一个实例,它将连接到与其他实例相同的队列,然后 HA 和负载平衡即可。

我对 AMQP 的想法有什么遗漏吗?

3个回答

105

起初,

  • REST、RPC - 架构模式,AMQP - 基于TCP/IP的线路级协议和基于HTTP的应用层协议
  • 相对于AMQP,HTTP是通用协议,因此HTTP的开销比AMQP高得多
  • AMQP的性质是异步的,而HTTP的性质是同步的
  • REST和RPC都使用数据序列化,格式取决于基础设施。如果你在所有地方都使用Python,我认为你可以使用Python本地序列化-pickle,这应该比JSON或任何其他格式更快。
  • HTTP+REST和AMQP+RPC都可以在异构和/或分布式环境中运行

因此,如果您要选择使用什么:HTTP+REST还是AMQP+RPC,答案实际上取决于基础设施复杂性和资源使用情况。在没有任何特定要求的情况下,两种解决方案都可以正常工作,但我宁愿进行一些抽象以便能够在它们之间透明地切换。

您说您的团队熟悉HTTP而不熟悉AMQP。如果开发时间很重要,那么您已经得到了答案。

如果您想构建具有最小复杂性的HA基础架构,我想AMQP协议是您想要的。

我有RESTful服务和AMQP的经验,RESTful服务的优点是:

  • 它们在Web界面上有很好的映射
  • 人们熟悉它们
  • 易于调试(由于HTTP的通用性)
  • 易于向第三方服务提供API。

基于AMQP的解决方案的优点:

  • 非常快速
  • 灵活
  • 成本效益高(资源使用意义上)

请注意,您可以在基于AMQP的API之上为第三方服务提供RESTful API,而REST不是一种协议,而是一种范例,但在构建AQMP RPC api时应考虑到它。我以这种方式完成了此操作,以向外部第三方服务提供API,并在运行旧代码库或无法添加AMQP支持的基础设施部分中提供对API的访问。

如果我没错的话,您的问题是关于如何更好地组织软件不同部分之间的通信,而不是如何向最终用户提供API。

如果你有一个高负载的项目,RabbitMQ是非常好的软件,你可以轻松地添加任意数量的工作者,并在不同的机器上运行。此外,它还具有镜像和集群功能。还有一件事,RabbitMQ是建立在Erlang OTP之上的,这是一个高可靠性、稳定的平台...(咕噜咕噜)...这不仅对市场营销人员有好处,对工程师也有好处。我只有一次使用RabbitMQ时遇到了问题,当nginx日志占用了与RabbitMQ相同分区的所有磁盘空间时。

更新(2018年5月):Saurabh Bhoomkar在2012年6月7日发布了Arnold Shoon撰写的MQ vs. HTTP文章的链接,以下是其中的一份副本:

我正在查看我的旧文件,并找到了关于MQ的笔记,想和大家分享一些使用MQ而不是HTTP的原因:
- 如果您的消费者以固定速率处理(即无法处理HTTP服务器的洪水[爆发]),那么使用MQ可以提供灵活性,使服务缓冲其他请求而不会拖慢它。 - 时间独立处理和消息交换模式 - 如果线程执行的是fire-and-forget,则MQ比HTTP更适合该模式。 - 长时间运行的进程更适合MQ,因为您可以发送请求并有一个单独的线程监听响应(注意,WS-Addressing允许HTTP以这种方式处理,但需要两个端点支持该功能)。 - 松耦合,其中一个进程可以继续工作,即使另一个进程不可用,而HTTP必须重试。 - 请求优先级,其中更重要的消息可以跳到队列的前面。 - XA事务-MQ完全符合XA标准-HTTP不符合。 - 容错-MQ消息在服务器或网络故障时仍然存在-HTTP不会。 - MQ提供了“确保”消息只发送一次的功能,而http没有。 - MQ提供了消息分段和消息分组的能力,用于大型消息-HTTP没有这种能力,因为它将每个事务视为单独的。 - MQ提供pub/sub接口,而HTTP是点对点的。

更新(2018年12月): 正如下面@Kevin在评论中提到的那样,RabbitMQ是否比RESTful服务更好扩展是有问题的。我的原始答案是基于简单地添加更多的工作人员,这只是扩展的一部分,只要单个AMQP代理容量没有超过,它是正确的,但之后需要更高级的技术,例如 高可用(镜像)队列,这使得基于HTTP和AMQP的服务在基础设施层面上具有一些非平凡的复杂性。

经过仔细思考,我还删除了维护AMQP代理(RabbitMQ)比任何HTTP服务器更简单的说法:原始答案是在2013年6月编写的,自那时以来发生了很多变化,但主要的变化是我对两种方法有了更多了解,所以现在最好的说法是“你的情况可能会有所不同”。

另外请注意,将HTTP和AMQP进行比较在某种程度上是不恰当的,因此,请不要将本答案解释为基于其做出决策的终极指南,而是将其视为一种来源或参考,以便进一步研究找出哪种确切的解决方案适合您的特定情况。


4
我们最终选择了使用HTTP/REST。我非常想采用AMQP路线,因为它与我们的架构非常契合,但我的团队不想尝试新事物,所以这有点遗憾。相对于使用AMQP和RPC,采用HTTP开发一个冗余且高可用的面向服务的体系结构需要更多工作。 - jreid42
1
@pinepain 我认为需要提到一件事(如果我错了,请纠正我),即使用AMQP,您实际上可以将消息推送到目的地,而使用HTTP则不行(只适用于请求-响应方法)。 - rayman
1
@rayman HTTP和AMQP是不同的概念,因此我更倾向于不使用这样的标准来进行比较。 - pinepain
1
@rayman 没错,AMQP和HTTP在许多方面都非常不同,比如已经提到的高级路由、连接复用(在http2中添加)等等。同样适用于HTTP,缓存、代理、方法等等。我的原始观点是HTTP和AMQP处于不同的层次,将它们进行比较可能就像比较汽车和火车一样:虽然两者都是交通工具,但在许多方面都有所不同。 - pinepain
1
@pinepain 我知道这是一个老问题,但是作为澄清,为什么AMQP比HTTP更具可扩展性?直觉上,AMQP强制所有流量通过代理,并且我会假设代理然后成为瓶颈,特别是如果架构中的所有消息传递都基于通过代理进行流量漏斗?在这种意义上,即使在其他方面不如HTTP,HTTP似乎也更具可扩展性? - Kevin
显示剩余7条评论

22

这个解决方案的讽刺之处在于,AMQP或其他MQ解决方案通常用来隔离调用者与仅使用HTTP协议服务的内在不可靠性,提供一定程度的超时和重试逻辑以及消息持久化,这样调用者就不必自己实现其自身的HTTP隔离代码。一个非常轻量级的HTTP网关或适配器层覆盖在可靠的AMQP核心上,具有使用更可靠的客户端协议如JSONRPC直接转到AMQP的选项,通常是这种情况下最好的解决方案。


1

你关于AMQP的想法很正确!

此外,由于你正在从单块架构转换为更分布式的架构,所以采用AMQP在服务之间进行通信更适合你的用例。原因如下...

通过REST接口和扩展HTTP进行通信是同步的——这种HTTP的同步性质使其在像你谈论的分布式架构中作为通信模式不是一个很好的选择。为什么?

想象一下你有两个服务,在你的Django应用程序中通过REST API调用进行通信: 服务A服务B。这些API调用通常是这样的: 服务A向服务B发出http请求,等待响应,只有在收到来自服务B的响应后才继续下一个任务。实际上,服务A被阻塞,直到它收到来自服务B的响应。

这是有问题的,因为微服务的目标之一是构建小型自治服务,即使一个或多个服务停机也将始终可用-没有单点故障。事实上,服务A直接连接到服务B,并且事实上等待某些响应,引入了一定程度的耦合,从而减弱了每个服务的预期自治性。

另一方面,AMQP是异步的——AMQP的这种异步性使其非常适合您的情况和其他类似情况。

如果您选择采用AMQP路线,而不是服务A直接向服务B发出请求,可以在这两个服务之间引入基于AMQP的MQ。服务A将请求添加到消息队列中。然后,服务B以自己的节奏拾取请求并处理它们。

这种方法解耦了两个服务,并使它们自治。这是真实的,因为:

  • 如果服务B意外失败,服务A将继续接受请求并将它们添加到队列中,就像什么也没有发生一样。请求始终在队列中等待服务B在重新上线时处理它们。
  • 如果服务A经历流量激增,服务B甚至不会注意到,因为它只以自己的节奏从消息队列中拾取请求
  • 这种方法还具有易于扩展的附加好处——您可以添加更多队列或创建服务B的副本以处理更多请求。
  • 最后,服务A不必等待来自服务B的响应,最终用户也不必等待太长时间——这导致性能得到改善,从而提供更好的用户体验。

如果您正在考虑从HTTP转向AMQP以在分布式架构中使用,但不确定如何进行,请查看这个7部分初学者指南,介绍消息队列和微服务。它向您展示了如何通过演示项目,在分布式架构中使用消息队列。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接