SpringCloud Stream基本使用

介绍

Spring Cloud Stream是一个用于构建与共享消息系统连接的高度可伸缩的事件驱动微服务框架。

该框架提供了一个基于已建立且熟悉的Spring习惯用法和最佳实践的灵活编程模型,包括对持久发布/订阅语义、消费者组和有状态分区的支持。

主要应用场景

可能我们会遇到不同的系统在用不同的消息队列,比如系统A用的Kafka、系统B用的RabbitMQ,但是我们现在又没有学习过Kafka,那么怎么办呢?有没有一种方式像JDBC一样,我们只需要关心SQL和业务本身,而不用关心数据库的具体实现呢?

SpringCloud Stream能够做到,它能够屏蔽底层实现,我们使用统一的消息队列操作方式就能操作多种不同类型的消息队列。

img

它屏蔽了不同消息队列底层操作,让我们使用统一的Input和Output形式,以Binder为中间件,这样就算我们切换了不同的消息队列,也无需修改代码,而具体某种消息队列的底层实现是交给Stream在做的。

Binder
Binder是SpringCloud Stream的一个抽象概念,是应用与消息中间件之间的粘合剂,目前SpringCloud Stream实现了Kafka、RabbitMQ和RocketMQ等的binder

通过binder,可以很方便的连接中间件,可以动态的改变消息的destinations(对应于 Kafka的topic,RabbitMQ的exchange),这些都可以通过外部配置项来做到,甚至可以任意的改变中间件的类型但是不需要修改一行业务代码

实践

Linux安装RabbitMQ

接下来创建一个springboot父子项目来演示一下其基本使用(以rabbitmq为例):

image-20220928141522794

父工程依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>2021.0.1</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

image-20220928142106277
对应关系见 官网LEARN -> Reference Doc. 点击对应cloud版本即可看到支持Boot版本
子模块依赖:

<dependencies>
    <!--  RabbitMQ的Stream实现  -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

image-20220928142150258

生产者

生产者配置文件:

server:
  port: 8801

spring:
  application:
    name: stream-publisher
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: # 表示定义的名称,用于binding整合(随意)
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关环境配置
            spring:
              rabbitmq:
                host: 47.96.156.51  # RabbitMQ在本机的用localhost,在服务器的用服务器的ip地址
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        output: # 这个名字是一个通道channel的名称
          destination: studyExchange # 表示要使用的Exchange名称
          content-type: text/plain  # 设置消息类型,application/json -> json格式,本文要设置为 text/plain -> 文本类型

定义发送消息接口:

public interface IMessagePublisher {
    void publish(String message);
}

接口实现类:

@EnableBinding(Source.class)    // 定义消息的推送管道(Source是spring的)
@Slf4j
public class MessagePublishImpl implements IMessagePublisher {

    @Resource
    private MessageChannel output;  // 消息发送管道

    @Override
    public void publish(String message) {

        log.info("发送消息:{}", message);
        // MessageBuilder是spring的integration.support.MessageBuilder
        output.send(MessageBuilder.withPayload(message).build());

    }

}

Source接口

image-20220930212128357

新建controller.PublishController

@RestController
public class PublishController {

    @Resource
    IMessagePublisher publisher;

    @RequestMapping("/publish")
    public String publish(String message) {
        publisher.publish(message);
        return "消息发送成功!" + new Date();
    }
}

消费者

配置文件:

server:
  port: 8802

spring:
  application:
    name: stream-consumer
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: # 表示定义的名称,用于binding整合(随意)
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关环境配置
            spring:
              rabbitmq:
                host: 47.96.156.51  # RabbitMQ在本机的用localhost,在服务器的用服务器的ip地址
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        input: # 这个名字是一个通道channel的名称
          destination: studyExchange # 表示要使用的Exchange名称
          content-type: text/plain  # 设置消息类型,application/json -> json格式,本文要设置为 text/plain -> 文本类型

监听消息:

@EnableBinding(Sink.class) // (Sink也是spring的)
public class ReceiveMessageListener {

    @StreamListener(Sink.INPUT) // 监听
    public void input(Message<String> message) {
        System.out.println("消费者1号------>收到的消息:" + message.getPayload());
    }
}

Sink接口

image-20220929165116435

注意: output输入信道是stream自带的,还自带了一个输出信道input,上述两个接口。

启动两个项目进行测试,项目启动完成发现studyExchange交换机已经创建好了。

image-20220929165628415

调用发送消息接口,消息发送成功

image-20220929165806075

消费者也成功消费消息

image-20220929165902093

使用自定义信道实现消息传递

上述代码实现是通过stream默认的信道完成的,本部分实现通过自定义信道实现

类比stream默认信道,创建两个自定义信道MySource、MySink

public interface MySource {
    /**
     * Name of the output channel.
     */
    String OUTPUT1 = "output1";

    /**
     * @return output channel
     */
    @Output(OUTPUT1)
    MessageChannel output();
}
public interface MySink {
    /**
     * Input channel name.
     */
    String INPUT1 = "input1";

