springcloud消息中间件 ----- springcloud stream

介绍

在实际的企业开发中,消息中间件是至关重要的组件之一。消息中间件主要解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性架构。不同的中间件其实现方式,内部构造不一样。如常见的RabbitMQ和Kafka,由于这两个消息中间件的架构上的不同,像RabbitMQ有exchange,kafka有Topic,partitions分区,这些中间件的差异性导致我们实际项目开发给我们造成了一定的困扰,我们如果用了两个消息队列的其中一种,后面的业务需求,我想往另外一种消息队列迁移,这时候无疑就是灾难性的,一大堆东西都要重新推到重新做,因为它跟我们的系统耦合了,这时候springcloud stream给我们提供了一种解耦合的方式。
在这里插入图片描述

应用

消息生产者

  • 依赖
<dependency>
   <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
  • 配置文件
server:
  port: 7001
spring:
  application:
    name: stream-producer #指定服务名
  rabbitmq:
    addresses: 127.0.0.1
    username: guest
    password: guest
    port: 5672
  cloud:
    stream:
      bindings:
        output:
          destination: stream-default #指定消息发送的目的地,在rabbitmq中,发送到一个stream-default的exchange
      binders: #配置绑定器
        defaultRabbit:
          type: rabbit
  • 发送消息
/***
 *  1.引入依赖
 *  2.配置application.yml
 *  3.发送消息的话,定义一个通道接口,通过接口中内置的messagechannel
 *          springcloudstream中内置接口, Source
 *  4.@EnableBinding:绑定对应的通道
 *  5.发送消息的话,通过MessageChannel发送消息
 *          如果需要MessageChannel ---> 通过绑定的内置接口获取
 * */
@EnableBinding(Source.class)
@SpringBootApplication
public class StreamProducerApplication implements CommandLineRunner {

    @Autowired
    private MessageChannel output;

    @Override
    public void run(String...args) throws Exception{
        //发送消息
        //messageBuilder: 工具类:创建消息
        output.send(MessageBuilder.withPayload("测试案例").build());
    }

    public static void main(String[] args){
        SpringApplication.run(StreamProducerApplication.class,args);
    }

}
  • 结果
    我们可以在rabbitmq的后台管理的Exchanges看到我们定义的 stream-default
  • 流程
    在这里插入图片描述

消息消费者

  • 依赖
<dependency>
   <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
  • 配置文件
server:
  port: 7002
spring:
  application:
    name: stream-consumer #指定服务名
  rabbitmq:
    addresses: 127.0.0.1
    username: guest
    password: guest
    port: 5672
  cloud:
    stream:
      bindings:
        input:
          destination: stream-default #指定消息接收地,在rabbitmq中,从一个stream-default的exchange中获取消息
      binders: #配置绑定器
        defaultRabbit:
          type: rabbit
  • 接收消息
/**
 * 1.引入依赖
 * 2.配置application.yml
 * 3.需要配置一个通道的接口
 *      内置获取消息的通道接口 sink
 *  4.绑定通道
 *  5.配置一个监听方法:当程序从消息件获取数据后,执行的业务逻辑方法
 *      需要在监听方法上配置一个@StreamListener
 * */
@SpringBootApplication
@EnableBinding(Sink.class)
public class StreamConsumerApplication {

    //监听binding中的消息
    @StreamListener(Sink.INPUT)
    public void input(String message){
        System.out.println("获取到新消息:"+message);
    }

    public static void main(String[] args) {
        SpringApplication.run(StreamConsumerApplication.class,args);
    }

}
  • 流程
    和消息生产者类似

自定义消息通道

  • 定义接口
public interface MyProcedure {

    /***
     * 消息生产者配置
     * */
    String MYOUTPUT = "myOutput";

    @Output("myOutput")
    MessageChannel myOutput();

    /***
     * 消息消费者配置
     * */
    String MYINPUT = "myInput";

    @Input("myInput")
    MessageChannel myInput();
}
  • 修改发送消息工具类
@EnableBinding(MyProcedure.class)

//引入output的时候
@Autowired
private MessageChannel myOutput;

  • 配置文件
server:
  port: 7001
spring:
  application:
    name: stream-producer #指定服务名
  rabbitmq:
    addresses: 127.0.0.1
    username: guest
    password: guest
    port: 5672
  cloud:
    stream:
      bindings:
        output:
          destination: stream-default #指定消息发送的目的地,在rabbitmq中,发送到一个stream-default的exchange
        myOutput: #自定义的消息通道
         destination: my-stream-default
      binders: #配置绑定器
        defaultRabbit:
          type: rabbit

完成,这样就可以使用自定义的通道了。

消息分组

通常在生产环境,我们的每个服务都不会以单节点的方式运行在生产环境,当同一个服务启动多个实例的时候,这些实例都会绑定到同一个消息通道的目标主题(Topic)上。默认情况下,当生产者发出一条消息绑定通道上,这条消息会产生多个副本被每个消费者实例接收和处理,但是有些业务场景之下,我们希望生产者的消息只被其中一个实例消费者,这个时候我们需要为这些消费者设置消费组来实现这样的功能。

  • 配置
spring:
 cloud:
    stream:
      bindings:
        input:
          destination: stream-default #指定消息接收地,在rabbitmq中,从一个stream-default的exchange中获取消息
          group: group1

其他的消费者也叫group1就可以了,整个group1分组,只会有一个消费者消费

消息分区

有一些场景需要满足,同一个特征的数据被同一个实例消费,比如同一个id的传感器监测数据必须被同一个实例统计计算分析,否则可能无法获取全部的数据。又比如部分异步任务,首次请求启动task,二次请求取消task,此场景就必须保证两次请求至同一实例。

  • 生产者配置
spring:
  cloud:
    stream:
      bindings:
        myoutput: #自定义的消息通道
          destination: my-stream-default
          producer:
            partition-key-expression: payload #分区关键字 对象中的id
            partition-count: 2 #分区大小
  • 消费者配置
spring:
  cloud:
    stream:
      bindings:
        myinput: #自定义的消息通道
          destination: my-stream-default
          consumer:
            partitioned: true #开启分区支持
      binders: #配置绑定器
        defaultRabbit:
          type: rabbit
      instance-count: 2 #消费者总数
      instance-index-list: 0 #当前消费者索引

如果数据是一样的,那相同的数据就到达相同的消费者

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值