第八章 springcloud消息驱动与链路跟踪笔记

一、SpringCloudStream消息驱动

SpringCloudStream看名字就知道他和消息队列相关,但它又不是消息队列,准确来说它类似于硬件里面的驱动程序,也就是前面说的适配器模式的体现。

在系统开发里面难免用到消息队列,但各个的消息队列又有所区别,SpringCloudStream的作用就是屏蔽各种消息队列的区别,对消息队列的API进行进一步的抽象,使得在springcloud里面能更加方便的集成各种消息系统。

首先来看SpringCloudStream的组成:

 

不管是生产者还是消费者,并不会直接和消息中间件打交道,在SpringCloudStream中抽象了已成binder(绑定层),有了这一层,使用者并不关心具体的消息中间件配置了,由访问层真正的和消息队列进行通信。

代码Git地址:https://gitee.com/hankin_chj/springcloud-micro-service.git

1、创建消息生产者

创建一个新的模块springcloud-micro-stream-provider,这模块负责生产一个消息

1.1、pom文件如下,映入springcloudstream的相关组件

<dependencies>
    <dependency>
        <groupId>com.chj</groupId>
        <artifactId>springcloud-micro-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
</dependencies>

1.2、修改application.yml文件

server:
  port: 8401
spring:
  application:
    name: springcloud-micro-stream-provider
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                addresses: localhost
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: HnakinExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

1.3、stream-provider定义一个消息发送接口

public interface IMessageProvider {
    void send(Product product);
}

stream-provider定义接口的实现类:

package com.chj.service.impl;
import com.chj.service.IMessageProvider;
import com.chj.vo.Product;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import javax.annotation.Resource;
@EnableBinding(Source.class)
public class MessageProviderImpl implements IMessageProvider {
    @Resource
    private MessageChannel output;  // 消息的发送管道
    @Override
    public void send(Product product) {
        output.send(MessageBuilder.withPayload(product).build());
    }
}

1.4、stream-provider定义启动类主程序

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

1.5、stream-provider编写测试类

@SpringBootTest(classes = StreamProviderApp.class)
@RunWith(SpringRunner.class)
public class TestMessageProvider {
    @Resource
    private IMessageProvider messageProvider;
    @Test
    public void testSend() {
        Product product = new Product();
        product.setProductId(1L);
        product.setProductName("messageName");
        product.setProductDesc("test springcloud stream message");
        messageProvider.send(product);
    }
}

1.5、运行测试方法

查看RabbitMQ控制台:http://localhost:15672/,已经产生了个消息:

 

对于RabbitMQ来说,在这默认的Exchange的类型是Topic。

2、创建消息消费者

新建模块springcloud-micro-stream-consumer,作为消息的消费者。

2.1、修改pom文件如下

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <dependency>
        <groupId>com.chj</groupId>
        <artifactId>springcloud-micro-api</artifactId>
    </dependency>
</dependencies>

2.2、修改application.yml配置文件

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

2.3、定义一个消息的监听

@Component
@EnableBinding(Sink.class)
public class MessageListener {
    @StreamListener(Sink.INPUT)
    public void input(Message<Product> message) {
        System.err.println("【*** 消息接收 ***】" + message.getPayload());
    }
}

2.4、创建启动类

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

启动后,发现rabbitmq里面已经有了一个消费者

 

stream-provider运行测试类,stream-consumer已经收到消息:

 

【rabbitmq】在消息队列中,也检测到了这匿名队列,可以发现Exchange默认的类型就是TOPIC,RoutingKey我们没有自定,默认的就是#,会给所有的消费者发消息。

 

3、自定义消息通道

前面在创建消息生产者的时候用到了@EnableBinding(Source.class)

在创建消息消费者的时候用到了@EnableBinding(Sink.class)

3.1、可以查看下Source.class与Sink.class的源码:

public interface Source {
    String OUTPUT = "output";
    @Output("output")
    MessageChannel output();
}

public interface Sink {
    String INPUT = "input";
    @Input("input")
    SubscribableChannel input();
}

其实这个input、output就是对应配置文件里面的内容,其实用户也是可以自定义管道信息的。

由于在tream-provider与stream-consumer这两个模块中都需要用到自定义管道信息,所以我们在系统api模块增加stream支持。

3.2、springcloud-micro-api修改pom文件,增加stream的支持

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

3.3、api模块增加管道接口

