十八.SpringCloud极简入门-Zipkin整合RabbitMQ使用ElasticSearch存储的高性能链路追踪方案

前言

之前讲过一个版本的Zipkin链路追踪,《Sleuth整合ZipKin链路追踪》,讲了Zipkin的工作流程,以及简单集成Zipkin,这篇文章将会对之前的方案进行升级,使用RabbitMQ异步收集数据,使用ElasticSearch进行数据存储。另外本文会使用Docker来搭建相关组件。 注意:请一定先看上一篇 Sleuth整合ZipKin链路追踪。学习该文章需要有一定的知识储备:Docker,ElasticSearch,RabbitMQ,SpringCloud等。

方案设计

Zipkin可以分为ZipKinServer端和Zipkin client 端,client端也就是咱们参与链路追踪的微服务。微服务需要整合Zipkin实时向Zipkin服务端发送链路数据,支持的方式有WEB(http),Rabbit,Kafka三种。ZipKinServer通过collector收集器收集链路数据,然后通过store把数据存储到内存或数据库或ElasticSearch。最后Zipkin通过UI把链路数据展示出来,大致原理图如下:

在这里插入图片描述
今天我们采用的方式是:

  1. 客户端使用rabbitmq的方式进行数据的异步推送,这样的方式性能更好,容错性更高,即使zIpkinserver挂了客户端也可以正常工作
  2. ZipkinServer的存储方式采用ElasticSearch,因为这种链路数据是非常庞大的,内存和数据库都不太适合存储。

组件环境安装

Docker安装

在准备好的linux机器上安装好Docker

# yum源指定
[root@localhost ~]# sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装docker
[root@localhost ~]# sudo yum -y install docker-ce
#启动dokcer
[root@localhost ~]# sudo systemctl start docker

使用阿里云镜像加速

[root@localhost ~]# vi /etc/docker/daemon.json
#加入如下内容
{
  "registry-mirrors": ["https://5pfmrxk8.mirror.aliyuncs.com"]
}

重启Docker

[root@localhost ~]# systemctl restart docker

ElasticSerach安装

ElasticSerach是用来存储链数据的全文搜索组件,专门应对大数据量的全文检索和存储。

#下载镜像
[root@localhost ~]# docker pull elasticsearch:6.8.6
# 启动容器
[root@localhost ~]# docker run --name elasticsearch -d -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 elasticsearch:6.8.6

访问测试:我的linux机器的ip是:192.168.119.129:9200
在这里插入图片描述

Kibana安装

Kibana是针对ElasticSearch的查询和分析统计的可视化工具

# 下载镜像
[root@localhost ~]# docker pull kibana:6.8.6
# 启动容器,通过ELASTICSEARCH_HOSTS指定es的地址
[root@localhost ~]# docker run --name kibana -e "ELASTICSEARCH_HOSTS=http://192.168.119.129:9200" -p 5601:5601 -d kibana:6.8.6

访问测试:我的linux机器的ip是:192.168.119.129:5601
在这里插入图片描述

安装RabbitMQ

RabbitMQ是一个高性能的消息队列,微服务把链路数据发送到MQ,zipkinserver从MQ中收集数据往ElasticSearch总存储

#下载镜像
[root@localhost ~]# docker pull rabbitmq:latest
#启动容器
[root@localhost ~]# docker run -d -v /opt/rabbitmq/data:/var/lib/rabbitmq -p 5672:5672 -p 15672:15672 --name rabbitmq --restart=always --hostname myRabbit rabbitmq
#安装可视化插件
[root@localhost ~]# docker exec -it rabbitmq rabbitmq-plugins enable rabbitmq_management

访问测试:我的linux机器的ip是:192.168.119.129:15672 , 登录账号是:guest/guest
在这里插入图片描述

安装ZipkinServer

ZipkinServer负责收集微服务发送过来的链路数据

#下载镜像
[root@localhost ~]# docker pull openzipkin/zipkin:2.14.1
#启动容器,指定存储方式为elasticsearch,并指定ElasticSearch主机,以及RabbitMQ的地址
[root@localhost ~]# docker run -d ---env STORAGE_TYPE=elasticsearch --env ES_HOSTS=192.168.119.129:9200 --env RABBIT_ADDRESSES=192.168.119.129:5672 -p 9411:9411 openzipkin/zipkin:2.14.1

这里指定存储方式为elasticsearch,并指定ElasticSearch主机,以及RabbitMQ的地址,它需要从RabbitMQ中拿到链路数据存储到ElasticSearch中。访问测试:我的linux机器的ip是:192.168.119.129:9411 ,
在这里插入图片描述

安装Zipkin-dependencies

当zipkin使用elasticsearch进行数据存储后,会丢失依赖关系,需要额外安装Zipkin-dependencies

#下载镜像
[root@localhost ~]# docker pull openzipkin/zipkin-dependencies:2.6.2
# 启动容器 ,存储方式为STORAGE_TYPE=elasticsearch ,并指定ES的主机
[root@localhost ~]# docker run  --name zipkin-dependencies --env STORAGE_TYPE=elasticsearch --env ES_HOSTS=192.168.119.129:9200 --env ES_INDEX=zipkin --rm=true -e JAVA_OPTS="-Xmx1024m -Xms1024m" openzipkin/zipkin-dependencies:2.6.2

