SpringCloud微服务实战系列教程

  Spring Cloud Stream 消息驱动组件帮助我们更快速,更⽅便,更友好的去构建消息驱动微服务的。当时定时任务和消息驱动的⼀个对⽐。(消息驱动:基于消息机制做⼀些事情)MQ:消息队列/消息中间件/消息代理,产品有很多,ActiveMQ RabbitMQ RocketMQ Kafka

一、 Stream解决的痛点问题

  MQ消息中间件⼴泛应⽤在应⽤解耦合、异步消息处理、流量削峰等场景中。不同的MQ消息中间件内部机制包括使⽤⽅式都会有所不同,⽐如RabbitMQ中有Exchange(交换机/交换器)这⼀概念,kafka有Topic、Partition分区这些概念,MQ消息中间件的差异性不利于我们上层的开发应⽤,当我们的系统希望从原有的RabbitMQ切换到Kafka时,我们会发现切换⽐较困难,很多要操作可能重来(因为⽤程序和具体的某⼀款MQ消息中间件耦合在⼀起了)。
  Spring Cloud Stream进⾏了很好的上层抽象,可以让我们与具体消息中间件解耦合,屏蔽掉了底层具体MQ消息中间件的细节差异,就像Hibernate屏蔽掉了具体数据库(Mysql/Oracle⼀样)。如此⼀
来,我们学习、开发、维护MQ都会变得轻松。⽬前Spring Cloud Stream⽀持RabbitMQ和Kafka。

二、Stream重要概念

  Spring Cloud Stream 是⼀个构建消息驱动微服务的框架。应⽤程序通过inputs(相当于消息消费者consumer)或者outputs(相当于消息⽣产者producer)来与Spring Cloud Stream中的binder对象交互,⽽Binder对象是⽤来屏蔽底层MQ细节的,它负责与具体的消息中间件交互。

  Binder绑定器是Spring Cloud Stream 中⾮常核⼼的概念,就是通过它来屏蔽底层不同MQ消息中间件的细节差异,当需要更换为其他消息中间件时,我们需要做的就是更换对应的Binder绑定器⽽不需要修改任何应⽤逻辑(Binder绑定器的实现是框架内置的,Spring Cloud Stream⽬前⽀持Rabbit、Kafka两种消息队列)

三、Stream消息通信⽅式

  Stream中的消息通信⽅式遵循了发布—订阅模式。在Spring Cloud Stream中的消息通信⽅式遵循了发布-订阅模式,当⼀条消息被投递到消息中间件之后,它会通过共享的 Topic 主题进⾏⼴播,消息消费者在订阅的主题中收到它并触发⾃身的业务逻辑处理。这⾥所提到的 Topic 主题是Spring Cloud Stream中的⼀个抽象概念,⽤来代表发布共享消息给消费者的地⽅。在不同的消息中间件中, Topic 可能对应着不同的概念,⽐如:在RabbitMQ中的它对应了Exchange、在Kakfa中则对应了Kafka中的Topic。

