中间件上基于HTTP / JMS的混合SOAP的请求 - 回复模型

时间:2009-10-25 17:47:09

标签: java web-services soap jms soa

我们的一个产品实现了以下单向Web服务结构:

Server <--------------------- Middleware <---------------- Client
        SOAP over JMS (queue)              SOAP over HTTP

在此模型中,客户端通过HTTP将SOAP消息发送到我们的中间件(Progress SonicMQ)。消息被SonicMQ推送到JMS队列,我们​​的服务器从那里获取它们。但是,正如您所看到的,服务器不会向客户端发送响应(异步JMS)。

我们希望为此模型实施响应通道。通常建议的解决方案是在中间件中创建临时replyTo队列(动态),允许服务器向该队列发送响应。然后,客户端可以获取响应并关闭replyTo队列。这听起来很方便,但不幸的是我们的客户端通过纯HTTP而不是JMS运行,因此他们的客户端无法轻松设置replyTo队列。

在这种混合HTTP / JMS SOAP模型中实现响应通道的一种方法是配置中间件以在每个成功的SOAP接收上打开replyTo队列,将replyTo-queue和sender信息附加到SOAP消息并推送消息到队列,服务器将获取它。在接收并处理消息之后,服务器可以向中间件中的指示的replyTo队列发送响应。最后,中间件将通过使用SOAP消息中的数据(在首次接收请求时在中间件过程中插入的数据)通过HTTP将响应(SOAP)发送回原始客户端。

虽然有可能,但听起来有点像hacky。所以问题是:在我们的案例中实现这种请求/响应模型的任何更清晰的方法?服务器端已用Java实现。

解决方案:

Progress SonicMQ支持“内容回复发送”HTTP Acceptor,它允许轻松发送JMS回复。内容回复发送接受器以下列方式工作:

  • Acceptor接收客户端发送的HTTP消息
  • Acceptor创建一个临时JMS队列
  • Acceptor构建包含HTTP正文的JMS消息,并将临时队列的标识添加到新创建的JMS消息中
  • Acceptor将JMS消息推送到其目标队列(而不是临时队列)
  • Acceptor开始使用临时回复队列
  • 当客户端从原始目标队列中提取消息时,它包含set reply-To queue identification
  • 客户消费消息
  • 客户端向回复队列发送回复
  • Acceptor从队列接收消息
  • Acceptor将消息作为HTTP发送给最初发送HTTP消息的客户端

如果消费者(在我们的情况下是“服务器”)失败并且没有发送回复导致超时,Sonic的HTTP Acceptor会向客户端发送HTTP消息,指示超时。这是SonicMQ中非常标准的功能。我想它也存在于其他产品中。

这允许在“服务器”端使用标准SOAP over JMS(参见skaffman的答案),避免在中间件中进行任何自定义编程。

我仍然在JMS模型中看到一些问题,但这肯定是一种改进。

更新2009-11-05:

在研究了这个问题之后,我发现我对HTTP&lt; - &gt;中间件&lt; - &gt; JMS的怀疑是相关的。

此模型中存在一些关键问题。具有中间件的同步异步模型简单不方便。要么两端都实现JMS连接(应该摇摆),要么两端都使用HTTP。混合它们只会导致头痛。在这两者中,SOAP-over-HTTP比SOAP-over-JMS更简单,更受支持。

再一次:如果你正在设计这种系统......请不要。

2 个答案:

答案 0 :(得分:5)

我认为您建议的解决方案根本不是黑客,我认为这是正确的解决方案。您有一个带有同步协议的客户端 - 中间层,然后是使用异步层的中间服务器层,您必须向其添加一个回复路径以满足同步语义。这就是中间件的用途。请记住,JMS为临时回复队列提供了明确的支持,您根本不需要乱用有效负载。

更左侧的可能性是利用SOAP 1.2在设计时考虑到JMS这一事实,因此您可以在中间件和服务器层之间使用Web服务层来实现SOAP-over-JMS。这意味着您可以将SOAP从端到端保留,中间件只会更改传输。

我所知道的唯一支持JMS传输的Web服务堆栈是Spring Web Services,其中进程和开发是documented here。这也可以让你有机会将你的SOAP层移植到Spring-WS,这会踢屁股:)

答案 1 :(得分:4)

为什么不添加一个链接到一个页面,让用户检查一下响应何时就绪,一个联邦快递的跟踪器ID?在发送请求时为您的用户提供跟踪器ID。

这适用于HTTP请求/响应习惯用法,您的用户仍然会知道该请求“一发不可”。