澳门金莎娱乐网站微服务调用链追踪中央搭建,

时间:2019-10-08 07:41来源:编程技术
Profile 封面图片 在前面:微服务调用链追踪中心搭建一文中我们利用Zipkin搭建了一个微服务调用链的追踪中心,并且模拟了微服务调用的实验场景。利用Zipkin的库Brave,我们可以收集一

澳门金莎娱乐网站 1Profile

澳门金莎娱乐网站 2封面图片

在前面:微服务调用链追踪中心搭建 一文中我们利用Zipkin搭建了一个微服务调用链的追踪中心,并且模拟了微服务调用的实验场景。利用Zipkin的库Brave,我们可以收集一个客户端请求从发出到被响应 经历了哪些组件哪些微服务请求总时长每个组件所花时长 等信息。

一个完整的微服务系统包含多个微服务单元,各个微服务子系统存在互相调用的情况,形成一个 调用链。一个客户端请求从发出到被响应 经历了哪些组件哪些微服务请求总时长每个组件所花时长 等信息我们有必要了解和收集,以帮助我们定位性能瓶颈、进行性能调优,因此监控整个微服务架构的调用链十分有必要,本文将阐述如何使用 Zipkin 搭建微服务调用链追踪中心。

本文将讲述如何利用Zipkin对Mysql数据库的调用进行追踪,这里同样借助OpenZipkin库Brave来完成。

注: 本文原载于 My Personal Blog:CodeSheep · 程序羊

注: 本文原载于 My Personal Blog:CodeSheep · 程序羊

正如 Ziplin官网 所描述,Zipkin是一款分布式的追踪系统,其可以帮助我们收集微服务架构中用于解决延时问题的时序数据,更直白地讲就是可以帮我们追踪调用的轨迹。

ZipkinTool是在《微服务调用链追踪中心搭建》一文中编写的与Zipkin通信的工具组件,利用其追踪微服务调用链的,现在我们想追踪Mysql数据库调用链的话,可以扩展一下其功能。

Zipkin的设计架构如下图所示:

  • pom.xml添加依赖:

澳门金莎娱乐网站 3Zipkin设计架构

要理解这张图,需要了解一下Zipkin的几个核心概念:

<dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-mysql</artifactId> <version>4.0.6</version></dependency>
  • Reporter
  • 在ZipkinConfiguration类中添加MySQLStatementInterceptorManagementBean

在某个应用中安插的用于发送数据给Zipkin的组件称为Report,目的就是用于追踪数据收集

  • Span
 @Bean public MySQLStatementInterceptorManagementBean mySQLStatementInterceptorManagementBean() { return new MySQLStatementInterceptorManagementBean.clientTracer; }

微服务中调用一个组件时,从发出请求开始到被响应的过程会持续一段时间,将这段跨度称为Span

依然继承前文:《微服务调用链追踪中心搭建》,我们改造一下文中的ServiceC这个微服务,在其中添加与Mysql数据库的交互。

  • Trace
  • pom.xml中添加JDBC和Mysql依赖

从Client发出请求到完成请求处理,中间会经历一个调用链,将这一个整个过程称为一个追踪。一个Trace可能包含多个Span,反之每个Span都有一个上级的Trace。

  • Transport
 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>

一种数据传输的方式,比如最简单的HTTP方式,当然在高并发时可以换成Kafka等消息队列

  • application.properties中添加Mysql连接的配置

看了一下基本概念后,再结合上面的架构图,可以试着理解一下,只有装配有Report组件的Client才能通过Transport来向Zipkin发送追踪数据。追踪数据由Collector收集器进行手机然后持久化到Storage之中。最后需要数据的一方,可以通过UI界面调用API接口,从而最终取到Storage中的数据。可见整体流程不复杂。

Zipkin官网给出了各种常见语言支持的OpenZipkin libraries:

spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://你的Mysql服务所在IP:3307/test?useSSL=false &statementInterceptors=com.github.kristofa.brave.mysql.MySQLStatementInterceptor &zipkinServiceName=mysqlServicespring.datasource.username=rootspring.datasource.password=XXXXXX

澳门金莎娱乐网站 4OpenZipkin libraries

  • Controller中添加JdbcTemplate访问数据库的代码

本文接下来将 构造微服务追踪的实验场景 并使用 Brave 来辅助完成微服务调用链追踪中心搭建!

利用Docker来部署Zipkin服务再简单不过了:

 @GetMapping("/mysqltest”) public String mysqlTest() { String name = jdbcTemplate.queryForObject( "SELECT name FROM user WHERE id = 1", String.class ); return "Welcome " + name; }
docker run -d -p 9411:9411 --name zipkin docker.io/openzipkin/zipkin

1. 启动Mysql容器

完成之后浏览器打开:localhost:9411可以看到Zipkin的可视化界面:

docker run -d -p 3307:3306 -v ~/mysql/data:/var/lib/mysql -v ~/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=XXXXXX --name mysql mysql

澳门金莎娱乐网站 5Zipkin可视化界面

2. 再启动一个Mysql容器,接入其中做一些设置

我们来构造一个如下图所示的调用链:

  • 首先进入mysql命令行

澳门金莎娱乐网站 6微服务调用链

图中包含 一个客户端 + 三个微服务

docker run -it --rm --link mysql:mysql mysql mysql -hmysql -u root -p
  • Client:使用/servicea接口消费ServiceA提供的服务

  • ServiceA:使用/serviceb接口消费ServiceB提供的服务,端口8881

  • ServiceB:使用/servicec接口消费ServiceC提供的服务,端口8882

  • ServiceC:提供终极服务,端口8883

澳门金莎娱乐网站 7进入Mysql的命令行

为了模拟明显的延时效果,准备在每个接口的响应中用代码加入3s的延时。

  • 接下来创建数据库zipkin: 用于存放Zipkin所收集的数据

简单起见,我们用SpringBt来实现三个微服务。

ServiceA的控制器代码如下:

CREATE DATABASE `zipkin`CREATE TABLE IF NOT EXISTS zipkin_spans ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit’, `trace_id` BIGINT NOT NULL, `id` BIGINT NOT NULL, `name` VARCHAR NOT NULL, `parent_id` BIGINT, `debug` BIT, `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL’, `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query’) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate’;ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations’;ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds’;ALTER TABLE zipkin_spans ADD INDEX COMMENT 'for getTraces and getSpanNames’;ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range’;CREATE TABLE IF NOT EXISTS zipkin_annotations ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit’, `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id’, `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id’, `a_key` VARCHAR NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1’, `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB’, `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation’, `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp’, `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null’, `endpoint_ipv6` BINARY COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address’, `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null’, `endpoint_service_name` VARCHAR COMMENT 'Null when Binary/Annotation.endpoint is null’) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate’;ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans’;ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds’;ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames’;ALTER TABLE zipkin_annotations ADD INDEX COMMENT 'for getTraces’;ALTER TABLE zipkin_annotations ADD INDEX COMMENT 'for getTraces’;ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job’;CREATE TABLE IF NOT EXISTS zipkin_dependencies ( `day` DATE NOT NULL, `parent` VARCHAR NOT NULL, `child` VARCHAR NOT NULL, `call_count` BIGINT, `error_count` BIGINT) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);
@RestControllerpublic class ServiceAContorller { @Autowired private RestTemplate restTemplate; @GetMapping("/servicea”) public String servicea() { try { Thread.sleep; } catch (InterruptedException e) { e.printStackTrace(); } return restTemplate.getForObject("http://localhost:8882/serviceb", String.class); }}

这里创建了三个数据表。

ServiceB的代码如下:

该Sql文件可以从以下链接获得:

@RestControllerpublic class ServiceBContorller { @Autowired private RestTemplate restTemplate; @GetMapping("/serviceb”) public String serviceb() { try { Thread.sleep; } catch (InterruptedException e) { e.printStackTrace(); } return restTemplate.getForObject("http://localhost:8883/servicec", String.class); }}

Sql脚本执行完成后,可以看到zipkin相关的三个表已经建成:

ServiceC的代码如下:

澳门金莎娱乐网站 8Zipkin相关的三个表澳门金莎娱乐网站 9Zipkin相关的三个表

@RestControllerpublic class ServiceCContorller { @Autowired private RestTemplate restTemplate; @GetMapping("/servicec”) public String servicec() { try { Thread.sleep; } catch (InterruptedException e) { e.printStackTrace(); } return "Now, we reach the terminal call: servicec !”; }}
  • 创建数据库test:用作测试数据库

我们将三个微服务都启动起来,然后浏览器中输入localhost:8881/servicea来发出请求,过了9s之后,将取到ServiceC中提供的微服务接口所返回的内容,如下图所示:

澳门金莎娱乐网站 10微服务链式调用结果

CREATE DATABASE `test`CREATE TABLE `user` ( `id` int unsigned NOT NULL auto_increment, `name` varchar DEFAULT NULL , PRIMARY KEY  ENGINE=InnoDB DEFAULT CHARSET = utf8;insert into user values (1,”hansonwang99”)

很明显,调用链可以正常work了!

这里插入了一条数据用于实验。

那么接下来我们就要引入Zipkin来追踪这个调用链的信息!

澳门金莎娱乐网站 11创建test数据库并插入一条数据

从Zipkin官网我们可以知道,借助OpenZipkin库Brave,我们可以开发一个封装Brave的公共组件,让其能十分方便地嵌入到ServiceA,ServiceB,ServiceC服务之中,完成与Zipkin的通信。

docker run -d -p 9411:9411 --link mysql:mysql -e STORAGE_TYPE=mysql -e MYSQL_HOST=mysql -e MYSQL_TCP_PORT=3306 -e MYSQL_DB=zipkin -e MYSQL_USER=root -e MYSQL_PASS=XXXXXX  --name zipkin openzipkin/zipkin

为此我们需要建立一个新的基于Maven的Java项目:ZipkinTool

在浏览器中输入:localhost:8883/mysqltest,如果看到以下输出,就可以证明数据库调用操作已经成功了!

  • pom.xml中加入如下依赖:

澳门金莎娱乐网站 12数据库调用操作已经成功

  • 浏览器输入:
<?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>

打开Zipkin Web UI,点击服务名下拉列表能看见已经成功识别了Mysql数据库调用服务

  • 编写ZipkinProperties类

澳门金莎娱乐网站 13成功识别Mysql数据库调用服务

其包含endpoint和service两个属性,我们最后是需要将该两个参数提供给ServiceA、ServiceB、ServiceC微服务作为其application.properties中的Zipkin配置

  • 选中mysqlservice后,点击Find Traces
@Data@Component@ConfigurationPropertiespublic class ZipkinProperties { private String endpoint; private String service;}

可以看到 首次查询 Mysql的调用链追踪信息,有很多

用了lombok之后,这个类异常简单!

澳门金莎娱乐网站 14首次查询Mysql所产生的Traces信息

【注意:关于lombok的用法,可以看这里】

随便点开某一个查看:

  • 编写ZipkinConfiguration类

澳门金莎娱乐网站 15随机查看某一个具体的Trace信息

这个类很重要,在里面我们将Brave的BraveClientHttpRequestInterceptor拦截器注册到RestTemplate的拦截器调用链中来收集请求数据到Zipkin中;同时还将Brave的ServletHandlerInterceptor拦截器注册到调用链中来收集响应数据到Zipkin中

  • 接下来浏览器中再次输入:localhost:8883/mysqltest

上代码吧:

目的是再次触发Mysql的调用,然后再次Find Traces,可以看到追踪数据类似下图:包含两次Mysql的query动作:

@Configuration@Import({RestTemplate.class, BraveClientHttpRequestInterceptor.class, ServletHandlerInterceptor.class})public class ZipkinConfiguration extends WebMvcConfigurerAdapter { @Autowired private ZipkinProperties zipkinProperties; @Autowired private RestTemplate restTemplate; @Autowired private BraveClientHttpRequestInterceptor clientInterceptor; @Autowired private ServletHandlerInterceptor serverInterceptor; @Bean public Sender sender() { return OkHttpSender.create( zipkinProperties.getEndpoint; } @Bean public Reporter<Span> reporter() { return AsyncReporter.builder.build(); } @Bean public Brave brave() { return new Brave.Builder(zipkinProperties.getService.reporter(reporter.build(); } @Bean public SpanNameProvider spanNameProvider() { return new SpanNameProvider() { @Override public String spanName(HttpRequest httpRequest) { return String.format( "%s %s", httpRequest.getHttpMethod(), httpRequest.getUri().getPath; } }; } @PostConstruct public void init() { List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors(); interceptors.add(clientInterceptor); restTemplate.setInterceptors(interceptors); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(serverInterceptor); }}

澳门金莎娱乐网站 16两次Mysql的query动作

ZipkinTool完成以后,我们需要在ServiceA、ServiceB、ServiceC三个SpringBt项目的application.properties中加入Zipkin的配置:

点开第一个query查看,其实际上是在 尝试连接Mysql数据库

以ServiceA为例:

澳门金莎娱乐网站 17第一个query详情

server.port=8881zipkin.endpoint=http://你Zipkin服务所在机器的IP:9411/api/v1/spanszipkin.service=servicea

点开第二个query查看,发现这里才是 实际查询业务

我们最后依次启动ServiceA、ServiceB、和ServiceC三个微服务,并开始实验来收集链路追踪数据 !

澳门金莎娱乐网站 18第二个query详情

1. 依赖分析

浏览器打开Zipkin的UI界面,可以查看 依赖分析

澳门金莎娱乐网站 19点击依赖分析

图中十分清晰地展示了ServiceA、ServiceB和ServiceC三个服务之间的调用关系!注意,该图可缩放,并且每一个元素均可以点击,例如点击 ServiceB这个微服务,可以看到其调用链的上下游!

澳门金莎娱乐网站 20点击ServiceB微服务

从图形化界面上可以清楚地知道每个阶段的详细步骤与耗时,因此可以用来分析哪个SQL语句执行相对较慢。

2. 查找调用链

接下来我们看一下调用链相关,点击 服务名,可以看到Zipkin监控到个所有服务:

澳门金莎娱乐网站 21查找调用链

同时可以查看Span,如以ServiceA为例,其所有REST接口都再下拉列表中:

澳门金莎娱乐网站 22查看Span

以ServiceA为例,点击 Find Traces,可以看到其所有追踪信息:

澳门金莎娱乐网站 23Find Traces

点击某个具体Trace,还能看到详细的每个Span的信息,如下图中,可以看到 A → B → C 调用过程中每个REST接口的详细时间戳:

澳门金莎娱乐网站 24某一个具体Trace

点击某一个REST接口进去还能看到更详细的信息,如查看/servicec这个REST接口,可以看到从发送请求到收到响应信息的所有详细步骤:

澳门金莎娱乐网站 25某一个具体Span详细信息

由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

  • My Personal Blog
  • 我的半年技术博客之路

本文实验所用源码已经开源,需要的话请 自取。

由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

  • My Personal Blog
  • 我的半年技术博客之路

编辑:编程技术 本文来源:澳门金莎娱乐网站微服务调用链追踪中央搭建,

关键词:

  • 上一篇:没有了
  • 下一篇:没有了