public interface DefaultProcess {
    public static final String OUTPUT = "hankin_output"; // 输出通道名称
    public static final String INPUT = "hankin_input"; // 输入通道名称
    @Input(DefaultProcess.INPUT)
    public SubscribableChannel input();
    @Output(DefaultProcess.OUTPUT)
    public MessageChannel output();
}

3.4、stream-provider修改application.yml配置文件

server:
  port: 8401
spring:
  application:
    name: springcloud-micro-stream-provider
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                addresses: localhost
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        hankin_output:
#        output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: HnakinExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

3.5、stream-consumer修改application.yml文件

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

3.6、stream-provider修改MessageProviderImpl发送实现类

//@EnableBinding(Source.class)
@EnableBinding(DefaultProcess.class)
public class MessageProviderImpl implements IMessageProvider {
    @Resource
    @Qualifier("hankin_output") //TODO 用于查询注定名称注解对应 @Output(DefaultProcess.OUTPUT)
    private MessageChannel output;  // 消息的发送管道
    @Override
    public void send(Product product) {
        output.send(MessageBuilder.withPayload(product).build());
    }
}

3.7、stream-consumer修改MessageListener

@Component
//@EnableBinding(Sink.class)
@EnableBinding(DefaultProcess.class)
public class MessageListener {
//    @StreamListener(Sink.INPUT)
    @StreamListener(DefaultProcess.INPUT) //TODO 用于查询注定名称注解对应  @Input(DefaultProcess.INPUT)
    public void input(Message<Product> message) {
        System.err.println("【*** 消息接收 ***】" + message.getPayload());
    }
}

修改之后就可以用自定义管道了。

3.8、分别启动服务消费者和提供者

测试发小消息成功后,查看MQ管理平台多了我们自定义的管道名字,实际对应的就是exchange。

 

4、分组(队列)

Group分组其实就是对应rabbitmq里面得队列,在前面的案例中,我们并没有指定group,产生的就是一个匿名队列。如果启动了多个stream-consumer接收者,但并没有指定group,那么将会产生多个匿名的消息队列,导致多个接收者都会收到同一个消息,也就是说一个消息被重复消费了,这在某些业务场景来说是并不运行的。

这个时候就需要用到group分组了,对于不想重复消费个某消息的各个消费者必须属于同一个组。

4.1、stream-consumer修改application.yml

server:
  port: 8402
spring:
  application:
    name: springcloud-micro-stream-consumer
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                addresses: localhost
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        hankin_input:
#        input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: HnakinExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
          group: hankin_group

4.2、启动了多个stream-consumer接收者

由于指定了group,在rabbitmq也就只会产生一个队列。

这个时候服务生产者stream-provider发送的任何消息都只会被同一个group的某一个消费者处理了。

 

5、设置RoutingKey

RoutingKey其实是RabbitMQ的概念,在RabbitMQ里面其实有好几种Exchange,在SpringCloudStream里面默认就是使用的最通用的Topic。如果没有配置RoutingKey,它使用的RoutingKey其实就是#,既类似于fanout的广播类型,其实也可以使用RoutingKey来实现类似于direct类型,也就是直连方式。

5.1、stream-consumer修改application.yml配置文件

server:
  port: 8402
spring:
  application:
    name: springcloud-micro-stream-consumer
  cloud:
    stream:
      rabbit:
        bindings:
          hankin_input:
            consumer:
              bindingRoutingKey: hankinKey # 设置一个RoutingKey信息
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                addresses: localhost
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        hankin_input:
#        input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: HnakinExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
          group: hankin_group

5.2、stream-provider定义RoutingKey的表达式配置

server:
  port: 8401
spring:
  application:
    name: springcloud-micro-stream-provider
  cloud:
    stream:
      rabbit:
        bindings:
          hankin_output:
            producer:
              routingKeyExpression: '''hankinKey'''
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                addresses: localhost
                port: 5672
                username: admin
                password: admin
                virtual-host: /
      bindings: # 服务的整合处理
        hankin_output:
#        output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: HnakinExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

5.3、运行服务测试

 

二、SpringCloudSleuth链路跟踪

在微服务的架构下,系统由大量服务组成,每个服务可能是由不同的团队开发,开发使用不同的语言,部署在几千台服务器上,并且横跨多个不同的数据中心,一次请求绝大多数情况会涉及多个服务,在系统发生故障的时候,想要快速定位和解决问题,就需要跟踪服务请求序列。

 SpringCloudSleuth使用的核心组件是Twitter推出的Zipkin监控组件,zipkin就是一个分布式的跟踪系统,用户收集服务的数据。

1、基本使用

1.1、新建跟踪服务

