• Spring Cloud Stream


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

    概述
    Spring Cloud Stream由一个中间件中立的核组成。应用通过Spring Cloud Stream插入的input(相当于
    消费者consumer,它是从队列中接收消息的)output(相当于生产者producer,它是从队列中发送消
    息的。)通道与外界交流。通道通过指定中间件的Binder实现与外部代理连接。业务开发者不再关注具
    体消息中间件,只需关注Binder对应用程序提供的抽象概念来使用消息中间件实现业务即可。

    说明:最底层是消息服务,中间层是绑定层,绑定层和底层的消息服务进行绑定,顶层是消息生产者和
    消息消费者,顶层可以向绑定层生产消息和和获取消息消费

    绑定器
    Binder 绑定器是Spring Cloud Stream中一个非常重要的概念。在没有绑定器这个概念的情况下,我们
    的Spring Boot应用要直接与消息中间件进行信息交互的时候,由于各消息中间件构建的初衷不同,它
    们的实现细节上会有较大的差异性,这使得我们实现的消息交互逻辑就会非常笨重,因为对具体的中间
    件实现细节有太重的依赖,当中间件有较大的变动升级、或是更换中间件的时候,我们就需要付出非常
    大的代价来实施。
    通过定义绑定器作为中间层,实现了应用程序与消息中间件(Middleware)细节之间的隔离。通过向应用
    程序暴露统一的Channel通过,使得应用程序不需要再考虑各种不同的消息中间件的实现。当需要升级
    消息中间件,或者是更换其他消息中间件产品时,我们需要做的就是更换对应的Binder绑定器而不需要
    修改任何应用逻辑 。甚至可以任意的改变中间件的类型而不需要修改一行代码。
    Spring Cloud Stream支持各种binder实现,下表包含GitHub项目的链接。

    RabbitMQ
    Apache Kafka
    Amazon Kinesis
    Google PubSub (partner maintained)
    Solace PubSub+ (partner maintained)
    Azure Event Hubs (partner maintained)

    通过配置把应用和spring cloud stream 的 binder 绑定在一起,之后我们只需要修改 binder 的配置来
    达到动态修改topic、exchange、type等一系列信息而不需要修改一行代码。
    发布/订阅模型
    在Spring Cloud Stream中的消息通信方式遵循了发布-订阅模式,当一条消息被投递到消息中间件之
    后,它会通过共享的 Topic 主题进行广播,消息消费者在订阅的主题中收到它并触发自身的业务逻辑处
    理。这里所提到的 Topic 主题是Spring Cloud Stream中的一个抽象概念,用来代表发布共享消息给消
    费者的地方。在不同的消息中间件中, Topic 可能对应着不同的概念,比如:在RabbitMQ中的它对应
    了Exchange、而在Kakfa中则对应了Kafka中的Topic。

    案例中通过rabbitMQ作为消息中间件,完成SpringCloud Stream的案例。需要自行安装
    消息生产者
    (1)创建工程引入依赖

        <dependencies>
            <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>
        </dependencies>

    (2)定义bingding
    发送消息时需要定义一个接口,不同的是接口方法的返回对象是 MessageChannel:

    /**
     * 自定义的消息通道
     */
    public interface MyProcessor {
    
        /**
         * 消息生产者的配置
         */
        String MYOUTPUT = "myoutput";
    
        @Output("myoutput")
        MessageChannel myoutput();
    
        /**
         * 消息消费者的配置
         */
        String MYINPUT = "myinput";
    
        @Input("myinput")
        SubscribableChannel myinput();
    }
    /**
     * 负责向中间件发送数据
     */
    @Component
    @EnableBinding(MyProcessor.class)
    public class MessageSender {
    
        @Autowired
        @Qualifier(value="myoutput")
        private MessageChannel myoutput;
    
        //发送消息
        public void send(Object obj) {
            myoutput.send(MessageBuilder.withPayload(obj).build());
        }
    }

    yml清单

    server:
      port: 7001 #服务端口
    spring:
      application:
        name: stream_producer #指定服务名
      rabbitmq:
        addresses: 192.168.180.137
        username: guest
        password: guest
      cloud:
        stream:
          bindings:
            output:
              destination: topcheer-default  #指定消息发送的目的地,在rabbitmq中,发送到一个topcheer-default的exchange中
            myoutput:
              destination: topcheer-custom-output
    #          producer:
    #            partition-key-expression: payload  #分区关键字   对象中的id,对象
    #            partition-count: 2  #分区大小
          binders:  #配置绑定器
            defaultRabbit:
              type: rabbit

    消息消费者
    (1)创建工程引入依赖

      <dependencies>
            <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>
        </dependencies>

    2)定义bingding
    同发送消息一致,在Spring Cloud Stream中接受消息,需要定义一个接口。

    /**
     * 自定义的消息通道
     */
    public interface MyProcessor {
    
        /**
         * 消息生产者的配置
         */
        String MYOUTPUT = "myoutput";
    
        @Output("myoutput")
        MessageChannel myoutput();
    
        /**
         * 消息消费者的配置
         */
        String MYINPUT = "myinput";
    
        @Input("myinput")
        SubscribableChannel myinput();
    }
    @Component
    @EnableBinding(MyProcessor.class)
    public class MessageListener {
    
        //监听binding中的消息
        @StreamListener(MyProcessor.MYINPUT)
        public void input(String message) {
            System.out.println("获取到消息: "+message);
        }
    
    }

    yml清单

    server:
      port: 7002 #服务端口
    spring:
      application:
        name: rabbitmq-consumer #指定服务名
      rabbitmq:
        addresses: 192.168.180.137
        username: guest
        password: guest
      cloud:
        stream:
    #      instanceCount: 2  #消费者总数
    #      instanceIndex: 0  #当前消费者的索引
          bindings:
            input: #内置的获取消息的通道 , 从topcheer-default中获取消息
              destination: topcheer-default
            myinput:
              destination: topcheer-custom-output
    #          group: group1
    #          consumer:
    #            partitioned: true  #开启分区支持
          binders:
            defaultRabbit:
              type: rabbit

     

     测试类:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = ProducerApplication.class)
    public class Test {
    
        @Autowired(required = false)
        private MessageSender messageSender;
    
        @org.junit.Test
        public void toSend(){
            messageSender.send("测试");
        }
    }

  • 相关阅读:
    感谢燕玲,搞定了客商名称输入即开始检测是否存在
    一步一步学习sqlserverBI多维数据库建立
    sql语句创建文件夹、判断文件夹、创建数据库、表、
    自定义Silverlight DataGrid行列:Defining Columns for a Silverlight DataGrid
    精简版XP SP3安装IIS6,过程坎坷,以此文献给有需要的朋友
    SilverLight 4页面跳转大全(转载)
    如何修改.net framework(转载)
    定义silverlight报表样式Styling a Silverlight Chart
    Silverlight Toolkit DataGrid 单元格内容对齐样式
    一步一步学习sqlserver BI数据仓库设计
  • 原文地址:https://www.cnblogs.com/dalianpai/p/12300738.html
Copyright © 2020-2023  润新知