    /**
     * @return input channel.
     */
    @Input(INPUT1)
    SubscribableChannel input();
}

生产者新增配置项:

image-20220930213141638

同理消费者新增配置项:

image-20220930213310450

接下来改造发送消息实现类

image-20220930213855720

修改该类,EnableBinding注解的值改为绑定多个传入信道接口,然后使用我们自定义信道发送消息。

消费者消费消息

image-20220930214025905

同理,EnableBinding注解的值改为绑定多个信道接口,新建一个方法监听即可。

启动项目,进行测试:

image-20220930214151104

发现我们自定义信道消息也能正常被消费到。

image-20220930214253006

@EnableBinding注解过时

由上图可以看到 @EnableBinding 注解貌似已经过时了。

@EnableBinding源码中明确声明,该注解在从3.1版本开始被弃用,推荐我们使用函数编程的方式

接下来会演示下这种方式基本使用:

生产者案例:

yml配置:

server:
  port: 8801

spring:
  application:
    name: stream-publisher
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: # 表示定义的名称,用于binding整合(随意)
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关环境配置
            spring:
              rabbitmq:
                host: 47.96.156.51  # RabbitMQ在本机的用localhost,在服务器的用服务器的ip地址
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        myChannel-out-0:
          destination: demo #表示要使用Exchange名称定义
          contentType: text/plain

注意使用这种方式,bingdings 集合中的key由 通道名-out/in-数字组成

新版发送消息:

@RestController
public class PublishController {

    @Resource
    StreamBridge bridge;

    @RequestMapping("/publish")
    public String publish(String message) {
        bridge.send("myChannel-out-0", message);
        return "消息发送成功!" + new Date();
    }
}

@Autowire注解自动注入StreamBridge的实例,直接使用StreamBridge发送消息,StreamBridge的send方法第一个参数是binding的名字,第二个参数是想要发送的消息。

消费者案例:

yml配置:

server:
  port: 8802

spring:
  application:
    name: stream-consumer
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: # 表示定义的名称,用于binding整合(随意)
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关环境配置
            spring:
              rabbitmq:
                host: 47.96.156.51  # RabbitMQ在本机的用localhost,在服务器的用服务器的ip地址
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        myChannel-in-0:
          destination: demo
          contentType: text/plain

消费者消费消息:

@Component
public class ConsumerComponent {

    @Bean("myChannel")  
    public Consumer<String> consumer() {
        return message -> System.out.println("新版本消费消息:" + message);
    }
 
 	// 两种方式选其一   
    //@Bean
    //public Consumer<String> myChannel() {
    //    return message -> System.out.println("新版本消费消息:" + message);
    //}
}

注意:@Bean里是yml配置文件中通道名称,这样生产者发送的数据才会正确到达,应用程序启动后会自动接收生产者发送的消息;

或者是方法名为yml配置文件中通道名称,两种方式都能正常消费消息。

启动项目进行测试:

交换机正常创建:

image-20220930223918155

消息发送成功:

image-20220930223539563

消息正常被消费:

image-20220930223617667

完毕!

参考博客:

SpringCloud Stream @EnableBinding注解过时

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Cloud Stream 是一个构建消息驱动微服务的框架,它基于 Spring Boot 和 Spring Integration,通过简单声明式模型来实现消息的发送和接收。Spring Cloud Stream 可以与多种消息中间件集成,如 RabbitMQ、Kafka 等。 使用 Spring Cloud Stream 的步骤如下: 1. 添加依赖 在 pom.xml 中添加 Spring Cloud Stream 相关的依赖,如下: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> </dependency> ``` 2. 创建消息处理器 创建一个消息处理器,用于接收和处理消息,例如: ``` @Component public class MessageHandler { @StreamListener(Sink.INPUT) public void handleMessage(String message) { System.out.println("Received message: " + message); } } ``` 这个消息处理器使用 `@StreamListener` 注解来监听 `Sink.INPUT`,表示接收来自输入通道的消息,并打印出来。 3. 配置绑定器 在配置文件中配置绑定器,用于将应用程序与消息中间件连接起来。例如,如果要使用 RabbitMQ,可以这样配置: ``` spring.cloud.stream.bindings.input.destination=myQueue spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest ``` 这里配置了输入通道的目的地为 `myQueue`,以及 RabbitMQ 的连接信息。 4. 发送消息 使用 `MessageChannel` 来发送消息,例如: ``` @Autowired private MessageChannel output; public void sendMessage(String message) { output.send(MessageBuilder.withPayload(message).build()); } ``` 这里注入了一个 `output` 的 `MessageChannel`,通过它发送消息,例如: ``` sendMessage("Hello, world!"); ``` 这样就可以将一条消息发送到 `myQueue` 队列中。 以上就是使用 Spring Cloud Stream基本步骤。需要注意的是,消息的发送和接收是基于通道(Channel)的,而通道是由绑定器(Binder)来创建和管理的。因此需要在配置文件中配置绑定器相关的信息,才能正常发送和接收消息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不进大厂不改名二号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值