消息队列和Web服务有什么区别?

288
在什么情况下,人们会更倾向于通过消息队列而不是Web服务进行应用程序之间的通信(我指的只是使用HTTP传输XML、JSON、YAML或其他任何格式,而不是特定类型)?
我需要在本地网络上的两个应用程序之间进行通信。其中一个是Web应用程序,必须在另一个应用程序上(运行在不同硬件上)请求命令。这些请求是一些诸如创建用户、移动文件以及创建目录之类的操作。在什么情况下,我会更喜欢使用XML Web服务(或直接TCP或其他协议),而不是使用消息队列呢?
这个Web应用程序是用Ruby on Rails编写的,但我认为这个问题比这个框架更广泛。
5个回答

348
当你使用Web服务时,你有一个客户端和一个服务器:
  1. 如果服务器失败了,客户端必须负责处理错误。
  2. 当服务器再次工作时,客户端负责重新发送请求。
  3. 如果服务器已经对调用做出响应,但客户端发生故障,操作将会丢失。
  4. 你没有争用(contention)问题,也就是说,如果数百万个客户端在一秒钟内调用一个服务器上的Web服务,你的服务器很可能会崩溃。
  5. 你可以期望从服务器得到立即响应,但你也可以处理异步调用。
当你使用像RabbitMQ、Beanstalkd、ActiveMQ、IBM MQ Series和Tuxedo这样的消息队列时,你会期望不同且更具容错性的结果:
  1. 如果服务器失败,队列会保存消息(甚至在机器关闭的情况下也可以选择保存)。
  2. 当服务器重新工作时,它会接收未处理的消息。
  3. 如果服务器已经对调用做出响应,但客户端发生故障,如果客户端没有确认该响应,那么消息将被保存。
  4. 你有争用问题,你可以决定服务器处理多少请求(称之为worker而不是请求)。
  5. 你不期望立即同步响应,但你可以实现/模拟同步调用。
消息队列有更多功能,但这是一些经验法则,可以决定是否要自己处理错误条件,还是交给消息队列。

2
如果使用SOAP/JMS绑定,则还可以在Web服务中获得松耦合。 - koppor
在服务器端的多个微服务中,应该优先选择Web服务还是队列? - shivendra pratap singh
亲爱的@sw.,请问这是否意味着我们可以在普通网站前面放置MQ?举个例子,我有一个WordPress网站(LAMP堆栈)。 我可以在Apache前面使用MQ,以便请求按顺序而来,而不是同时到达。 在这种情况下,客户端(浏览器)连接到MQ而不是Apache,对吗?但是,浏览器是否保持HTTP连接开启并等待Apache响应呢? 请帮我理解一下。感谢您的好意。 - 夏期劇場
1
这些与客户端/服务器设置相关的问题不是仍然存在于队列和服务器之间以及客户端和队列之间吗?看起来客户端/服务器范例仍然存在,并且现在存在于两个位置。 - imagineerThat
如果底层系统是异步的,我该如何可靠地实现/模拟同步调用? - Minh Nghĩa
显示剩余2条评论

79

最近有相当多的研究考虑如何使用REST HTTP调用来替代消息队列的概念。

如果你将进程和任务作为资源引入,那么中间消息传递层的需求就开始消失了。

例如:

POST /task/name
    - Returns a 202 accepted status immediately
    - Returns a resource url for the created task: /task/name/X
    - Returns a resource url for the started process: /process/Y

GET /process/Y
    - Returns status of ongoing process

一个任务可以有多个初始化步骤,进程可以在轮询时返回状态或者在完成时POST到回调URL。

这很简单,当你意识到你现在可以订阅所有运行的进程和任务的rss/atom feed而不需要中间层时,它变得非常强大。任何队列系统都需要一些类型的Web前端,而这个概念已经内置了,不需要另一层自定义代码。

你的资源会一直存在,直到你将它们删除,这意味着你可以在进程和任务完成后长时间查看历史信息。