四、基于RabbitMQ应用

  第一步:构建消息生产者

    1、引入依赖pom.ml

  1. <!--eureka client 客户端依赖引⼊-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>
  6. <!--spring cloud stream 依赖(rabbit)-->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
  10. </dependency>

    2、添加配置

    注意:标红的位置应设置相同的binder,蓝色位置必须为output,被默认框架定义好的

  1. server:
  2. port: 9090
  3. spring:
  4. application:
  5. name: stream-provider
  6. cloud:
  7. stream:
  8. binders: # 绑定MQ服务信息(此处我们是RabbitMQ)
  9. cityRabbitBinder: # 给Binder定义的名称,⽤于后⾯的关联
  10. type: rabbit # MQ类型,如果是Kafka的话,此处配置kafka
  11. environment: # MQ环境配置(⽤户名、密码等)
  12. spring:
  13. rabbitmq:
  14. host: localhost
  15. port: 5672
  16. username: guest
  17. password: guest
  18. bindings: # 关联整合通道和binder对象
  19. output: # output是我们定义的通道名称,此处不能乱改
  20. destination: cityExchange # 要使⽤的Exchange名称(消息队列主题名称)
  21. content-type: text/plain # application/json # 消息类型设置,⽐如json
  22. binder: cityRabbitBinder # 关联MQ服务
  23. eureka:
  24. client:
  25. serviceUrl: # eureka server的路径
  26. defaultZone: http://localhost:8761/eureka/
  27. instance:
  28. prefer-ip-address: true #使⽤ip注册

  3、消息发送通过source对象

  1. package city.alber;
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.cloud.stream.annotation.EnableBinding;
  5. import org.springframework.cloud.stream.messaging.Source;
  6. import org.springframework.messaging.support.MessageBuilder;
  7.  
  8. /**
  9. * @author niunafei
  10. * @function
  11. * @email niunafei0315@163.com
  12. * @date 2020/9/24 2:26 PM
  13. * Source.class⾥⾯就是对输出通道的定义(这是Spring Cloud Stream内置的通道封装)
  14. */
  15. @EnableBinding(Source.class)
  16. public class ProviderService {
  17. /**
  18. * 将MessageChannel的封装对象Source注⼊到这⾥使⽤
  19. */
  20. @Autowired
  21. private Source source;
  22.  
  23. public void sendMessage(String content) {
  24. // 向mq中发送消息(并不是直接操作mq,应该操作的是spring cloud stream)
  25. // 使⽤通道向外发出消息(指的是Source⾥⾯的output通道)
  26. source.output().send(MessageBuilder.withPayload(content).build());
  27. }
  28. }

  4、启动类添加@EnableDiscoveryClient 注解,启动

 第二步:构建消息消费者

  下面的内容是和生产者不一致的地方

  1、配置,标蓝地方为不同点

  1. server:
  2. port: 9091
  3. spring:
  4. application:
  5. name: stream-consumer
  6. cloud:
  7. stream:
  8. binders: # 绑定MQ服务信息(此处我们是RabbitMQ)
  9. cityRabbitBinder: # 给Binder定义的名称,⽤于后⾯的关联
  10. type: rabbit # MQ类型,如果是Kafka的话,此处配置kafka
  11. environment: # MQ环境配置(⽤户名、密码等)
  12. spring:
  13. rabbitmq:
  14. host: localhost
  15. port: 5672
  16. username: guest
  17. password: guest
  18. bindings: # 关联整合通道和binder对象
  19. input: # output是我们定义的通道名称,此处不能乱改
  20. destination: cityExchange # 要使⽤的Exchange名称(消息队列主题名称)
  21. content-type: text/plain # application/json # 消息类型设置,⽐如json,自动将对象转为json
  22. binder: cityRabbitBinder # 关联MQ服务
  23. eureka:
  24. client:
  25. serviceUrl: # eureka server的路径
  26. defaultZone: http://localhost:8761/eureka/
  27. instance:
  28. prefer-ip-address: true #使⽤ip注册

    2、接收消费消息类

  1. package city.albert;
  2.  
  3. import org.springframework.cloud.stream.annotation.EnableBinding;
  4. import org.springframework.cloud.stream.annotation.StreamListener;
  5. import org.springframework.cloud.stream.messaging.Sink;
  6. import org.springframework.messaging.Message;
  7.  
  8. /**
  9. * @author niunafei
  10. * @function
  11. * @email niunafei0315@163.com
  12. * @date 2020/9/24 2:43 PM
  13. */
  14. @EnableBinding(Sink.class)
  15. public class ConsumerMsg {
  16. @StreamListener(Sink.INPUT)
  17. public void recevieMessages(Message<String> message) {
  18. System.out.println("=========接收到的消息:" + message);
  19. }
  20. }

