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

        <!--eureka client 客户端依赖引⼊-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--spring cloud stream 依赖(rabbit)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

    2、添加配置

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

server:
port: 9090
spring:
application:
name: stream-provider
cloud:
stream:
binders: # 绑定MQ服务信息(此处我们是RabbitMQ)
cityRabbitBinder: # 给Binder定义的名称,⽤于后⾯的关联
type: rabbit # MQ类型,如果是Kafka的话,此处配置kafka
environment: # MQ环境配置(⽤户名、密码等)
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
bindings: # 关联整合通道和binder对象
output: # output是我们定义的通道名称,此处不能乱改
destination: cityExchange # 要使⽤的Exchange名称(消息队列主题名称)
content-type: text/plain # application/json # 消息类型设置,⽐如json
binder: cityRabbitBinder # 关联MQ服务
eureka:
client:
serviceUrl: # eureka server的路径
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true #使⽤ip注册

  3、消息发送通过source对象

package city.alber;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.support.MessageBuilder; /**
* @author niunafei
* @function
* @email niunafei0315@163.com
* @date 2020/9/24 2:26 PM
* Source.class⾥⾯就是对输出通道的定义(这是Spring Cloud Stream内置的通道封装)
*/
@EnableBinding(Source.class)
public class ProviderService {
/**
* 将MessageChannel的封装对象Source注⼊到这⾥使⽤
*/
@Autowired
private Source source; public void sendMessage(String content) {
// 向mq中发送消息(并不是直接操作mq,应该操作的是spring cloud stream)
// 使⽤通道向外发出消息(指的是Source⾥⾯的output通道)
source.output().send(MessageBuilder.withPayload(content).build());
}
}

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

 第二步:构建消息消费者

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

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

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

    2、接收消费消息类

package city.albert;

import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message; /**
* @author niunafei
* @function
* @email niunafei0315@163.com
* @date 2020/9/24 2:43 PM
*/
@EnableBinding(Sink.class)
public class ConsumerMsg {
@StreamListener(Sink.INPUT)
public void recevieMessages(Message<String> message) {
System.out.println("=========接收到的消息:" + message);
}
}

五、定义输出

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

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

package city.albert;

import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel; /**
* @author niunafei
* @function
* @email niunafei0315@163.com
* @date 2020/9/24 3:11 PM
*/
public interface CustomStreamConfig { String INPUT_SYS_LOG = "inputSysLog";
String OUTPUT_SYS_LOG = "outputSysLog"; @Input(INPUT_SYS_LOG)
SubscribableChannel inputSysLog(); @Output(OUTPUT_SYS_LOG)
MessageChannel outputSysLog(); /**
* 。。。。。可以跟上面一样定义多个通道信息
*/
}

  2、生产者调用

package city.albert;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder; /**
* @author niunafei
* @function
* @email niunafei0315@163.com
* @date 2020/9/24 3:14 PM
*
*/
@EnableBinding(CustomStreamConfig.class)
public class CustomStreamProvider { @Autowired
CustomStreamConfig customStreamConfig; public void sendMessage(String content) {
// 向mq中发送消息(并不是直接操作mq,应该操作的是spring cloud stream)
// 使⽤通道向外发出消息(指的是Source⾥⾯的output通道)
customStreamConfig.outputSysLog().send(MessageBuilder.withPayload(content).build());
}
}

  3、消费者调用

package city.albert;

import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.Message; /**
* @author niunafei
* @function
* @email niunafei0315@163.com
* @date 2020/9/24 3:14 PM
*
*/
@EnableBinding(CustomStreamConfig.class)
public class CustomStreamConsumer { @StreamListener(CustomStreamConfig.INPUT_SYS_LOG)
public void messages(Message<String> message) {
System.out.println("=========接收到的消息:" + message);
}
}

六、分组

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

 

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. 大话Spark(7)-源码之Master主备切换

    Master作为Spark Standalone模式中的核心,如果Master出现异常,则整个集群的运行情况和资源都无法进行管理,整个集群将处于无法工作的状态. Spark在设计的时候考虑到了这种情况 ...

  2. 《C++ Primer》笔记 第5章 语句

    空块的作用等价于空语句. case标签必须是整型常量表达式,default也是一种特殊的case标签. 标签不应该孤零零地出现,它后面必须跟上一条语句或者另外一个case标签. 如果在某处一个带有初值 ...

  3. 剑指 Offer 15. 二进制中1的个数

    剑指 Offer 15. 二进制中1的个数 Offer 15 题目描述: 方法一:使用1逐位相与的方式来判断每位是否为1 /** * 方法一:使用1逐位与的方法 */ public class Off ...

  4. 1.2 Python3基础-规范

    >>返回主目录 总的来说,如果安装的不是安装的Anaconda,pip命令还是经常会用到的(cmd模式使用),当然也可以在PyCharm中直接安装 PEP8规范,我另有一篇博客已经写好,可 ...

  5. 2020年12月-第02阶段-前端基础-CSS Day03

    CSS Day03 盒子模型(CSS重点) css学习三大重点: css 盒子模型 . 浮动 . 定位 主题思路: 理解: 1.能说出盒子模型有那四部分组成 2.能说出内边距的作用以及对盒子的影响 3 ...

  6. C++高精度计算(大整数类)

    Java和Pathon可以不用往下看了 C++的基本数据类型中,范围最大的数据类型不同编译器不同,但是最大的整数范围只有[-2^63-2^63-1](对应8个字节所对应的二进制数大小).但是对于某些需 ...

  7. JavaScript快速上手

    引入JavaScript项目 在html中 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  8. linux 安装FastFdfs

    一.安装依赖软件和类库(安装前的准备) 依次执行以下命令: yum install gcc-c++ -y yum -y install zlib zlib-devel pcre pcre-devel ...

  9. 涂鸦基于OAuth2在开发者平台上的探索与实践

    前言 开发授权(OAuth2)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资料(如照片.视频.联系人列表),而无需将用户名和密码提供给第三方应用. OAuth2允许用户提供一 ...

  10. [set]JZOJ 5821 手机信号

    Description