微服务调用链追踪中心搭建
概述
一个完整的微服务系统包含多个微服务单元,各个微服务子系统存在互相调用的情况,形成一个 调用链。一个客户端请求从发出到被响应 经历了哪些组件、哪些微服务、请求总时长、每个组件所花时长 等信息我们有必要了解和收集,以帮助我们定位性能瓶颈、进行性能调优,因此监控整个微服务架构的调用链十分有必要,本文将阐述如何使用 Zipkin 搭建微服务调用链追踪中心。
Zipkin初摸
正如 Ziplin官网 所描述,Zipkin是一款分布式的追踪系统,其可以帮助我们收集微服务架构中用于解决延时问题的时序数据,更直白地讲就是可以帮我们追踪调用的轨迹。
Zipkin的设计架构如下图所示:
要理解这张图,需要了解一下Zipkin的几个核心概念:
- Reporter
在某个应用中安插的用于发送数据给Zipkin的组件称为Report,目的就是用于追踪数据收集
- Span
微服务中调用一个组件时,从发出请求开始到被响应的过程会持续一段时间,将这段跨度称为Span
- Trace
从Client发出请求到完成请求处理,中间会经历一个调用链,将这一个整个过程称为一个追踪(Trace)。一个Trace可能包含多个Span,反之每个Span都有一个上级的Trace。
- Transport
一种数据传输的方式,比如最简单的HTTP方式,当然在高并发时可以换成Kafka等消息队列
看了一下基本概念后,再结合上面的架构图,可以试着理解一下,只有装配有Report组件的Client才能通过Transport来向Zipkin发送追踪数据。追踪数据由Collector收集器进行手机然后持久化到Storage之中。最后需要数据的一方,可以通过UI界面调用API接口,从而最终取到Storage中的数据。可见整体流程不复杂。
Zipkin官网给出了各种常见语言支持的OpenZipkin libraries:
本文接下来将 构造微服务追踪的实验场景 并使用 Brave 来辅助完成微服务调用链追踪中心搭建!
部署Zipkin服务
利用Docker来部署Zipkin服务再简单不过了:
docker run -d -p 9411:9411 \
--name zipkin \
docker.io/openzipkin/zipkin
完成之后浏览器打开:localhost:9411
可以看到Zipkin的可视化界面:
模拟微服务调用链
我们来构造一个如下图所示的调用链:
图中包含 一个客户端 + 三个微服务:
- Client:使用/servicea接口消费ServiceA提供的服务
- ServiceA:使用/serviceb接口消费ServiceB提供的服务,端口8881
- ServiceB:使用/servicec接口消费ServiceC提供的服务,端口8882
- ServiceC:提供终极服务,端口8883
为了模拟明显的延时效果,准备在每个接口的响应中用代码加入3s的延时。
简单起见,我们用SpringBt来实现三个微服务。
ServiceA的控制器代码如下:
@RestController
public class ServiceAContorller {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/servicea”)public String servicea() {try {Thread.sleep( 3000 );} catch (InterruptedException e) {e.printStackTrace();}return restTemplate.getForObject("http://localhost:8882/serviceb", String.class);}
}
ServiceB的代码如下:
@RestController
public class ServiceBContorller {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/serviceb”)public String serviceb() {try {Thread.sleep( 3000 );} catch (InterruptedException e) {e.printStackTrace();}return restTemplate.getForObject("http://localhost:8883/servicec", String.class);}
}
ServiceC的代码如下:
@RestController
public class ServiceCContorller {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/servicec”)public String servicec() {try {Thread.sleep( 3000 );} catch (InterruptedException e) {e.printStackTrace();}return "Now, we reach the terminal call: servicec !”;}
}
我们将三个微服务都启动起来,然后浏览器中输入localhost:8881/servicea
来发出请求,过了9s之后,将取到ServiceC中提供的微服务接口所返回的内容,如下图所示:
很明显,调用链可以正常work了!
那么接下来我们就要引入Zipkin来追踪这个调用链的信息!
编写与Zipkin通信的工具组件
从Zipkin官网我们可以知道,借助OpenZipkin库Brave,我们可以开发一个封装Brave的公共组件,让其能十分方便地嵌入到ServiceA,ServiceB,ServiceC服务之中,完成与Zipkin的通信。
为此我们需要建立一个新的基于Maven的Java项目:ZipkinTool
- pom.xml中加入如下依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hansonwang99</groupId><artifactId>ZipkinTool</artifactId><version>1.0-SNAPSHOT</version><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>6</source><target>6</target></configuration></plugin></plugins></build><packaging>jar</packaging><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot</artifactId><version>2.0.1.RELEASE</version><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.3.7.RELEASE</version><scope>provided</scope></dependency><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-spring-web-servlet-interceptor</artifactId><version>4.0.6</version></dependency><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-spring-resttemplate-interceptors</artifactId><version>4.0.6</version></dependency><dependency><groupId>io.zipkin.reporter</groupId><artifactId>zipkin-sender-okhttp3</artifactId><version>0.6.12</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope></dependency></dependencies></project>
- 编写ZipkinProperties类
其包含endpoint和service两个属性,我们最后是需要将该两个参数提供给ServiceA、ServiceB、ServiceC微服务作为其application.properties中的Zipkin配置
@Data
@Component
@ConfigurationProperties("zipkin")
public class ZipkinProperties {private String endpoint;private String service;
}
用了lombok之后,这个类异常简单!
【注意:关于lombok的用法,可以看这里】
- 编写ZipkinConfiguration类
这个类很重要,在里面我们将Brave的BraveClientHttpRequestInterceptor拦截器注册到RestTemplate的拦截器调用链中来收集请求数据到Zipkin中;同时还将Brave的ServletHandlerInterceptor拦截器注册到调用链中来收集响应数据到Zipkin中
上代码吧:
@Configuration
@Import({RestTemplate.class, BraveClientHttpRequestInterceptor.class, ServletHandlerInterceptor.class})
public class ZipkinConfiguration extends WebMvcConfigurerAdapter {@Autowiredprivate ZipkinProperties zipkinProperties;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate BraveClientHttpRequestInterceptor clientInterceptor;@Autowiredprivate ServletHandlerInterceptor serverInterceptor;@Beanpublic Sender sender() {return OkHttpSender.create( zipkinProperties.getEndpoint() );}@Beanpublic Reporter<Span> reporter() {return AsyncReporter.builder(sender()).build();}@Beanpublic Brave brave() {return new Brave.Builder(zipkinProperties.getService()).reporter(reporter()).build();}@Beanpublic SpanNameProvider spanNameProvider() {return new SpanNameProvider() {@Overridepublic String spanName(HttpRequest httpRequest) {return String.format("%s %s",httpRequest.getHttpMethod(),httpRequest.getUri().getPath());}};}@PostConstructpublic void init() {List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();interceptors.add(clientInterceptor);restTemplate.setInterceptors(interceptors);}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(serverInterceptor);}
}
ZipkinTool完成以后,我们需要在ServiceA、ServiceB、ServiceC三个SpringBt项目的application.properties中加入Zipkin的配置:
以ServiceA为例:
server.port=8881
zipkin.endpoint=http://你Zipkin服务所在机器的IP:9411/api/v1/spans
zipkin.service=servicea
我们最后依次启动ServiceA、ServiceB、和ServiceC三个微服务,并开始实验来收集链路追踪数据 !
实际实验
1. 依赖分析
浏览器打开Zipkin的UI界面,可以查看 依赖分析:
图中十分清晰地展示了ServiceA、ServiceB和ServiceC三个服务之间的调用关系!
注意,该图可缩放,并且每一个元素均可以点击,例如点击 ServiceB这个微服务,可以看到其调用链的上下游!
2. 查找调用链
接下来我们看一下调用链相关,点击 服务名,可以看到Zipkin监控到个所有服务:
同时可以查看Span,如以ServiceA为例,其所有REST接口都再下拉列表中:
以ServiceA为例,点击 Find Traces,可以看到其所有追踪信息:
点击某个具体Trace,还能看到详细的每个Span的信息,如下图中,可以看到 A → B → C 调用过程中每个REST接口的详细时间戳:
点击某一个REST接口进去还能看到更详细的信息,如查看/servicec这个REST接口,可以看到从发送请求到收到响应信息的所有详细步骤:
后记
作者更多的原创文章:在云栖社区
作者一些其他容器化应用方面的文章:
- Docker容器可视化监控中心搭建
- 利用K8S技术栈打造个人私有云连载文章
- 利用ELK搭建Docker容器化应用日志中心
微服务调用链追踪中心搭建相关推荐
- 微服务调用链追踪中心搭建 1
概述 一个完整的微服务系统包含多个微服务单元,各个微服务子系统存在互相调用的情况,形成一个 调用链.一个客户端请求从发出到被响应 经历了哪些组件.哪些微服务.请求总时长.每个组件所花时长 等信息我们有 ...
- 微服务调用链追踪框架Skywalking,看完你就懂了!
思维导图 文章已收录Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary 概述 **skywalking**又是一个优秀的国产开源框 ...
- 微服务调用链追踪方案
zipkin调用链追踪,主要可以知道,服务与服务之间的调用关系,调用的时间,数据信息 1. Trace:一个完整Trace 由一组Span组成,这一组Span必须具有相同的TraceID:Span具有 ...
- 微服务调用链日志追踪分析
一.技术原理 1.1 背景 微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元.由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位.主要体现在,一个 ...
- 微服务调用链监控开源工具CAT
1 监控在微服务架构的地位 2 为何需要调用链监控? 在初期的单体应用,应用都打在一个包中,无分布式概念,监控也只需对一些埋点监控. 但是微服务时代下,很多服务在各自的包,一旦出现问题,没有调用链监控 ...
- 微服务调用链的原理和选型
原文:https://juejin.im/post/5cde874e6fb9a07f091b713c 微服务是一个分布式非常复杂系统,如果没有一套调用链监控,如果服务之间依赖出现问题就很难进行调位 下 ...
- springboot2 springcloud Greenwich.SR3 构建微服务--1.eureka注册中心搭建
本一系列springcloud的文章主主要讲应用, 也会涉及到一些原理的讲解. 写了几句自己这段时间看书,总结的微服务的东西送给你们 : 道为源,源分多支为术,如龙生九子,九子各不同,然皆为龙也. 凡 ...
- spring cloud+dotnet core搭建微服务架构:配置中心续(五)
前言 上一章最后讲了,更新配置以后需要重启客户端才能生效,这在实际的场景中是不可取的.由于目前Steeltoe配置的重载只能由客户端发起,没有实现处理程序侦听服务器更改事件,所以还没办法实现彻底实现这 ...
- springboot 之 微服务调用 之 链路追踪
说明:本文来自 本篇主要内容 一.为什么要用链路追踪? 1.1 因:拆分服务单元 微服务架构其实是一个分布式的架构,按照业务划分成了多个服务单元. 由于服务单元的数量是很多的,有可能几千个,而且业务也 ...
- 调用链追踪系统在伴鱼:实践篇
我们介绍了伴鱼在调用链追踪领域的调研工作,本篇继续介绍伴鱼的调用链追踪实践.在正式介绍前,简单交代一下背景:2015 年,在伴鱼服务端起步之时,技术团队就做出统一使用 Go 语言的决定.这个决定的影响 ...
最新文章
- 关于TensorFlow报错ModuleNotFoundError: No module named ‘imutils‘
- Mysql 新建用户并分配所有权限
- 探讨浏览器CSS选择器的权重!!!
- 华三实现vlan通过
- 烟草局计算机笔试,2020年广西南宁烟草局什么时候笔试?
- 工作223:状态管理里面取值
- 静态成员函数与静态数据的使用
- 怎么用php myadmin连接远程MYSQL数据库
- 用matlab实现人脸识别,Matlab实现简单的人脸识别程序
- Tenserflow 情感分类
- office2016鼠标右键没有新建word等
- ramda 函数 list
- win7虚拟机详细搭建过程
- 学习 MySQL 需要知道的 28 个小技巧
- 代谢组学助力研究“线粒体闪烁”,揭示细胞“返老还童”的新奥秘
- 重磅直播丨迈向移动数字金融 —— 神州信息并购云核网络线上发布会
- 帝国CMS 批量修改信息标题方法
- Windows实用工具推荐
- Nautre综述:鸟枪法宏基因组-从取样到数据分析(1)2万字带你系统入门宏基因组实验和分析...
- element的table组件,表头合并(合并表头单元格)
热门文章
- error: crosses initialization of ‘std::string xx变量‘
- Jruby On Rails 的安装及部署实践
- 中信证券:降准并非货币宽松 缺口或达9000亿
- 计算机主机显卡安装,电脑显卡驱动怎么安装
- php html block,html blockquote怎么用?blockquote标签的用法介绍
- 微信小程序|基于小程序实现打卡功能
- 带壳截图 android,给手机截屏带个「套」:带壳截图应用合辑
- bi 工具 市场排行榜_bi工具市场排行榜,国内BI软件排名
- UVa12235 Help Bubu
- Java常用英语汇总(面试必备)