This action will force synchronization from 陌溪/LearningNotes, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
Zipkin是一个开源的分布式的链路追踪系统,每个微服务都会向zipkin报告计时数据,聚合各业务系统调用延迟数据,达到链路调用监控跟踪。
如图,在复杂的调用链路中假设存在一条调用链路响应缓慢,如何定位其中延迟高的服务呢?
zipkin
的web UI
可以一眼看出延迟高的服务如图所示,各业务系统在彼此调用时,将特定的跟踪消息传递至zipkin
,zipkin在收集到跟踪信息后将其聚合处理、存储、展示等,用户可通过web UI
方便获得网络延迟、调用链路、系统依赖等等。
同时zipkin会根据调用关系通过zipkin ui生成依赖关系图,下面是我搭建成功后,蘑菇博客链路追踪的依赖图。
tip:在使用zipkin链路追踪的时候,需要提前启动zipkin服务,然后在启动我们的蘑菇博客项目,这样才能够正常的将服务调用的信息注册到zipkin中
在 SpringBoot 2.x 版本后就不推荐自定义 zipkin server 了,推荐使用官网下载的 jar 包方式
也就是说我们不需要编写一个mogu-zipkin服务了,而改成直接启动jar包即可
https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec
java -jar zipkin-server-2.12.5-exec.jar
# 或集成RabbitMQ
java -jar zipkin-server-2.12.5-exec.jar --zipkin.collector.rabbitmq.addresses=127.0.0.1
这样zipkin就是以内存存储的方式进行启动了
目前zipkin收集的信息能够以三种方式进行存储
这里我们尝试的是以mysql的方式进行存储,如果不想以mysql进行存储的话,可以忽略这一步
首先我们需要在mogu_blog数据库中,执行下面的官方SQL脚本,创建对应的表
如果上述地址过期,请执行下面的SQL脚本,在之前,需要创建一个数据库,叫zipkin
--
-- Copyright 2015-2019 The OpenZipkin Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software distributed under the License
-- is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions and limitations under
-- the License.
--
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(255) NOT NULL,
`remote_service_name` VARCHAR(255),
`parent_id` BIGINT,
`debug` BIT(1),
`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',
PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
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(255) 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(16) 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(255) 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(`a_type`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values';
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(255) NOT NULL,
`child` VARCHAR(255) NOT NULL,
`call_count` BIGINT,
`error_count` BIGINT,
PRIMARY KEY (`day`, `parent`, `child`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
执行完成后,我们将会得到下面的三个表
其中
然后在安装下面的方式进行启动
java -jar zipkin.jar --STORAGE_TYPE=mysql --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306
启动完成后,我们在运行我们的服务,在打开数据库就能看到信息存储在mysql中了
安装完成后,我们需要引入 sleuth 和 zipkin的依赖
<!-- sleuth -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<!-- zipkin链路追踪 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
然后在业务服务的application.yml增加下面的配置,其中蘑菇博客的业务服务主要是:mogu-web,mogu-admin,mogu-sms,mogu-picture,mogu-search
#spring
spring:
# sleuth 配置
sleuth:
web:
client:
enabled: true
sampler:
probability: 1.0 # 采样比例为: 0.1(即10%),设置的值介于0.0到1.0之间,1.0则表示全部采集。
# zipkin 配置
zipkin:
base-url: http://localhost:9411 # 指定了Zipkin服务器的地址
然后浏览器输入下面的地址:http://localhost:9411 ,如果出现下面的画面,那么代表我们zipkin服务配置成功了
spring-cloud-starter-sleuth: 英文名是侦探,它的功能是在项目中自动为日志加入Tag与序列号
源码:https://github.com/spring-cloud/spring-cloud-sleuth
调用侧请求中加入额外的Span序列号等上下文信息放入Header中(通过注入Feign定制Client实现),被调用侧通过全局Filter模拟AOP记录执行情况,计算执行情况与耗时,并存入定制的ByteBoundedQueue队列中,然后通过HTTP等将信息异步发送到Zipkin收集器中,Zipkin收集器通过UI显示调用详情
其中添加了如下组件
TraceFeignClient: 请求端注入的FeignClient,为Request的Header添加SpanID, TraceID等信息
TraceFilter: 接收端注入的定制Filter,它将解析Request中的Header,执行业务,计算耗时,最终算出一个完整的JSON格式的Span,通过队列异步发送到收集器ZipKin中
ZipKin:日志收集器,读取JSON格式的SPAN信息,并存储与展示
如果使用spring-cloud-sleuth-zipkin或spring-cloud-sleuth-stream,PercentageBasedSampler是默认的(默认值是0.1),你可以使用spring.sleuth.sampler.percentage配置输出
用户可以使用span tags定制关键字,为了限制span数据量,一般一个HTTP请求只会被少数元数据标记,例如status code、host以及URL,用户可以通过配置spring.sleuth.keys.http.headers(一系列头名称)添加request headers
来自Twitte的分布式日志收集工具,分为上传端(spring-cloud-starter-zipkin,集成到项目中)与服务端(独立部署,默认将数据存到内存中)
注意: Zipkin仅对RPC通信过程进行记录,注意它与业务代码日志是无关的,如果你希望找到一款LogAppender来分析所有Log4j留下的日志,那么建议还是使用Kakfa+ELK这种传统的方法来实现。
https://github.com/apache/incubator-zipkin
使用zipkin涉及到以下几个概念
上图表示一请求链路,一条链路通过Trace Id
唯一标识,Span
标识发起的请求信息,各span
通过parent id
关联起来,如图
整个链路的依赖关系如下:
完成链路调用的记录后,如何来计算调用的延迟呢,这就需要利用Annotation
信息
sr-cs 得到请求发出延迟
ss-sr 得到服务端处理延迟
cr-cs 得到整个链路完成延迟
Zipkin Server主要包括四个模块:
首页里面主要承载了trace的查询功能,根据不同的条件,搜索数据
这个图中,需要注意的是相对时间和调用行为
调用行为分如下四种:
cs - Client Send : 客户端已经提出了请求。这就设置了跨度的开始。
sr - Server Receive: 服务器已收到请求并将开始处理它。这与CS之间的差异将是网络延迟和时钟抖动的组合。
ss - Server Send: 服务器已完成处理,并将请求发送回客户端。这与SR之间的差异将是服务器处理请求所花费的时间
cr - Client Receive : 客户端已经收到来自服务器的响应。这就设置了跨度的终点。当记录注释时,RPC被认为是完整的。
相对时间:
表示在调用链开始到现在的时间,比如
从trace生成到现在,
17ms的时候,Client Send bas-ms这个应用发出了调用
19ms的时候,Server Receive ems-ms收到了bas-ms的调用。 这个说明,从bas-ms到ems-ms中间的网络耗时花费了2ms.
34ms的时候,Server Send ems-ms的方法执行完毕,准备返回响应结果给bas-ms , 这说明ems-ms处理请求花费了34-19 = 15ms
34ms的时候,Client Receive bas-ms收到了返回结果
界面显示的时候,是根据相对时间来排序的,所以Client Receive排在了第三位,因为他和Server Send的时间是一样的。
点击服务名,弹出如下框,显示出了调用关系
点击具体的服务名,出现如下界面
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。