新建立模块springcloud-micro-sleuth,这个模块用户跟踪用户的请求,把请求的链路进行展示

Pom依赖如下:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-sleuth</artifactId>

<version>2.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>

<version>2.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-server</artifactId>
        <version>2.9.4</version>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-ui</artifactId>
        <version>2.9.4</version>
    </dependency>
</dependencies>

1.2、修改application.yml文件

server:
  port: 8601
spring:
  application:
    name: springcloud-micro-sleuth
management:
  metrics:
    web:
      server:
        auto-time-requests: false

1.3、新建启动类@EnableZipkinServer

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

2、客户端配置

为了演示链路追踪,需要启动一些列服务:eureka、user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix等服务。下图为显示的最终结果:

 

启动eureka这个服务的目的是让product、users两服务注册到其中,后面需要zuul的调用。

2.1、修改以下服务的pom文件,增加sleuth的支持

需要修改的服务:user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix

<!-- springcloud sleuth -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

偶尔有可能下载不到,如果不行,用下面这个:

<!-- springcloud sleuth -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

2.2、修改以下服务的application.yml文件,增加zipkin的配置

需要修改的服务:user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix

spring:
  zipkin: # 添加springcloud链路追踪sleuth
    base-url: http://localhost:8601 #所有的数据提交到此服务之中
    sender:
      type: web  #提交的类型是web 服务
  sleuth:
    sampler:
      probability: 1.0 # 定义抽样比率,默认为0.1

2.3、依次启动服务测试

需要依次启动:eureka、user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix

首先访问接口:http://localhost/consumer/product/getProductAndUser?id=1

访问跟踪服务:http://localhost:8601/zipkin/dependency/

结果如下如所示:

 

3、数据持久化

现在以及成功实现了一个 SpringCloudSleuth 的基本操作,但会发现,如果重新启动sleuth服务,所有的链路跟踪数据都会丢失,那么这些数据应该存储到数据库里面的。但又有另外一个问题,如果请并发量特别大,对于mysql来说可能会承受不了这么大的并发,为了解决这个问题,可以使用消息队列缓冲处理,最后才从mq中把数据存到mysql中。

3.1、先在数据库里面创建zipkin的表

https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql

DROP DATABASE IF EXISTS zipkin ;
CREATE DATABASE zipkin CHARACTER SET UTF8 ;
USE zipkin ;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for zipkin_annotations
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_annotations`;
CREATE TABLE `zipkin_annotations`  (
  `trace_id_high` bigint(20) NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` bigint(20) NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
  `span_id` bigint(20) NOT NULL COMMENT 'coincides with zipkin_spans.id',
  `a_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
  `a_value` blob NULL COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
  `a_type` int(11) NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
  `a_timestamp` bigint(20) NULL DEFAULT NULL COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
  `endpoint_ipv4` int(11) NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_ipv6` binary(16) NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
  `endpoint_port` smallint(6) NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_service_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  UNIQUE INDEX `trace_id_high`(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) USING BTREE COMMENT 'Ignore insert on duplicate',
  INDEX `trace_id_high_2`(`trace_id_high`, `trace_id`, `span_id`) USING BTREE COMMENT 'for joining with zipkin_spans',
  INDEX `trace_id_high_3`(`trace_id_high`, `trace_id`) USING BTREE COMMENT 'for getTraces/ByIds',
  INDEX `endpoint_service_name`(`endpoint_service_name`) USING BTREE COMMENT 'for getTraces and getServiceNames',
  INDEX `a_type`(`a_type`) USING BTREE COMMENT 'for getTraces and autocomplete values',
  INDEX `a_key`(`a_key`) USING BTREE COMMENT 'for getTraces and autocomplete values',
  INDEX `trace_id`(`trace_id`, `span_id`, `a_key`) USING BTREE COMMENT 'for dependencies job'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compressed;
