SpringCloud 消息中间件组件、链路跟踪之【Stream && RabbitMQ、Sleuth】

在这里插入图片描述

什么是Spring Cloud Stream

官方定义Spring Cloud Stream是一个构建消息驱动微服务的框架

应用程序通过inputs或者outputs来与Spring Cloud Stream中binder对象交互(我们主要就是操作binder对象与底层mq交换)。通过我们配置来binding(绑定),而Spring Cloud Stream的binder对象负责与消息中间件交互。所以,我们只需要搞清楚如何与Spring Cloud Stream交互就可以方便使用消息驱动的方式。
通过使用Spring Integration来连接消息代理中间件以实现消息事件驱动。Spring Cloud Stream为一些供应商的消息中间件产品提供了个性化的自动化配置实现,引用了发布-订阅、消费组、分区的三个核心概念。目前仅支持RabbitMQ、Kafka.

Spring Cloud Stream是怎么屏蔽底层差异的?
通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。

Spring Cloud Stream的业务流程:
在这里插入图片描述
在这里插入图片描述

消息驱动的生产者

  1. 建模块cloud-stream-rabblitmq-provider8801
  2. 导依赖
<!--stream rabbit -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
  1. 写yml文件
server:
  port: 8801

spring :
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders:          #在此处配置要绑定的rabbitmg的服务信息;       
        defaultRabbit: #表示定义的名称,用于Jbinding整合      注意,这个defalutRabbit是我们自定义的一个名字
          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                     #设置要绑定的消息服务的具体设置,指点上面我们定义的defaultRabbit

eureka:
  client:
    register-with-eureka: true  # true向服务中心注册自己
    fetch-registry: true  # 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/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地址
  1. 主启动类
  2. 业务类
    定义一个发送消息的接口,并编写实现类
import com.kk.springcloud.service.IMessageProvider;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import javax.annotation.Resource;
import java.util.UUID;

// 表示当前这个类是source,负责生产消息,并且发送给channel
@EnableBinding(Source.class)
public class MessageProviderImpl implements IMessageProvider {

    // channel,我们将消息发送给channel
    @Resource
    private MessageChannel output;

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        // 构建消息发送,build方法会构建一个Message类
        output.send(MessageBuilder.withPayload(serial).build());
        System.out.println("*****************serical:"+serial);
        return null;
    }
}

调用send方法,将消息发送给channel,然后channel将消息发送给binder,然后发送到rabbitmq中
6. 写controller,调用接口方法
7. 启动8801后,会在rabbitmq中创建一个Exchange,就是我们配置文件中配置的exchange。访问接口方法

消息驱动的消费者

  1. 同样的步骤
    只是修改一下yml文件中的端口以及将绑定的spring.cloud.bindings.output改为spring.cloud.bindings.input,instance-id也修改一下
server:
  port: 8802

spring :
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders:          #在此处配置要绑定的rabbitmg的服务信息;       注意,这个defalutRabbit
        defaultRabbit: #表示定义的名称,用于Jbinding整合      是我们自定义的一个名字
          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:
    register-with-eureka: true  # true向服务中心注册自己
    fetch-registry: true  # 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka  # 注册地址和端口
  instance:
    lease-renewal-interval-in-seconds: 2            #设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5            #如果现在超过了5秒的间隔(默认是90秒)
    instance-id: send-8802.com
    prefer-ip-address: true  # 访问路径可以显示IP地址
  1. 实现监听
import org.springframework.beans.factory.annotation.Value;
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;
import org.springframework.stereotype.Component;

@Component
// 启动绑定,就是表示当前类是sink,负责接收channel发送过来的数据
@EnableBinding(Sink.class)
public class ReceiveMessageListenerController {

    @Value("${server.port}")
    private String serverPort;

	// 这里表示监听sink的input,而input我们在配置文件中配置了,绑定在了指定Exchange上获取数据
    @StreamListener(Sink.INPUT)
    public void input(Message<String> message){
        System.out.println("我是消费者1号------->接收到的消息:" + message.getPayload()+"\t"+serverPort);
    }
}
  1. 启动8801和8802,测试 生产者生产的消息消费者是否能消费,控制台可以查看结果

重复消费问题

以8802为模板克隆一个8803消费者,都启动测试,会发现8801的生产的消息都被两个消费者消费了。
这是由于8801和8802没有配置分组,默认是不同分组的,所以都对消息进行了消费。
在这里插入图片描述

解决----->定义分组

修改8802,8803的配置文件,都定义为相同分组groupA
在这里插入图片描述
这样生产者生产的消息每一次都只会被同一组内的一个消费者消费

消息持久化问题

停掉8802和8803,删除8802的group分组属性,将8802从A组中移除。此时让8801生产消息,接着重启8802和8803服务,发现8802会发生消息丢失故障,而8803会把未曾消费过的消息重新获得并消费。

链路跟踪

  1. 下载zipkin的zipkin-server-2.12.9-exec.jar
    地址:https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server

  2. jar命令运行jar包
    在这里插入图片描述

  3. 运行控制台
    访问http://localhost:9411/zipkin/
    在这里插入图片描述

使用sleuth:

不需要额外创建项目,使用之前的payment8001和orde80即可

  1. 都导入依赖
<!-- 包含了sleuth zipkin 数据链路追踪-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
  1. 都添加配置
spring:
  zipkin:
    base-url: http://localhost:9411   #指定zipkin的地址
  sleuth:
    sampler:
      probability: 1    #如果是1,表示不放过所有数据    #采样率值介于0到工之间,1则表示全部采集

8001controller中增加一个测试方法

@GetMapping("zipkin")
    public String paymentzipkin(){
        return "hhhhhhhhhhhhhhhhhhhhhhhh-----paymentzipkin";
    }

80服务调用8001服务的方法

@GetMapping("/consumer/payment/zipkin")
    public String paymentzipkin(){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/zipkin", String.class);
    }
  1. 启动服务,调用测试,http://localhost/consumer/payment/zipkin,刷新zipkin窗口,可以查看调用链路和依赖关系
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值