Spring Cloud Stream 学习笔记

Spring Cloud Stream

官方文档: https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/

中文手册: https://m.wang1314.com/doc/webapp/topic/20971999.html

是什么?

Spring Cloud Stream is a framework for building highly scalable event-driven microservices connected with shared messaging systems.

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

The framework provides a flexible programming model built on already established and familiar Spring idioms and best practices, including support for persistent pub/sub semantics, consumer groups, and stateful partitions.

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

为什么用?

​ 在没有绑定器这个概念的情况下,我们的SpringBoot应用要直接与消息中间件进行信息交互的时候,由于各消息中间件构建的初衷不同,它们的实现细节上会有较大的差异性通过定义绑定器作为中间层,完美地实现了应用程序与消息中间件细节之间的隔离。通过向应用程序暴露统一的Channel通道,使得应用程序不需要再考虑各种不同的消息中间件实现。通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。

屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型

Kafka是Topic广播,RabbitMQ是Exchange广播

Binders

Spring Cloud Stream provides a Binder abstraction for use in connecting to physical destinations at the external middleware.

Spring cloud Stream是通过Binder来定义一个外部消息服务器。具体对于RabbitMQ来说,Binder就是一个Exchange的抽象。

简而言之就是连接的中间件。

Source Channel Sink 三者意思不再赘述。

原理图:自己看官方文档

组成说明
Middleware中间件
BinderBinder是应用与消息中间件之间的封装
@Input注解标识输入通道,通过该输入通道接收到的消息进入应用程序
@Output注解标识输出通道,发布的消息将通过该通道离开应用程序
@StreamListener监听队列,用于消费者的队列的消息接收
@EnableBinding指信道channel和exchange绑定在一起

Demo

cloud-stream-rabbitmq-provider8801, 作为生产者进行发消息模块

依赖

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <!--基础配置-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

配置

server:
  port: 8801
spring:
  application:
    name: cloud-stream-provider
  cloud:
      stream:
        binders: # 在此处配置要绑定的rabbitmq的服务信息;
          defaultRabbit: # 表示定义的名称,用于于binding整合
            type: rabbit # 消息组件类型
            environment: # 设置rabbitmq的相关的环境配置
              spring:
                rabbitmq:
                  host: localhost
                  port: 5672
                  username: guest
                  password: guest
        bindings: # 服务的整合处理
          output: # 这个名字是一个通道的名称
            destination: studyExchange # 表示要使用的Exchange名称定义
            content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
            binder: defaultRabbit # 设置要绑定的消息服务的具体设置
eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: send-8801.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址

业务类

@EnableBinding(Source.class) // 可以理解为是一个消息的发送管道的定义
public class MessageProviderImpl implements IMessageProvider
{
    @Resource
    private MessageChannel output; // 消息的发送管道

    @Override
    public String send()
    {
        String serial = UUID.randomUUID().toString();
        this.output.send(MessageBuilder.withPayload(serial).build()); // 创建并发送消息
        System.out.println("***serial: "+serial);

        return serial;
    }
}

控制层

@RestController
public class SendMessageController
{
    @Resource
    private IMessageProvider messageProvider;

    @GetMapping(value = "/sendMessage")
    public String sendMessage()
    {
        return messageProvider.send();
    }
}

启动eureka7001,访问http://localhost:8801/sendMessage,可以在rabbitmq对应的exchange看到波峰。

cloud-stream-rabbitmq-consumer8802,作为消息接收模块

依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!--基础配置-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

配置

server:
  port: 8802

spring:
  application:
    name: cloud-stream-consumer
  cloud:
      stream:
        binders: # 在此处配置要绑定的rabbitmq的服务信息;
          defaultRabbit: # 表示定义的名称,用于于binding整合
            type: rabbit # 消息组件类型
            environment: # 设置rabbitmq的相关的环境配置
              spring:
                rabbitmq:
                  host: localhost
                  port: 5672
                  username: guest
                  password: guest
        bindings: # 服务的整合处理
          input: # 这个名字是一个通道的名称
            destination: studyExchange # 表示要使用的Exchange名称定义
            content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
            binder: defaultRabbit # 设置要绑定的消息服务的具体设置

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: receive-8802.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址

业务类

@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListener
{
    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message)
    {
        System.out.println("消费者1号,------->接收到的消息:" + message.getPayload()+"\t port: "+serverPort);
    }
}

测试:http://localhost:8801/sendMessage,8802消费数据,控制台能看到。

cloud-stream-rabbitmq-consumer8803 作为消息接收模块

配置和8802大同小异。

问题?

8802和8803 不出意外的话会有重复消费的问题。还有一个问题就是消息持久问题。

重复消费解决办法如下:

这里说明:如果group组名不同还是会存在消费重复的问题

微服务应用放置于同一个group中,就能够保证消息只会被其中一个应用消费一次,不同的组是可以消费的,同一个组内会发生竞争关系,只有其中一个可以消费。

# 在如下配置下加入组
spring.cloud.stream.bindings.input.group

8802/8803都变成相同的组。这样8802/8803实现了轮询分组,每次只有一个消费者8801模块的发的消息只能被8802或8803其中一个接收到,这样避免了重复消费。

如果消费者断掉,但是重启之后还在特定的组,数据还是能消费掉,反之重启不再之前的组,数据无法消费

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于vue健身小程序正是采用微信小程序和网络设计的新型系统,可以有效的把健身信息与网络相结合,为用户提供工作帮助和管理需求。本系统采用mysql数据库存储数据,兼容性更强,可跨越多种平台,采用的框架为ssm。主要设计的内容包括课程信息、教练信息、健身视频。教练可以上传健身视频,学员可以购买课程和预约教练以及在线充值、发帖。为了可以给用户更多的提醒,本系统中加入了当前登录角色的提示内容。管理员在系统中可以更新各种数据信息。本系统是信息化社会发展的必然产物,可以为用户提供更为高效的管理以及辅助,同时也可以改变健身房管理的局面,提高效率。 登录功能为管理员、教练和学员登录,在登录界面设计中包括用户名和密码、权限的检验。用户名和密码、权限的检验过程由数据库自动完成,此过程需要1秒左右。首先由用户填写账号和密码,选择权限,然后点击登录系统,数据库自行对用户名和密码进行对比,所填写数据正确方能进行登录,所填写数据错误则需要返回登录界面重新登录。首页界面是最直接的展示,用户可以对系统进行最直接的了解。在本功能界面里可以看到背景图片、功能导航栏,视频信息、课程信息、教练信息等。学员信息是健身房的重要组成部分,管理员可以添加学员信息,查询学员信息.。教练信息管理功能分为管理员管理教练信息和登记、查询教练信息,管理员可以看到教练的各项基本信息,可以删除教练的基本信息。系统里展示的健身视频都可以由管理员进行审核和添加管理,教练也可以发布视频。管理员可以输入视频名称和上传视频来实现健身视频的添加。管理员和教练可以上传培训课程,学员可以浏览课程信息。管理员和教练都可以管理预约信息,学员在看到教练后可以进行预约。管理员可以审核帖子信息。管理员、教练和学员都可以管理订单信息。学员在课程详情里可以购买课程。学员在教练详情里可以评价、收藏以及预约。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值