你内置了服务发现功能,即使是有多个步骤的任务,也不需要任何额外复杂的协议。

GET /task/name
    - returns form with required fields

POST (URL provided form's "action" attribute)

您的服务发现是一个HTML表单——一种通用且易于阅读的格式。

整个流程可以通过程序或人工使用普遍接受的工具来完成。它是客户端驱动的,因此符合RESTful原则。为Web创建的每个工具都可以驱动您的业务流程。您仍然可以通过将消息异步地POST到一个单独的日志服务器数组来使用备用消息通道。

在考虑一段时间后,您可以坐下来开始意识到REST可能只需消除消息队列和ESB的需要。

http://www.infoq.com/presentations/BPM-with-REST


14
@tempire,容错性等方面怎么办?REST很好,但开发人员最终需要自己构建中间件。 - Dan Rosenstark
10
大多数关于“这个怎么样”的问题都可以改为“在网页上如何处理?”。容错可以通过负载平衡器或甚至对 DNS 记录进行操纵来处理。还有一些需要解决的问题,比如水平扩展——网页本质上并不擅长处理这方面的问题(例如 DDoS 攻击)。 - tempire
8
@tempire,网络上没有保证投递的功能,对吗?我只能提交信息并祈祷它能到达目的地。但是使用 MQ,我知道一旦信息到达了 MQ,我的任务就完成了。MQ 会负责将信息发送到目的地。 - Dan Rosenstark
10
考虑一下“保证交付”意味着什么。它只有在消息队列的正常运行时间内才能被“保证”。如果用将任务和进程视为资源的REST服务器替换消息队列,那么你就拥有了与其他任何东西一样的“保证”。实质上,你仍然有一个消息队列,但它以 Web 标准可访问的格式存在,可以使用任何 Web 工具进行监控。 - tempire
18
@Yar - 我不认为许多人理解MQ试图解决的问题定义,甚至考虑这样的事情。他们理解MQ,但这与理解问题空间不同。这是一个普遍存在的问题,因为我认为世界上大多数程序员和管理者都接受了连接零件而不是设计解决方案的培训。 - tempire
显示剩余4条评论

44

消息队列适用于可能需要很长时间处理的请求。请求被排队并可以在不阻塞客户端的情况下离线处理。如果客户端需要接收完成通知,可以提供一种方式让客户端周期性地检查请求的状态。

消息队列还允许您更好地跨时间进行扩展。它提高了您处理突发大量活动的能力,因为实际处理可以分布在时间上。

请注意,消息队列和Web服务是正交概念,即它们并不互斥。例如,您可以拥有一个基于XML的Web服务,作为消息队列的接口。我认为您要区分的是消息队列与请求/响应,后者是同步处理请求的情况。


3
是的,我刚刚也在思考这个问题:重点不是它们是阻塞还是非阻塞,而是它们是否需要更长时间和/或无法预测的时间来处理。关于它们是否正交,同样适用于Web服务可以被用于长时间请求(当然要分开下车和接送)。但如果你有消息队列的条件,那会是一个不错的选择。 - Dan Rosenstark
我的新问题是,如果我想让进程同步进行,但在超时时异步进行呢?那么也许Web服务会更合适。 - Dan Rosenstark

31

消息队列是异步的,如果传递失败会进行多次重试。如果请求者不需要等待响应,请使用消息队列。

"Web服务"这个词让我想到通过HTTP对分布式组件进行同步调用。如果请求者需要收到响应,请使用Web服务。


1
谢谢,是的,“保证交付”我得考虑一下是否重要。我的意思是,同步与异步在某种程度上是一种口味问题。虽然有明显的黑白之分,但也存在着巨大的灰色地带。 - Dan Rosenstark

22

一般来说,对于需要阻塞代码执行的任务,您会需要使用 Web 服务,而对于不需要等待的可能需要很长时间的任务,则需要使用消息队列。


Web服务还提供单向方法(@Oneway)。为了接收答案,客户端必须提供一个Web服务。 - koppor

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