出现这样的效果就可以了
在这里插入图片描述
到这里所有的组件准备完毕,使用 docker ps 查看容器
在这里插入图片描述

微服务准备

这里我基于Eureka做服务发现,搭建了Producer和Consumer两个微服务,服务之间使用OpfenFeign进行通信。项目结构如

springcloud-elk
|--- eureka-server #注册中心
|--- service-consumer #消费者
|--- service-producer #提供者

搭建父工程

 <!--SpringBoot-->
    <parent>
        <groupId> org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>
    <dependencyManagement>
        <dependencies>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

Eureka搭建

第一步导入POM

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

第二步:编写启动内

@SpringBootApplication
@EnableEurekaServer
public class EurekaStarter {

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

第三步:yml配置

server:
  port: 1000
eureka:
  instance:
    hostname: localhost #主机
  client: #客户端配置
    registerWithEureka: false  #EurekaServer自己不要注册到EurekaServer自己 ,只有EurekaClient才注册
    fetchRegistry: false  #EurekaServer不要拉取服务的通信地址列表 ,只有EurekaClient才拉取地址列表
    serviceUrl:  #注册中心的注册地址
      defaultZone: http://localhost:1000/eureka/  #http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    enable-self-preservation: false #关闭自我保护警告

服务提供者

第一步导入POM , 需要导入:spring-cloud-starter-zipkin整合zipkin ; 导入spring-rabbit整合RabbitMQ

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit</artifactId>
        </dependency>
        <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>
    </dependencies>

第二步:启动类

@SpringBootApplication
public class ProducerStarter {

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

第三步:yml配置

#注册到EurekaServer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/ #注册地址
  instance:
    prefer-ip-address: true #使用ip地址进行注册
    instance-id: service-producer:3000	#实例ID
spring:
  application:
    name: service-producer
  rabbitmq: #rabbitMQ配置
    host: 192.168.119.129 #使用的是docker安装的RabbitMQ
    port: 5672
    username: guest
    password: guest
  zipkin:
    base-url: http://192.168.119.129:9411 #Zipkin服务端地址 ,可以使用ip地址也可以使用服务发现方式。
    discovery-client-enabled: false #如果使用服务发现的方式查找zipkin则打开为true
    sender:
      type: rabbit #使用MQ的方式发送链路数据,还可以是web,kafka
  sleuth:
    sampler:
      probability: 1.0 #链路数据收集率,越大收集的越全
server:
  port: 3000

第四步:编写一个controller,提供给消费者调用

@RestController
public class ProducerController {

    @RequestMapping("/hi")
    public String hi(){
        return "hello";
    }
}

服务消费者

第一步导入依赖:比提供者多一个OpenFeign的依赖,因为要做服务调用

 <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit</artifactId>
        </dependency>
        <!--sleuth-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <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-openfeign</artifactId>
        </dependency>
    </dependencies>

第二步:启动类 , 这里开启Feign

@SpringBootApplication
@EnableFeignClients
public class ConsumerStarter {

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

第三步:编写feign客户端接口 , 该接口是用来调用提供者服务的

@FeignClient("service-producer")
public interface HIFeignClient {

    @RequestMapping("/hi")
    String hi();
}

第四步:编写controller,使用feign访问提供者

@RestController
public class ConsumerController {
    @Autowired
    private HIFeignClient feignClient;

    @RequestMapping("/hi")
    public String hi(){
        return feignClient.hi();
    }
}

第五步:yml配置

#注册到EurekaServer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/
  instance:
    prefer-ip-address: true #使用ip地址进行注册
    instance-id: service-consumer:4000	#实例ID
spring:
  application:
    name: service-consumer
  rabbitmq:
    host: 192.168.119.129
    port: 5672
    username: guest
    password: guest
  zipkin:
    base-url: http://192.168.119.129:9411 #Zipkin服务端地址 ,可以使用ip地址也可以使用服务发现方式。
    discovery-client-enabled: false #如果使用服务发现的方式查找zipkin则打开为true
    sender:
      type: rabbit #使用MQ的方式发送链路数据,还可以是web,kafka
  sleuth:
    sampler:
      probability: 1.0
server:
  port: 4000

到了,到这里所有的 微服务也准备完毕。

测试

依次启动:Eureka ,提供者服务(3000),消费者服务(4000) , 使用浏览器访问 http://localhost:4000/hi ,可以多访问几次,数据会收集多一点,
在这里插入图片描述
控制台效果
在这里插入图片描述

然后微服务会把链路调用数据发送到RabbitMQ中,而ZipkinServer会从RabbitMQ中数据并存储到ElasticSearch中。下面是ES中的效果:http://192.168.119.129:5601
在这里插入图片描述
在Discover中看到收集的数据
在这里插入图片描述
然后Zipkin会通过UI展示链路信息 http://192.168.119.129:9411/zipkin
在这里插入图片描述
查看依赖
在这里插入图片描述

文章结束希望对你有所帮助,喜欢的话请给个好评

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨家巨子@俏如来

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值