前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringCloud微服务实战系列(十五)分布式链路跟踪Sleuth与Zipkin实现

SpringCloud微服务实战系列(十五)分布式链路跟踪Sleuth与Zipkin实现

作者头像
品茗IT
发布2020-05-28 16:12:53
4110
发布2020-05-28 16:12:53
举报
文章被收录于专栏:品茗IT品茗IT

SpringCloud微服务实战系列(十五)分布式链路跟踪Sleuth与Zipkin实现

一、概述

分布式链路追踪,是一种用于分析和监控应用程序的方法,尤其是那些使用微服务架构的那些应用。分布式链路跟踪有助于查找故障发生位置和导致性能低下的原因。

SpringCloud全家桶中,整合了Sleuth和Zipkin做分布式链路跟踪和数据的收集展示。

Sleuth:为服务之间调用提供链路追踪。通过 Sleuth 可以很清楚的了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。

Zipkin:可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的 REST API 接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。

Spring Cloud Zipkin 整合了Sleuth和Zipkin的功能,提供了一套完整的分布式链路解决方案。

代码可以在SpringBoot组件化构建https://www.pomit.cn/java/spring/springcloud.html中的Zipkin组件中查看,并下载。

**如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以<a

href="https://jq.qq.com/?_wv=1027&k=52sgH1J"

target="_blank">

加入我们的java学习圈,点击即可加入

</a>

,共同学习,节约学习时间,减少很多在学习中遇到的难题。**

二、准备工作

使用zipkin,要明白zipkin的客户端和服务端的概念:

  1. Sleuth是做链路跟踪的。Spring Cloud Sleuth就可以完成链路跟踪;
  2. Zipkin收集数据,如果Spring Cloud应用使用了Zipkin,它就相当于客户端;
  3. Zipkin服务端是单独部署的,单纯负责收集数据和展示等。
2.1 安装zipkin服务端

首先要安装zipkin的服务端,就是一个jar包,启动之后收集客户端数据并做展示。

Zipkin开源地址https://github.com/openzipkin/zipkin

当你首次接触zipkin时,一定会各种博客上的文章给绕晕的,乱七八糟,各种写法,这是因为Spring Cloud版本不同,提供的功能逐渐丰富,而且zipkin也提供了快读部署的方案。

我当前使用的Spring Cloud zipkin版本为2.1.0.RELEASE。zipkin在github的提交最新记录为Commits on Oct 25, 2019。

下面开始讲安装:

很多博客都是写的自己打包编译zipkin,然后用@EnableZipkinServer注解Spring boot应用来启动zipkin服务端。这种方式已经被官网遗弃,@EnableZipkinServer注解也被标记为@Deprecated。

所以,它给了一种更简单的部署方案:

代码语言:javascript
复制
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar

如果用 Docker 的话,直接

代码语言:javascript
复制
docker run -d -p 9411:9411 openzipkin/zipkin

然后通过9411端口访问即可,比如我的是:http://10.247.62.23:9411

2.2 SpringCloud应用引入依赖

需要引入spring-boot-starter-web和spring-cloud-starter-zipkin;

因为使用了consul做服务注册发现,需要引入spring-cloud-starter-consul-discovery和spring-cloud-starter-netflix-ribbon。

依赖如下:

代码语言:javascript
复制
<?xml version="1.0"?>
<project
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>cn.pomit</groupId>
		<artifactId>springcloudwork</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>SleuthZipkin</artifactId>
	<name>SleuthZipkin</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<maven-jar-plugin.version>2.6</maven-jar-plugin.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zipkin</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</dependency>
	</dependencies>
</project>

父模块pom文件可以在https://www.pomit.cn/spring/SpringCloudWork/pom.xml获取。

3.2 配置文件

这里使用yaml文件写配置,配置文件application.yml:

application.yml:

代码语言:javascript
复制
server:
   port: 8111
spring:
   application:
      name: sleuthZipkin
   sleuth:
      web:
         client:
            enabled: true
      sampler:
         probability: 1.0 # 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1
   zipkin:
      base-url: http://10.247.62.23:9411/ # 指定了 Zipkin 服务器的地址
   cloud:
      consul:
         host: 10.247.62.23
         port: 8500
         discovery:
            prefer-ip-address: true
            healthCheckPath: /consul/health

这里,应用名称是sleuthZipkin,在8111端口监听。

  • spring.cloud.consul开头的配置时consul服务注册发现的配置。前面章节已经有说明。
  • spring.sleuth.*是sleuth的配置,开启webClient,并设置采样比例为1.0,即全部采样。
  • spring.zipkin.base-url:指定了 Zipkin 服务器的地址,就是上面我部署的那个zipkin服务端。

配置完成后,之后就是普通的调用和服务了。下面的第四章节将代码展示出来,第五章节介绍下链路跟踪zipkin的展示和用法。

四、启动服务注册发现

我这里启动了三个服务做测试,分别为consulServer、consulClient和sleuthZipkin。

在这里插入图片描述

链路是从sleuthZipkin -> consulClient -> consulServer.

4.1 启动类

使用@EnableDiscoveryClient注解启动类, @EnableDiscoveryClient是将项目作为客户端注册到注册中心的注解,开启服务发现功能。

SleuthZipkinApplication :

