第十二节:Stream(消息驱动)和Sleuth(分布式请求链路跟踪)

一、Stream(消息驱动)

消息驱动概述:

MQ(消息中间件):ActiveMQ、RabbitMQ、RocketMQ、kafkaMQ

解决问题:多种MQ适配(切换、维护、开发)

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

官方连接:https://spring.io/projects/spring-cloud-stream

  • 官方定义 Spring Cloud Stream 是一个构建消息驱动微服务的框架。
  • 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互。
  • 通过我们配置来 binding ,而 Spring Cloud Stream 的 binder 负责与消息中间件交互。所以,我们只需要搞清楚如何与 Spring Cloud Stream 交互就可以方便使用消息驱动的方式。
  • 通过使用Spring Integration来连接消息代理中间件以实现消息事件驱动。
  • Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,引用了发布-订阅、消费组、分区的三个核心概念。
  • 目前仅支持RabbitMQKafka

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

12.1

标准流程套路:Binder、Channel、Source和Sink

12.2

编码API和常用注解:

12.3

案例说明:

RabbitMQ环境OK

新建三个模块:

  • cloud-stream-rabbitmq-provider8801,作为生产者进行发消息模块
  • cloud-stream-rabbitmq-consumer8802,作为消息接收模块
  • cloud-stream-rabbitmq-consumer8803,作为消息接收模块

消息驱动生产者:

pom

<!-- stream rabbit -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

yml

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:
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 #心跳时间间隔
    lease-expiration-duration-in-seconds: 5 #如果现在超过了5秒的间隔
    instance-id: send-8801.com  #在信息列表显示主机名称
    prefer-ip-address: true  #访问路径变为IP地址

主启动类StreamMQMain8801

package com.jiao.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author jyl
 * @create 2021-3-15
 */

@SpringBootApplication
public class StreamMQMain8801 {
    public static void main(String[] args) {
        SpringApplication.run(StreamMQMain8801.class,args);
    }
}

业务类

  • 发送消息接口(IMessageProvider)
package com.jiao.springcloud.service;

public interface IMessageProvider {
    public String send();
}
  • 发送消息接口实现类(IMessageProviderImpl)
package com.jiao.springcloud.service.impl;

import com.jiao.springcloud.service.IMessageProvider;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;

import javax.annotation.Resource;
import java.util.UUID;

@EnableBinding(Source.class)    //定义消息的推送管道
public class IMessageProviderImpl implements IMessageProvider {
    @Resource
    private MessageChannel output;  //消息发送管道

    public String send() {
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());
        System.out.println("*********serial:"+serial);
        return null;
    }
}
  • Controller(SendMessageController)
package com.jiao.springcloud.controller;

import com.jiao.springcloud.service.IMessageProvider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

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

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

12.4

测试(启动7001、启动RabbitMQ、启动8801)

http://localhost:8801/sendMessage

12.5

12.6

消息驱动消费者:

pom

<!-- stream rabbit -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

yml

12.10

主启动

package com.jiao.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author jyl
 * @create 2021-3-15
 */

@SpringBootApplication
public class StreamMQMain8802 {
    public static void main(String[] args) {
        SpringApplication.run(StreamMQMain8802.class,args);
    }
}

业务类

package com.jiao.springcloud.controller;

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
@EnableBinding(Sink.class)
public class ReceiveMessageListenerController {
    @Value("${server.port}")
    private String serverPort;

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

测试(7001、RabbitMQ、8801、8802)

测试8801发送8802接收消息:http://localhost:8801/sendMessage

12.11

12.12

12.13

12.14

分组消费与持久化:

8803与8802一样,yml稍作修改。

启动(RabbitMQ、7001服务注册、8801消息生产、8802消息消费、8803消息消费)

12.15

12.16

运行后两个问题:(分组特性解决)