-- ----------------------------
-- Table structure for zipkin_dependencies
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_dependencies`;
CREATE TABLE `zipkin_dependencies`  (
  `day` date NOT NULL,
  `parent` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `child` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `call_count` bigint(20) NULL DEFAULT NULL,
  `error_count` bigint(20) NULL DEFAULT NULL,
  UNIQUE INDEX `day`(`day`, `parent`, `child`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compressed;
-- ----------------------------
-- Table structure for zipkin_spans
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_spans`;
CREATE TABLE `zipkin_spans`  (
  `trace_id_high` bigint(20) NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` bigint(20) NOT NULL,
  `id` bigint(20) NOT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `parent_id` bigint(20) NULL DEFAULT NULL,
  `debug` bit(1) NULL DEFAULT NULL,
  `start_ts` bigint(20) NULL DEFAULT NULL COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
  `duration` bigint(20) NULL DEFAULT NULL COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
  UNIQUE INDEX `trace_id_high`(`trace_id_high`, `trace_id`, `id`) USING BTREE COMMENT 'ignore insert on duplicate',
  INDEX `trace_id_high_2`(`trace_id_high`, `trace_id`, `id`) USING BTREE COMMENT 'for joining with zipkin_annotations',
  INDEX `trace_id_high_3`(`trace_id_high`, `trace_id`) USING BTREE COMMENT 'for getTracesByIds',
  INDEX `name`(`name`) USING BTREE COMMENT 'for getTraces and getSpanNames',
  INDEX `start_ts`(`start_ts`) USING BTREE COMMENT 'for getTraces ordering and range'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compressed;
SET FOREIGN_KEY_CHECKS = 1;

3.2、sleuth服务修改pom文件

springcloud-micro-sleuth服务修改pom文件,增加数据库,消息队列相关的依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-sleuth</artifactId>
        <version>2.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>
        <version>2.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-server</artifactId>
        <version>2.9.4</version>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-ui</artifactId>
        <version>2.9.4</version>
    </dependency>
    <!-- 链路数据持久化支持 -->
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-collector-rabbitmq</artifactId>
        <version>2.9.4</version>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-storage-mysql</artifactId>
        <version>2.9.4</version>
    </dependency>
</dependencies>

3.3、sleuth服务修改application.yml文件

server:
  port: 8601
spring:
  application:
    name: springcloud-micro-sleuth
management:
  metrics:
    web:
      server:
        auto-time-requests: false
# 链路追踪数据持久化配置
zipkin:
  collector:
    sample-rate: 1.0
    http:
      enabled: false
    rabbitmq:
      addresses: localhost:5672
      username: admin
      password: admin
      queue: zipkin
      virtual-host: /
  storage:
    type: mysql
    mysql:
      host: localhost
      port: 3306
      username: root
      password: root
      db: zipkin

3.4、其他服务增加RabbitMQ相关依赖

确认客户方都有rabbitmq的依赖,修改pom文件,增加相关依赖,主要涉及链路追踪的服务有:

user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix

<!-- springcloud sleuth -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>

3.5、相关application.yml文件修改zipkin的配置

修改以下服务的application.yml文件,修改zipkin的配置type改为rabbit,主要涉及链路追踪的服务有:

user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix

spring:
  zipkin: # 添加springcloud链路追踪sleuth
    base-url: http://localhost:8601 #所有的数据提交到此服务之中
    sender:
      type: RABBIT  #提交的类型是web 服务
  sleuth:
    sampler:
      probability: 1.0 # 定义抽样比率,默认为0.1

3.6、依次启动测试

需要依次启动的服务:

springcloud-micro-eureka

springcloud-micro-product-hystrix

springcloud-micro-user-hystrix

springcloud-micro-zuul-gateway

springcloud-micro-consumer-feign-hystrix

然后访问:http://localhost/consumer/product/getProductAndUser?id=1

查看链路追踪以来分析如下所示:http://localhost:8601/zipkin/

 

http://localhost:15672/#/queues/%2F/zipkin,数据一节通过rabbitmq传输,并且数据已经到了数据库

 

 

具体配置参考:

https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

三、Springcloud admin

1、Maven依赖

Springcloud admin是基于spring-boot-starter-actuator实现的:

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

把actuator负责统计数据,admin是根据统计出来的数据来进行展示的,可以很好的监控整个微服务系统中的实例运行情况信息。

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
    <version>LATEST</version>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server-ui</artifactId>
    <version>LATEST</version>
</dependency>

2、启动类加注解

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

3、安全配置

application.properties配置信息如下:

spring.application.name=springcloud-micro-admin
server.port=8282
#是否注册到eureka
eureka.client.registerWithEureka=true
#是否从eureka中拉取注册信息
eureka.client.fetchRegistry=true
eureka.client.serviceUrl.defaultZone: http://admin:admin@eureka1:7001/eureka,http://admin:admin@eureka2:7002/eureka,http://admin:admin@eureka3:7003/eureka
# 安全配置
spring.security.user.name=admin
spring.security.user.password=admin
eureka.instance.metadata-map.user.name=${spring.security.user.name}
eureka.instance.metadata-map.user.password=${spring.security.user.password}

展示效果如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值