五、定义输出

  定一使用与上面配置中蓝色字体的input/ouput类似,定义完成配置应该为 inputSysLog/outputSysLog

  1、定义通过接口,目的是给生产者消费者调用

  1. package city.albert;
  2.  
  3. import org.springframework.cloud.stream.annotation.Input;
  4. import org.springframework.cloud.stream.annotation.Output;
  5. import org.springframework.messaging.MessageChannel;
  6. import org.springframework.messaging.SubscribableChannel;
  7.  
  8. /**
  9. * @author niunafei
  10. * @function
  11. * @email niunafei0315@163.com
  12. * @date 2020/9/24 3:11 PM
  13. */
  14. public interface CustomStreamConfig {
  15.  
  16. String INPUT_SYS_LOG = "inputSysLog";
  17. String OUTPUT_SYS_LOG = "outputSysLog";
  18.  
  19. @Input(INPUT_SYS_LOG)
  20. SubscribableChannel inputSysLog();
  21.  
  22. @Output(OUTPUT_SYS_LOG)
  23. MessageChannel outputSysLog();
  24.  
  25. /**
  26. * 。。。。。可以跟上面一样定义多个通道信息
  27. */
  28. }

  2、生产者调用

  1. package city.albert;
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.cloud.stream.annotation.EnableBinding;
  5. import org.springframework.cloud.stream.annotation.StreamListener;
  6. import org.springframework.messaging.Message;
  7. import org.springframework.messaging.support.MessageBuilder;
  8.  
  9. /**
  10. * @author niunafei
  11. * @function
  12. * @email niunafei0315@163.com
  13. * @date 2020/9/24 3:14 PM
  14. *
  15. */
  16. @EnableBinding(CustomStreamConfig.class)
  17. public class CustomStreamProvider {
  18.  
  19. @Autowired
  20. CustomStreamConfig customStreamConfig;
  21.  
  22. public void sendMessage(String content) {
  23. // 向mq中发送消息(并不是直接操作mq,应该操作的是spring cloud stream)
  24. // 使⽤通道向外发出消息(指的是Source⾥⾯的output通道)
  25. customStreamConfig.outputSysLog().send(MessageBuilder.withPayload(content).build());
  26. }
  27. }

  3、消费者调用

  1. package city.albert;
  2.  
  3. import org.springframework.cloud.stream.annotation.EnableBinding;
  4. import org.springframework.cloud.stream.annotation.StreamListener;
  5. import org.springframework.messaging.Message;
  6.  
  7. /**
  8. * @author niunafei
  9. * @function
  10. * @email niunafei0315@163.com
  11. * @date 2020/9/24 3:14 PM
  12. *
  13. */
  14. @EnableBinding(CustomStreamConfig.class)
  15. public class CustomStreamConsumer {
  16.  
  17. @StreamListener(CustomStreamConfig.INPUT_SYS_LOG)
  18. public void messages(Message<String> message) {
  19. System.out.println("=========接收到的消息:" + message);
  20. }
  21. }

六、分组

  同组内一条消息,只能一个消费者获取,添加配置即可

 