  • 有重复消费问题

8801请求sendMessage,8802和8803都消费了。

解决:分组和持久化属性group(不同组可以全面消费,同一组会发生竞争关系,其中只有一个可以消费。

12.17

8802/8803变成不同的组,group两个不同。group:(jiaoA,jiaoB)

8802修改yml:

12.18

8803修改yml:与上位置同

12.19

消费了两次。

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

8802/8803变成不同的组,group两个不同。group:(jiaoA,jiaoA)

12.20

结果:8801发送两次,8802消费一次,8803消费一次

  • 消息持久化问题
  1. 停止8802/8803并且去掉8802分组的group:jiaoA,
  2. 8801先发送4条消息到RabbitMQ
  3. 8802启动,消息丢失。8803启动,消息消费,没有丢失。

二、Sleuth(分布式请求链路跟踪)

概述:

链路中任何一环出现延时或者错误都会引起整个请求最后失败。(提供一套完整的服务跟踪的解决方案,兼容支持了zipkin。)

搭建链路监控步骤:

  • zipkin

H版后不用安装Zipkin Server,直接调用jar包。

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

在下载路径启动cmd窗口:输入 java -jar zipkin-server-2.12.9-exec.jar

后台启动:

12.21

运行控制台:http://localhost:9411/zipkin

12.23

Trace:类似于树结构的Span集合,表示一条调用链路,存在唯一标识。

span:表示调用链路来源,通俗讲span就是一次请求信息。

12.22

  • 服务提供者(修改cloud-provider-payment8001)

pom

<!-- 包含了sleuth+zipkin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

yml

...
spring:
  application:
    name: cloud-payment-service
  zipkin:
    base-url: http://localhost:9411
  sleuth: 
    sampler:
      probability: 1  #采样率值介于0-1之间,1表示全部采集
...

业务类PaymentController

...
@GetMapping("/payment/zipkin")
    public String paymentZipkin(){
        return "I'm PaymentZipkin server fall back.";
    }
...
  • 服务消费者(调用方)(修改cloud-consumer-order80)

pom、yml与上面一样

业务类OrderController

...
@GetMapping("/consumer/payment/zipkin")
    public String paymentZipkin(){
        String result = restTemplate.getForObject("http://localhost:8001"+"payment/zipkin",String.class);
        return result;
    }
...

12.24

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java8新特性及实战视频教程完整版Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用Lambda 表达式可以使代码变的更加简洁紧凑。Java8实战视频-01让方法参数具备行为能力Java8实战视频-02Lambda表达式初探Java8实战视频-03Lambda语法精讲Java8实战视频-04Lambda使用深入解析Java8实战视频-05Lambda方法推导详细解析-上.wmvJava8实战视频-06Lambda方法推导详细解析-下Java8实战视频-07Stream入门及Stream在JVM中的线程表现Java8实战视频-08Stream知识点总结Stream源码阅读Java8实战视频-09如何创建Stream上集Java8实战视频-10如何创建Stream下集.wmvJava8实战视频-11Stream之filter,distinct,skip,limit,map,flatmap详细介绍Java8实战视频-12Stream之Find,Match,Reduce详细介绍Java8实战视频-13NumericStream的详细介绍以及和Stream之间的相互转换Java8实战视频-14Stream综合练习,熟练掌握API的用法Java8实战视频-15在Optional出现之前经常遇到的空指针异常.wmvJava8实战视频-16Optional的介绍以及API的详解Java8实战视频-17Optional之flatMap,综合练习,Optional源码剖析Java8实战视频-18初识Collector体会Collector的强大Java8实战视频-19Collector使用方法深入详细介绍-01Java8实战视频-20Collector使用方法深入详细介绍-02Java8实战视频-21Collector使用方法深入详细介绍-03.wmvJava8实战视频-22Collector使用方法深入详细介绍-04Java8实战视频-23Collector原理讲解,JDK自带Collector源码深度剖析Java8实战视频-24自定义Collector,结合Stream的使用详细介绍Java8实战视频-25Parallel Stream编程体验,充分利用多核机器加快计算速度Java8实战视频-26Fork Join框架实例深入讲解Java8实战视频-27Spliterator接口源码剖析以及自定义Spliterator实现一个Stream.wmvJava8实战视频-28Default方法的介绍和简单的例子Java8实战视频-29Default方法解决多重继承冲突的三大原则详细介绍Java8实战视频-30多线程Future设计模式原理详细介绍,并且实现一个Future程序Java8实战视频-31JDK自带Future,Callable,ExecutorService介绍Java8实战视频-32实现一个异步基于事件回调的Future程序.wmvJava8实战视频-33CompletableFuture用法入门介绍Java8实战视频-34CompletableFuture之supplyAsync详细介绍Java8实战视频-35CompletableFuture流水线工作,join多个异步任务详细讲解Java8实战视频-36CompletableFuture常用API的重点详解-上Java8实战视频-37CompletableFuture常用API的重点详解-下Java8实战视频-38JDK老DateAPI存在的问题,新的DateAPI之LocalDate用法及其介绍.wmvJava8实战视频-39New Date API之LocalTime,LocalDateTime,Instant,Duration,Period详细介绍Java8实战视频-40New Date API之format和parse介绍

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值