代码语言:javascript
复制
package cn.pomit.springbootwork.zipkin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class SleuthZipkinApplication {
	public static void main(String[] args) {
		SpringApplication.run(SleuthZipkinApplication.class, args);
	}
	
	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

这里的RestTemplate使用@LoadBalanced注解,我们跟踪RestTemplate的时候可以看到,RestTemplate多了个LoadBalancerInterceptor。

4.2 健康检查

不管是服务注册还是服务调用,都需要写健康检查接口。前面写了我们健康检查地址是/consul/health,这里要开放个接口,让consul来检查身体。

代码语言:javascript
复制
package cn.pomit.springbootwork.zipkin.web;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/consul")
public class HealthWeb {

	@RequestMapping(value = "health", method = { RequestMethod.GET })
	public String health() {
		return "check health";
	}
	
}
4.3 Ribbon做服务调用

如果我们使用Ribbon做服务调用,需要使用RestTemplate,这个RestTemplate是标识为负载均衡的。我们来调用上一篇提供的ip服务:

IpInfoService :

代码语言:javascript
复制
package cn.pomit.springbootwork.zipkin.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import cn.pomit.springbootwork.zipkin.model.ResultModel;

@Service
public class IpInfoService {
	/**
	 * 第一个consulServer是配置文件种的spring.application.name,第二个是controller中配置的路径
	 */
	public static String remoteIpServiceUrl = "http://consulClient/consulClient/ip";
	@Autowired
	private RestTemplate restTemplate;

	public ResultModel getIpInfo() {
		ResponseEntity<ResultModel> ipModel = restTemplate.getForEntity(remoteIpServiceUrl, ResultModel.class);
		return ipModel.getBody();
	}
}

这里,第一个consulClient是服务提供方配置文件种的spring.application.name,第二个consulClient是服务提供方的controller中配置的路径。我们使用统一的实体ResultModel进行数据接收转换。

4.4 测试Web

SleuthZipkinRest :

代码语言:javascript
复制
package cn.pomit.springbootwork.zipkin.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import cn.pomit.springbootwork.zipkin.model.ResultModel;
import cn.pomit.springbootwork.zipkin.service.IpInfoService;

@RestController
@RequestMapping("/sleuthTest")
public class SleuthZipkinRest {
	@Autowired
	IpInfoService ipInfoService;
	
	@RequestMapping(value = "/ip", method = { RequestMethod.GET })
	public ResultModel ip() {
		return ipInfoService.getIpInfo();
	}
}

五、链路跟踪展示

我这里对三个服务调用链路sleuthZipkin -> consulClient -> consulServer的不同形式做测试和分析,下面是分析的几种情况:

在这里插入图片描述

5.1 单一调用方使用zipkin

只有sleuthZipkin开启了sleuth和zipkin。consulClient 和consulServer都未开启zipkin。

5.1.1 正常情况

这种情况下,只显示sleuthZipkin调用consulClient的情况,展示两个应用的调用情况:

在这里插入图片描述

5.1.2 异常情况

如果将consulServer停掉,会显示sleuthZipkin调用consulClient的异常情况,只能到consulClient,展示两个应用的调用情况:

在这里插入图片描述

5.2 中间商也使用zipkin

sleuthZipkin和consulClient 都开启了sleuth和zipkin。consulServer为最后调用级别,不开启zipkin了。

5.2.1 正常情况

这种情况下,显示sleuthZipkin -> consulClient -> consulServer的调用情况:

在这里插入图片描述

5.2.2 异常情况

如果将consulServer停掉,会显示consulClient调用consulServer的异常情况,会显示完整的调用链:

在这里插入图片描述

六、过程中用到的实体

过程中用到了ResultModel实体,作为统一的实体来用。

ResultModel:

代码语言:javascript
复制
package cn.pomit.springbootwork.zipkin.model;

/**
 * @author cff
 */
public class ResultModel {

	private String errorCode;
	private String message;
	private Object data;

	public ResultModel() {

	}

	public ResultModel(String errorCode, String message) {
		this.errorCode = errorCode;
		this.message = message;
	}

	public ResultModel(String errorCode, String message, Object data) {
		this.errorCode = errorCode;
		this.message = message;
		this.data = data;
	}

	public String geterrorCode() {
		return errorCode;
	}

	public void seterrorCode(String errorCode) {
		this.errorCode = errorCode;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

	public static ResultModel ok(String testValue) {
		ResultModel rm = new ResultModel();
		rm.setData(testValue);
		return rm;
	}

}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-10-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringCloud微服务实战系列(十五)分布式链路跟踪Sleuth与Zipkin实现
  • 一、概述
  • 二、准备工作
    • 2.1 安装zipkin服务端
      • 2.2 SpringCloud应用引入依赖
        • 3.2 配置文件
        • 四、启动服务注册发现
          • 4.1 启动类
            • 4.2 健康检查
              • 4.3 Ribbon做服务调用
                • 4.4 测试Web
                • 五、链路跟踪展示
                  • 5.1 单一调用方使用zipkin
                    • 5.1.1 正常情况
                    • 5.1.2 异常情况
                  • 5.2 中间商也使用zipkin
                    • 5.2.1 正常情况
                    • 5.2.2 异常情况
                • 六、过程中用到的实体
                相关产品与服务
                负载均衡
                负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档