【问题标题】:Spring integration - channel adapter vs. gateway (AMQP)Spring 集成 - 通道适配器与网关 (AMQP)
【发布时间】:2018-10-26 01:31:38
【问题描述】:
我对 Spring 集成中 Channel Adapters 和 Gateways 的区别感到困惑。正如@gary-russell 在https://stackoverflow.com/a/29992267/467944 中所述,通道适配器是非定向的,而网关是双向的。如果是这样,为什么有 amqp 入站网关和 amqp 出站网关?
我最终想要完成的是:
- 在控制器中收到 Http 请求
- 将消息放在 amqp 队列中
- 消费者消费消息并将结果放入结果队列
- 结果到达控制器
所以我想我需要一个带有接口的网关,该接口从控制器调用并将有效负载放入 amqp 队列(配置为其请求通道),同时它在其回复通道上侦听其答案。
但是,使用这种配置,我总是以
MessageDeliveryException: Dispatcher has no subscribers for channel 'application.fromRabbit'
fromRabibbit 是我的回复队列。
【问题讨论】:
标签:
spring
rabbitmq
spring-integration
amqp
spring-amqp
【解决方案1】:
在提出此类问题时,您应该始终显示配置。
Dispatcher 没有订阅者...
这是一个配置错误,您没有正确连接集成流程。
Spring Integration 中有两种类型的网关 -
与外部系统交互的网关
这些为外部系统提供请求/回复语义。
入站网关用于服务器端请求/回复,服务器接收请求,执行一些处理并返回回复。
出站网关是客户端发送请求并等待回复的等效网关。使用 AMQP,我们有一个异步版本,其中回复在不同的线程上返回。
消息传递网关
这些基于接口的网关从 Java 代码(而不是某些外部系统)提供网关(通常是请求/回复,但结果为 void 的方法是单向的)。
这使遗留 Java 代码能够使用基于集成的流程。
所以你可能...
controller -> gateway -> transformer(optional) -> amqp-outbound-gateway
...这是一种常见的模式,效果很好。
服务器端可能是
amqp-inbound-gateway -> service-activator
显示您的代码/配置,有人可以帮助调试您的配置问题。
【解决方案2】:
感谢@gary-russell 提供的见解。我想我现在有正确的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 'CLIENT' SIDE CONFIG -->
<int:channel id="clientToRabbit" />
<int:channel id="clientFromRabbit" />
<int:gateway id="uppercaseGateway" service-interface="com.example.queuing.UpperCaseService" default-request-channel="clientToRabbit" />
<int-amqp:outbound-gateway request-channel="clientToRabbit" amqp-template="amqpTemplate" exchange-name="si.test.exchange" routing-key="si.test.binding" />
<!-- 'SERVER' SIDE CONFIG -->
<int:channel id="serverFromRabbit" />
<int:channel id="serverToRabbit" />
<int-amqp:inbound-gateway request-channel="serverFromRabbit" reply-channel="serverToRabbit" queue-names="si.test.queue" amqp-template="amqpTemplate" connection-factory="connectionFactory" />
<int:service-activator input-channel="serverFromRabbit" output-channel="serverToRabbit" ref="upperCaseService" method="toUpperCase" />
<!-- Infrastructure -->
<rabbit:connection-factory id="connectionFactory" host="localhost" />
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" />
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:queue name="si.test.queue" />
<rabbit:direct-exchange name="si.test.exchange">
<rabbit:bindings>
<rabbit:binding queue="si.test.queue" key="si.test.binding" />
</rabbit:bindings>
</rabbit:direct-exchange>
</beans>