Spring boot 针对不同消费者的每条消息的Spring云流主题(在一个消费者应用程序中)

Spring boot 针对不同消费者的每条消息的Spring云流主题(在一个消费者应用程序中),spring-boot,spring-cloud-stream,spring-rabbit,Spring Boot,Spring Cloud Stream,Spring Rabbit,这个问题类似于,但不同的是,我希望在一个消费者springboot应用程序中有多个接收器,我希望通过rabbitmq主题(在SpringCloudStream中是默认的)来实现这一点。我无法找出正确的配置或代码中的某些错误。我有3个水槽/消耗品。consumer1是默认值,每条消息都会发送到那里 **根据Garry的建议进行更新** 注释:我的Producer应用程序具有路由密钥='*.events' application.yml spring: cloud: stream:

这个问题类似于,但不同的是,我希望在一个消费者springboot应用程序中有多个接收器,我希望通过rabbitmq主题(在SpringCloudStream中是默认的)来实现这一点。我无法找出正确的配置或代码中的某些错误。我有3个水槽/消耗品。consumer1是默认值,每条消息都会发送到那里

**根据Garry的建议进行更新**

注释:我的Producer应用程序具有路由密钥='*.events' application.yml

spring:
  cloud:
    stream:
      bindings:
        output:
          destination: my-exchange
      rabbit:
        bindings:
          output:
            producer:
              routing-key-expression: headers['*.events']
  application:
    name: publisher-service
server:
  port: 15010
spring:
  cloud:
      stream:
        bindings:
          defaultconsumer:
            destination: my-exchange
            group: queue1
          billingconsumer:
            destination: my-exchange
            group: queue2
          messageconsumer:
            destination: my-exchange
            group: queue3

        rabbit:
          bindings:
            defaultconsumer:
              consumer:
                bindingRoutingKey: '*.events.#'
            billingconsumer:
              consumer:
                bindingRoutingKey: test1.events.billing
            messageconsumer:
              consumer:
                bindingRoutingKey: test2.events.messages

  application:
    name: subscriber-service
server:
  port: 15020

生产者代码片段 注释:消息通过路由键=“test.events”发送。我不确定第二个参数,但我假设它是bindingrouting key=test1.events.billing,这意味着我希望将它交付给计费消费者,而不是默认消费者

 source.output().send(MessageBuilder.withPayload(eventRequest.getEventMessage())
                    .setHeader("*.events", "test1.events.billing")
                    .build());

消费者配置 注释:我希望为exchange=“myexchange”分配3个队列。我不确定配置是否正确。 application.yml

spring:
  cloud:
    stream:
      bindings:
        output:
          destination: my-exchange
      rabbit:
        bindings:
          output:
            producer:
              routing-key-expression: headers['*.events']
  application:
    name: publisher-service
server:
  port: 15010
spring:
  cloud:
      stream:
        bindings:
          defaultconsumer:
            destination: my-exchange
            group: queue1
          billingconsumer:
            destination: my-exchange
            group: queue2
          messageconsumer:
            destination: my-exchange
            group: queue3

        rabbit:
          bindings:
            defaultconsumer:
              consumer:
                bindingRoutingKey: '*.events.#'
            billingconsumer:
              consumer:
                bindingRoutingKey: test1.events.billing
            messageconsumer:
              consumer:
                bindingRoutingKey: test2.events.messages

  application:
    name: subscriber-service
server:
  port: 15020

消费者代码: IEventConsumer.java 注释:我不确定下面的代码是否正确

public interface IEventConsumer {
     String INPUT = "my-exchange";

    @Input
    SubscribableChannel defaultconsumer();

    @Input
    SubscribableChannel billingconsumer();

    @Input
    SubscribableChannel messageconsumer();
}
EventConsumer.java 评论:我所希望的是,下面的信息不应该被我的消费者收到! 但在现实中,它通过所有这些方法



    @StreamListener("defaultconsumer")
    public void subscribe1(EventMessage eventMessage) {
        logger.info(" DefaultEventConsumer received new event [" + eventMessage.toString() + "] ");
    }


   @StreamListener("billingconsumer")
    public void subscribe2(EventMessage eventMessage) {
        logger.info(" billingEventConsumer received new event [" + eventMessage.toString() + "] ");
    }

    @StreamListener("messageconsumer")
    public void subscribe3(EventMessage eventMessage) {
        logger.info(" messageEventConsumer received new event [" + eventMessage.toString() + "] ");
    }

显然上面有点不对劲,我看不出有什么效果。有什么想法吗

    @Input(INPUT)
    SubscribableChannel defaultconsumer();

    @Input(INPUT)
    SubscribableChannel billingconsumer();

    @Input(INPUT)
    SubscribableChannel messageconsumer();
您为所有三个绑定指定了相同的名称;只需使用
@INPUT
,方法名称将用作绑定名称

等等

编辑

我只是复制了你的代码,它工作得很好

