• Spring Cloud Alibaba学习笔记(12)


    什么是Spring Cloud Stream

    一个用于构建消息驱动的微服务的框架

    应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互,通过我们配置来 binding ,而 Spring Cloud Stream 的 binder 负责与中间件交互。所以,我们只需要搞清楚如何与 Spring Cloud Stream 交互就可以方便使用消息驱动的方式

    Spring Cloud Stream编程模型

    • Destination Binder(目标绑定器)
      • 与消息中间件通信的组件
    • Destination Bindings(目标绑定)
      • Binding是连接应用程序与消息中间件的桥梁,用于消息的消费和生产,有Binder创建
    • Message(消息)

    微服务集成了Stream,Stream的Destination Binder创建了两个Binding,左边的Binding连接Rabbit MQ,右边的MQ连接Kafka。
    左边的Binding从Rabbit MQ处消费消息,然后经过Application处代码的处理,把处理结果传输给Kafka。【从Rabbit MQ处消费消息,然后经过处理,生产到Kafka】

    使用Spring Cloud Stream 实现消息收发

    编写生产者

    添加依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
    </dependency>
    

    注意groupIdcom.alibaba.cloud,而不是org.springframework.cloud

    添加注解

    在启动类上添加@EnableBinding注解,其中Source用来发送消息

    @SpringBootApplication
    @EnableBinding(Source.class)
    public class Study01Application {
        public static void main(String[] args) {
            SpringApplication.run(Study01Application.class, args);
        }
    }
    

    添加配置

    rocketmq.binder.name-server RocketMQ控制台地址
    output 表示生产者,用于绑定一个topic投递消息
    bindings.output.destination 指定topic

    spring:
      cloud:
        stream:
          rocketmq:
            binder:
              name-server: 127.0.0.1:9876
          bindings:
            # 生产者
            output:
              # 指定topic
              destination: topic-stream
    

    代码实现

    注入Source接口,用来实现消息发送
    MessageBuilder构建消息体

    @Autowired
    private Source source;
    
    @GetMapping("test-stream")
    public String testStream() {
        this.source.output()
                .send(
                        MessageBuilder
                                .withPayload("消息体")
                                .build()
                );
        return "testStream";
    }
    

    控制台查看

    启动项目,请求之后,可以在RocketMQ控制台-消息页面看见topic为topic-stream的消息

    编写消费者

    添加依赖

    同生产者

    添加注解

    @SpringBootApplication
    @EnableBinding(Sink.class)
    public class Study02Application {
        public static void main(String[] args) {
            SpringApplication.run(Study02Application.class, args);
        }
    }
    

    添加配置

    input表示消费者,用于绑定一个topic消费消息
    destination指定topic,要与生产者的topic相对应.在使用RocketMQ时,group必填;使用其他MQ时,可以留空

    spring:
      cloud:
        stream:
          rocketmq:
            binder:
              name-server: 127.0.0.1:9876
          bindings:
            # 消费者
            input:
              # 指定topic,要与生产者的topic匹配
              destination: topic-stream
              # 根据业务指定
              # 一定要设置,否则会启动报错
              # 如果使用的是其他的MQ,可以留空
              group: group-stream
    

    代码实现

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.stream.annotation.StreamListener;
    import org.springframework.cloud.stream.messaging.Sink;
    import org.springframework.stereotype.Service;
    
    @Service
    @Slf4j
    public class testStreamConsumer {
        @StreamListener(Sink.INPUT)
        public void receive(String messageBody) {
            log.info("------>" + messageBody);
        }
    }
    

    测试结果

    Spring Cloud Stream自定义接口

    在以上的例子中,我们发现只可以设置一个topic,这显然满足不了实际的生产需求,所以这个时候就需要用到stream的自定义接口来实现多个“input”和“output”绑定不同的topic了。

    生产者发送消息时使用的是Source接口里的output方法,而消费者接收消息时使用的是Sink接口里的input方法,并且都需要配置到启动类的@EnableBinding注解里。所以实际上我们需要自定义接口的源码与这两个接口的源码几乎一致,只是名称有所不同而已,使用上也只是将Source和Sink改为自定义的接口即可。

    自定义发送消息

    自定义消息发送接口

    import org.springframework.cloud.stream.annotation.Output;
    import org.springframework.messaging.MessageChannel;
    
    /**
     * 自定义发送消息接口
     */
    public interface customizeSource {
        String CUSTOMIZE_OUTPUT = "customize-output";
    
        @Output(CUSTOMIZE_OUTPUT)
        MessageChannel output();
    }
    
    

    修改注解

    在启动类的@EnableBinding注解上添加刚刚自定义的消息发送接口

    @EnableBinding({Source.class, customizeSource.class})
    

    修改配置

    注意customize-output的值一定要与自定义消息发送接口中@Output注解的值相同

    cloud:
      stream:
        rocketmq:
          binder:
            name-server: 127.0.0.1:9876
        bindings:
          # 生产者
          output:
            # 指定topic
            destination: topic-stream
          customize-output:
            destination: topic-stream-customize
    

    代码实现

    @Autowired
    private CustomizeSource customizeSource;
    
    @GetMapping("test-stream-customize")
    public String testCustomizeStream() {
        customizeSource.output()
                .send(
                        MessageBuilder
                                .withPayload("消息体")
                                .build()
                );
        return "testStream";
    }
    

    验证

    自定义接收消息

    自定义消息接收接口

    import org.springframework.cloud.stream.annotation.Input;
    import org.springframework.messaging.SubscribableChannel;
    
    /**
     * 自定义消费消息接口
     */
    public interface CustomizeSink {
        String CUSTOMIZE_INPUT = "customize-input";
    
        @Input(CUSTOMIZE_INPUT)
        SubscribableChannel input();
    }
    

    修改注解

    在启动类的@EnableBinding注解上添加刚刚自定义的消息接收接口

    @EnableBinding({Sink.class, CustomizeSink.class})
    

    修改配置

    注意customize-input的值一定要与自定义消息发送接口中@Input注解的值相同

    cloud:
        stream:
          rocketmq:
            binder:
              name-server: 127.0.0.1:9876
    
          bindings:
            # 消费者
            input:
              # 指定topic,要与生产者的topic匹配
              destination: topic-stream
              # 根据业务指定
              # 一定要设置,否则会启动报错
              # 如果使用的是其他的MQ,可以留空
              group: group-stream
            customize-input:
              destination: topic-stream-customize
              group: group-stream-customize
    

    代码实现

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.stream.annotation.StreamListener;
    import org.springframework.stereotype.Service;
    
    @Service
    @Slf4j
    public class CustomizeStreamConsumer {
        @StreamListener(CustomizeSink.CUSTOMIZE_INPUT)
        public void receive(String messageBody) {
            log.info("------>自定义>" + messageBody);
        }
    }
    

    验证

    PS:总结来说,@EnableBinding注解的Source接口实现了发送消息,Sink接口实现了接收消息.而@EnableBinding还有一个Processor接口,Processor接口继承了Source接口和Sink接口,使用这个接口可以实现收发消息

    package org.springframework.cloud.stream.messaging;
    
    public interface Processor extends Source, Sink {
    }
    
  • 相关阅读:
    rpc error: code = Internal desc = stream terminated by RST_STREAM with error code: PROTOCOL_ERROR
    golang处理signal
    docker容器添加微软雅黑字体
    docker容器里设置中文时区
    SecureCRT自动上传文件python脚本
    联想Y50耳机插入耳机孔后没有声音解决办法
    win10 svchost.exe (LocalSystemNetworkRestricted)大量读写数据
    虚拟机加入主机对应的局域网的设置
    解决VM Workstation安装VMware Tools显示灰色的办法
    关于SET QUOTED_IDENTIFIER {ON|OFF}的问题
  • 原文地址:https://www.cnblogs.com/fx-blog/p/11740688.html
Copyright © 2020-2023  润新知