SpringCloud-Stream消息通信的更多相关文章

  1. SpringCloud Stream 消息驱动

    1.什么是消息驱动 SpringCloud Stream消息驱动可以简化开发人员对消息中间件的使用复杂度,让系统开发人员更多尽力专注与核心业务逻辑的开发.SpringCloud Stream基于Spr ...

  2. 九. SpringCloud Stream消息驱动

    1. 消息驱动概述 1.1 是什么 在实际应用中有很多消息中间件,比如现在企业里常用的有ActiveMQ.RabbitMQ.RocketMQ.Kafka等,学习所有这些消息中间件无疑需要大量时间经历成 ...

  3. SpringCloud学习笔记(九、SpringCloud Stream)

    目录: 什么是SpringCloud Stream 如何使用SpringCloud Stream 消息分流 什么是SpringCloud Stream: SpringCloud Stream是一个用于 ...

  4. Spring Cloud Stream消息总线

    Springcloud 里面对于MQ的整合一个是前一篇的消息总线一个是本文介绍的消息驱动 大体要学习这么几个知识点: 课题:SpringCloud消息驱动Stream1.什么是SpringCloud消 ...

  5. 《springcloud 五》springcloud stream

    什么是消息驱动? SpringCloud Stream消息驱动可以简化开发人员对消息中间件的使用复杂度,让系统开发人员更多尽力专注与核心业务逻辑的开发.SpringCloud Stream基于Spri ...

  6. SpringCloud Stream使用案例

    官方定义 Spring Cloud Stream 是一个构建消息驱动微服务的框架. 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互 ...

  7. SpringCloud学习之Stream消息驱动【自定义通道】(十一)

    如果不清楚本篇内容的,请务必先去看完上一篇再看本篇,否则阅读起来可能会有部分障碍和困难: 上一篇文章<SpringCloud学习之Stream消息驱动[默认通道](十)>我们简单用自定义通 ...

  8. SpringCloud(七)Stream消息驱动

    Stream消息驱动 概述 屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型 官网:https://cloud.spring.io/spring-cloud-static/spring-cl ...

  9. SpringCloud 2020.0.4 系列之 Stream 消息广播 与 消息分组 的实现

    1. 概述 老话说的好:事情太多,做不过来,就先把事情记在本子上,然后理清思路.排好优先级,一件一件的去完成. 言归正传,今天我们来聊一下 SpringCloud 的 Stream 组件,Spring ...

随机推荐

  1. 【Azure 服务总线】Azure Service Bus中私信(DLQ - Dead Letter Queue)如何快速清理

    在博文ServiceBus 队列中死信(DLQ - Dead Letter Queue)问题一文中,介绍了服务总线产生私信的原因及可以通过代码的方式来清楚私信队列中的消息,避免长期占用空间(因为私信中 ...

  2. HDOJ-1711(KMP算法)

    Number Sequence HDOJ-1711 1.这里使用的算法是KMP算法,pi数组就是前缀数组. 2.代码中使用到了一个技巧就是用c数组看成是复合字符串,里面加一个特殊整数位-1000006 ...

  3. Python数据格式:%s字符串,%d整型,%f浮点型

    格式化符% name="Tom" age=int(input("age")) pt2="%s你的年龄是%d"%(name,age) prin ...

  4. 【Git】敏感信息保护

    保护Git仓库敏感信息 代码中无可避免有一些敏感信息,包含但不限于,数据库信息,密钥,账号信息等等.通常我们会把这些信息放在配置文件,这些信息若泄露会造成安全问题. 以前我们做法,是把配置文件通过.g ...

  5. 【odoo14】第二十一章、性能优化

    通过odoo框架,我们可以开发大型且复杂的应用.良好的性能是实现这一目标的基础.本章,我们将探讨如何提高应用性能.同时,我们也会讲解找出影响性能的因素. 本章包含以下内容: 记录集的预读取模式 将数据 ...

  6. python-实现顺序栈

    7 class sqstack(object): 8 def __init__(self,maxsize): 9 self.maxsize = maxsize 10 self.stackElem = ...

  7. HashMap 这套八股,不得背个十来遍?

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...

  8. java例题_08 输入特定数字求和(n个a位数递增求和问题)

    1 /*8 [程序 8 输入数字求和] 2 题目:求 s=a+aa+aaa+aaaa+aa...a 的值,其中 a 是一个数字.例如 2+22+222+2222+22222(此时共有 5 个数相加), ...

  9. 为科学计算而生的Julia——基于Manjaro Linux的安装与入门

    技术背景 Julia是一门为科学计算而生的编程语言,其着重强调了开源.生态与性能.从开源角度来说,相比于Matlab就要友好很多,用户可以免费使用,而且MIT协议应该是最宽松的开源协议之一(截图来自于 ...

  10. Android Studio 之 Button(圆角,描边,按压效果)

    •普通Button <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns: ...