@springboot应用程序
@EnableBinding({IEventConsumer.class,Source.class})
公共类SO60879187应用程序{
私有静态最终记录器Logger=LoggerFactory.getLogger(So60879187Application.class);
公共静态void main(字符串[]args){
SpringApplication.run(So60879187Application.class,args);
}
@StreamListener(“defaultconsumer”)
public void subscribe1(字符串eventMessage){
info(“DefaultEventConsumer收到新事件[“+eventMessage.toString()+”]);
}
@StreamListener(“billingconsumer”)
public void subscribe2(字符串eventMessage){
logger.info(“billingEventConsumer收到新事件[“+eventMessage.toString()+”]);
}
@StreamListener(“messageconsumer”)
public void subscribe3(字符串eventMessage){
info(“messageEventConsumer收到新事件[“+eventMessage.toString()+”]);
}
@豆子
公共应用程序运行程序(MessageChannel输出){
return args->output.send(MessageBuilder.withPayload(“foo”)
.setHeader(“*.events”、“test1.events.billing”)
.build());
}
}
接口IEventConsumer{
字符串输入=“我的交换”;
@输入
SubscribableChannel defaultconsumer();
@输入
SubscribableChannel billingconsumer();
@输入
SubscribableChannel messageconsumer();
}
spring:
云:
流:
绑定:
默认消费者:
目的地:我的交易所
组:队列1
计费用户:
目的地:我的交易所
组:队列2
messageconsumer:
目的地:我的交易所
组:队列3
输出:
目的地:我的交易所
兔子:
绑定:
默认消费者:
消费者:
bindingRoutingKey:“*.events.#”
计费用户:
消费者:
bindingRoutingKey:test1.events.billing
messageconsumer:
消费者:
bindingRoutingKey:test2.events.messages
输出:
制作人:
路由键表达式:标头['*.events']
应用程序:
名称:订户服务
服务器:
港口:15020

EDIT2

更新的函数式编程模型等效

@springboot应用程序
公共类SO608791871应用程序{
专用静态最终记录器Logger=LoggerFactory.getLogger(SO608791application.class);
公共静态void main(字符串[]args){
SpringApplication.run(SO608791application.class,args);
}
@豆子
公共消费者违约消费者(){
返回事件消息->
info(“DefaultEventConsumer收到新事件[“+eventMessage.toString()+”]);
}
@豆子
公共消费者账单消费者(){
返回事件消息->
logger.info(“billingEventConsumer收到新事件[“+eventMessage.toString()+”]);
}
@豆子
公共消费者信息消费者(){
返回事件消息->
info(“messageEventConsumer收到新事件[“+eventMessage.toString()+”]);
}
专用最终DirectProcessor>>输出(){
return()->this.output;
}
@豆子
公共应用程序运行程序(){
Message msg1=MessageBuilder.withPayload(“foo”)
.setHeader(“*.events”、“test1.events.billing”)
.build();
Message msg2=MessageBuilder.withPayload(“bar”)
.setHeader(“*.events”、“test2.events.messages”)
.build();
返回参数->{
this.output.onNext(msg1);
this.output.onNext(msg2);
};
}
}

您为所有三个绑定指定了相同的名称;只需使用
@INPUT
,方法名称将用作绑定名称

等等

编辑

我只是复制了你的代码,它工作得很好

@springboot应用程序
@EnableBinding({IEventConsumer.class,Source.class})
公共类SO60879187应用程序{
私有静态最终记录器Logger=LoggerFactory.getLogger(So60879187Application.class);
公共静态void main(字符串[]args){
SpringApplication.run(So60879187Application.class,args);
}
@Str
spring:
  cloud:
    function:
      definition: defaultconsumer;billingconsumer;messageconsumer;output
    stream:
      bindings:
        defaultconsumer-in-0:
          destination: my-exchange
          group: queue1
        billingconsumer-in-0:
          destination: my-exchange
          group: queue2
        messageconsumer-in-0:
          destination: my-exchange
          group: queue3
        output-out-0:
          destination: my-exchange

      rabbit:
        bindings:
          defaultconsumer-in-0:
            consumer:
              bindingRoutingKey: '*.events.#'
          billingconsumer-in-0:
            consumer:
              bindingRoutingKey: test1.events.billing
          messageconsumer-in-0:
            consumer:
              bindingRoutingKey: test2.events.messages
          output-out-0:
            producer:
              routing-key-expression: headers['*.events']

  application:
    name: subscriber-service
server:
  port: 15020
2020-03-27 14:28:37.426  INFO 3646 --- [change.queue3-1] com.example.demo.So608791871Application
  :  messageEventConsumer received new event [bar] 
2020-03-27 14:28:37.426  INFO 3646 --- [change.queue1-1] com.example.demo.So608791871Application
  :  DefaultEventConsumer received new event [foo] 
2020-03-27 14:28:37.426  INFO 3646 --- [change.queue2-1] com.example.demo.So608791871Application
  :  billingEventConsumer received new event [foo] 
2020-03-27 14:28:37.429  INFO 3646 --- [change.queue1-1] com.example.demo.So608791871Application
  :  DefaultEventConsumer received new event [bar]