配置Spring Integration聚合器以组合RabbitMq扇出交换的响应

时间:2012-10-29 17:34:31

标签: java rabbitmq spring-integration spring-amqp

我正在尝试使用Spring Integration配置以下内容:

  1. 向频道发送消息。
  2. 将这条消息发布给与n个消费者的兔子粉丝(pub / sub)交换。
  3. 每位消费者都会提供回复信息。
  4. 让Spring Integration在将它们返回给原始客户端之前聚合这些响应。
  5. 到目前为止,我遇到了一些问题...

    1. 我正在使用发布 - 订阅频道来设置apply-sequence="true"属性,以便使用correlationId,sequenceSize& sequenceNumber属性已设置。 DefaultAmqpHeaderMapper抛弃了这些属性。 DEBUG headerName=[correlationId] WILL NOT be mapped

    2. 即使在扇出交换中注册了2个队列,sequenceSize属性也只能设置为1。据推测,这意味着消息将过早地从聚合器中释放。我希望这是因为我滥用发布 - 订阅频道才能使用apply-sequence="true"而且正确地说只有一个订阅者int-amqp:outbound-gateway

    3. 我的出站Spring配置如下:

      <int:publish-subscribe-channel id="output" apply-sequence="true"/>
      
      <int:channel id="reply">
          <int:interceptors>
              <int:wire-tap channel="logger"/>
          </int:interceptors>
      </int:channel>
      
      <int:aggregator input-channel="reply" method="combine">
          <bean class="example.SimpleAggregator"/>
      </int:aggregator>
      
      <int:logging-channel-adapter id="logger" level="INFO"/>
      
      <int:gateway id="senderGateway" service-interface="example.SenderGateway" default-request-channel="output" default-reply-channel="reply"/>
      
      <int-amqp:outbound-gateway request-channel="output"
                                         amqp-template="amqpTemplate" exchange-name="fanout-exchange"
                                         reply-channel="reply"/>
      

      我的rabbitMQ配置如下:

      <rabbit:connection-factory id="connectionFactory" />
      
      <rabbit:template id="amqpTemplate" connection-factory="connectionFactory" reply-timeout="-1" />
      
      <rabbit:admin connection-factory="connectionFactory" />
      
      <rabbit:queue name="a-queue"/>
      <rabbit:queue name="b-queue"/>
      
      <rabbit:fanout-exchange name="fanout-exchange">
          <rabbit:bindings>
              <rabbit:binding queue="a-queue" />
              <rabbit:binding queue="b-queue" />
          </rabbit:bindings>
      </rabbit:fanout-exchange>
      

      消费者看起来像这样:

      <int:channel id="input"/>
      
      <int-amqp:inbound-gateway request-channel="input" queue-names="a-queue" connection-factory="connectionFactory" concurrent-consumers="1"/>
      
      <bean id="listenerService" class="example.ListenerService"/>
      
      <int:service-activator input-channel="input" ref="listenerService" method="receiveMessage"/>
      

      任何建议都会很棒,我怀疑我的某个地方有错误的结尾......

      根据Gary的评论新的出站春季配置:

      <int:channel id="output"/>
      
      <int:header-enricher input-channel="output" output-channel="output">
          <int:correlation-id expression="headers['id']" />
      </int:header-enricher>
      
      <int:gateway id="senderGateway" service-interface="example.SenderGateway" default-request-channel="output" default-reply-timeout="5000" default-reply-channel="reply" />
      
      <int-amqp:outbound-gateway request-channel="output"
                                         amqp-template="amqpTemplate" exchange-name="fanout-exchange"
                                         reply-channel="reply"
                                         mapped-reply-headers="amqp*,correlationId" mapped-request-headers="amqp*,correlationId"/>
      
      <int:channel id="reply"/>
      
      <int:aggregator input-channel="reply" output-channel="reply" method="combine" release-strategy-expression="size() == 2">
          <bean class="example.SimpleAggregator"/>
      </int:aggregator>
      

2 个答案:

答案 0 :(得分:3)

问题是S.I.不知道扇出交换的拓扑结构。

最简单的方法是使用自定义发布策略

release-strategy-expression="size() == 2"
聚合器上的

(假设扇出为2)。所以,你不需要序列大小;你可以避免使用标题扩充器“滥用”发布/子频道......

    <int:header-enricher input-channel="foo" output-channel="bar">
        <int:correlation-id expression="T(java.util.UUID).randomUUID().toString()" />
    </int:header-enricher>

您可以使用消息ID避免创建新的UUID,消息ID已经是唯一的...

<int:correlation-id expression="headers['id']" />

最后,您可以通过添加

将correlationId标头传递给AMQP
mapped-request-headers="correlationId"

到您的amqp端点。

答案 1 :(得分:-1)

即使这个问题是3年之久,我也会回答这个问题,因为我有同样的问题。

Spring Integration有一个Scatter-Gather的实现,听起来非常像你原来的问题。

以下是Spring Documentation

的相关部分
  

它是一个复合端点,其目标是向该端点发送消息   收件人并汇总结果....

     

以前,可以使用分立组件配置模式,   这种增强功能带来了更方便的配置。

     

ScatterGatherHandler是一个结合了a的请求 - 回复端点   PublishSubscribeChannel(或RecipientListRouter)和一个   AggregatingMessageHandler。请求消息将发送到分散   channel和ScatterGatherHandler等待来自的回复   要发送到outputChannel的聚合器。