spring cloud stream

1、首先添加引用

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>

2、先写一个简单的消息接收的例子,定义消息的输入输出通道

public interface StreamClient {
    //定义输入和输出通道
    String INPUT = "myInput";
    String OUTPUT = "myOutput";

    //如果Input注解无参数,通道的名称就是注解的方法的名称
    @Input(StreamClient.INPUT)
    SubscribableChannel input();

    @Output(StreamClient.OUTPUT)
    MessageChannel output();
}

3、定义消息的侦听方法

//@EnableBinding 注解用来指定一个或多个定义了 @Input 或 @Output 注解的接口,以此实现对消息通道(Channel)的绑定
//@EnableBinding(value={Sink.class,Source.class})
@EnableBinding(StreamClient.class)
public class StreamReceiver {
    @StreamListener(StreamClient.INPUT)
    public void receive(String message) {
        System.out.println("接受到消息:" + message);
    }
}

4、配置文件配置信息

server:
  port: 8090
spring:
  application:
    name: spring-cloud-stream
  rabbitmq:
    host: 192.168.1.1
    port: 5672
    username: sa
    password: 123456
  cloud:
    stream:
      bindings:
        #指定输入输出通道对应的主题名
        myInput:
          destination: hello
        myOutput:
          destination: hello

5、向这个通道里面添加消息测试看看效果

@RestController
public class HomeController {
    @Autowired
    private StreamClient streamClient;

    @GetMapping("/index")
    public void index() {
        //向被监听的消息通道发送消息
        streamClient.output().send(MessageBuilder.withPayload("发送一条测试消息").build());
    }
}

运行起来就看以看到消息了。但是你运行两个程序实例的时候会发现,两个接收者都接受到这条消息了。

7ff11dcd4a3f7f2742420fe6bd11200c75e.jpg

我运行两个实例就启动两个队列,都属于交换机“hello”的。AD表示自动删除,Excl表示排他队列(排他队列,只有创建它的连接有权访问,连接断开后,排他队列将自动删除。这种队列适用于一个队列仅对应一个客户端收发消息的场景),ML好像是设置队列master的策略用的(https://blog.bossma.cn/rabbitmq/highly-available-mirrored-queues/),

92bee40160aaf883750e8d18c6e8d6b61fd.jpg

可以看到Routing key是“#”,表示任意位数符。

574e640283ecaa8946d9d923e9ba7594acb.jpg

 

为了不让消息重复消费就又一个“消费组”的概念,我们就来设置下消费组。配置文件添加group: world设置即可,运行两个实例,就会发现队列只有一个,两个程序监听这一个队列,发送消息,也确实是每次只有一个程序能输出信息。

6a01e6a2b50074cd36abeb738ea9cf7b4c2.jpg

server:
  port: 8091
spring:
  application:
    name: spring-cloud-stream
  rabbitmq:
    host: 192.168.1.1
    port: 5672
    username: sa
    password: 123456
  cloud:
    stream:
      bindings:
        #指定输入输出通道对应的主题名
        myInput:
          destination: hello
          #指定该应用实例属于world消费组
          group: world
        myOutput:
          destination: hello

 

还有一个“消息分区”的概念,重点是partitionKeyExpression配置信息,这个配置信息配置后,会进行计算,具体怎么计算我暂时也不知,如果是消息1就会路由到一个分区,如果是2路由到另一个分区。感觉像是取模的样子,发送消息a和消息b也不在一个分区,还没找到具体的计算方式。。。。找到再来补充。。。

注意,配置的缩进千万别搞错了。。。

server:
  port: 8090
spring:
  application:
    name: spring-cloud-stream
  rabbitmq:
    host: 192.168.1.1
    port: 5672
    username: sa
    password: 123456
  cloud:
    stream:
      bindings:
        myInput:
          #指定输入通道对应的主题名
          destination: hello
          #指定该应用实例属于world消费组
          group: world
          consumer:
            #通过该参数开启消费者分区功能
            partitioned: true
        myOutput:
          destination: hello
          producer:
            #通过该参数指定了分区键的表达式规则,可以根据实际的输出消息规则配置 SpEL 来生成合适的分区键
            partitionKeyExpression: payload
            partitionCount: 2
      #该参数指定了当前消费者的总实例数量
      instance-count: 2
      #该参数设置了当前实例的索引号,从 0 开始,最大值为 spring.cloud.stream.instance-count 参数 - 1
      instance-index: 1

 

异常重试,默认情况下,代码出现异常,消费者会进行3次重试,3次后依旧失败则抛出异常。可以设置重试次数max-attempts。

bindings:
  myInput:
    #指定输入通道对应的主题名
    destination: hello
    #指定该应用实例属于world消费组
    group: world
    consumer:
      #设置重试次数,默认3次,重试时间貌似指数增长
      max-attempts: 3
  myOutput:
    destination: hello

 

异常可以自定义一个异常方法来接收信息参考:http://blog.didispace.com/spring-cloud-starter-finchley-7-3/

推荐使用异常情况将队列数据传入死信队列中,注意每次实验前将之前队列以及交换机删除掉,否则会出现异常。配置信息如下

cloud:
  stream:
    bindings:
      myInput:
        #指定输入通道对应的主题名
        destination: hello
        #指定该应用实例属于world消费组
        group: world
        consumer:
          #设置重试次数,默认3次,重试时间貌似指数增长
          max-attempts: 3
      myOutput:
        destination: hello
    rabbit:
      bindings:
        myInput:
          consumer:
            #开启死信队列
            auto-bind-dlq: true
            #超过时间自动从DLQ中移除,单位毫秒
            dlq-ttl: 10000
            #会在headers中加入错误信息
            republish-to-dlq: true

提示:如果死信队列中设置headers加入错误信息,就可以获取headers获取指定错误做出指定数据的处理。

 

此外还有一种配置,指明出现异常,将队列数据重新入队列,而不是将数据丢弃。

consumer:
  requeue-rejected: true

 

死信队列:http://blog.didispace.com/spring-cloud-starter-finchley-7-4/

参考链接:https://blog.csdn.net/hubo_88/article/details/80904165

转载于:https://my.oschina.net/uwith/blog/3101864

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值