学网站建设难,网站每年都要续费吗,什么网站做班服比较好,兰州做网站的公司有哪些目录 一、前言
二、分布式链路调用问题
三、链路追踪中的几个概念
3.1 什么是链路追踪
3.2 常用的链路追踪技术
3.3 链路追踪的几个术语
3.3.1 span
编辑
3.3.2 trace
3.3.3 Annotation
四、sluth与zipkin概述
4.1 sluth介绍
4.1.1 sluth是什么
4.1.2 sluth核心…目录 一、前言
二、分布式链路调用问题
三、链路追踪中的几个概念
3.1 什么是链路追踪
3.2 常用的链路追踪技术
3.3 链路追踪的几个术语
3.3.1 span
编辑
3.3.2 trace
3.3.3 Annotation
四、sluth与zipkin概述
4.1 sluth介绍
4.1.1 sluth是什么
4.1.2 sluth核心功能
4.1.3 sluth工作原理
4.2 zipkin介绍
4.2.1 zipkin是什么
4.2.2 zipkin工作原理与核心组件
4.3 sluth与zipkin的关系
五、微服务集成Sleuth
5.1 Sleuth集成过程
5.1.1 导入依赖
5.1.2 添加注解
5.1.3 参数说明
六、微服务集成sleuth zipkin
6.1 部署zipkin服务端
6.1.2 访问UI界面
6.2 zipkin数据持久化
6.2.1 获取zipkin的建表sql
6.2.2 重启zipkin服务
6.3 springcloud客户端集成zipkin
6.3.1 导入zipkin依赖
6.3.2 添加配置文件
6.3.3 重启服务并触发接口调用
七、写在文末 一、前言
在springcloud技术栈构建的微服务架构体系中一旦微服务数量越来越多服务之间的调用链路也必然越来越复杂遇到问题时排查难度也会相应增加。 二、分布式链路调用问题
如下图所示为模拟一个微服务架构的系统在真实线上部署的场景客户端发出的一个请求通过网关之后在内部处理请求时可能经历了非常复杂的互相调用试想现在某个链路突然发生异常对于开发人员来说是不是有点摸不着头脑。 以上只是众多的微服务调用链路中相对比较简单的一种通常来说在分布式调用中一个由客户端发起的请求在后端系统中会经过多个不同的微服务调用来协同产生最后的请求结果。 在复杂的微服务架构系统中几乎每一个请求都会形成一条复杂的分布式服务调用链路。在每条链路中任何一个依赖服务出现延迟过高或错误时都有可能造成请求最后的失败。这时对于每个请求全链路调用的跟踪就变得非常重要。 通过实现对请求调用的跟踪可以帮助开发人员快速的定位错误根源以及监控分析每条请求链路上的性能瓶颈等。 在开源的分布式链路追踪解决方案中以springcloud生态来说针对微服务链路追踪这个问题Spring Cloud Sleuth提供了一套完整的解决方案。 三、链路追踪中的几个概念 3.1 什么是链路追踪
链路追踪一词最早在2010年提出由谷歌发表的一篇关于大规模分布式系统跟踪的论述介绍了谷歌自研的分布式链路追踪的实现原理。 侠义上理解链路追踪就是指一次任务从开始到结束期间调用的所有系统以及耗时时间跨度都可以完整的记录下来。 广义上讲链路追踪是指在分布式系统中将一次请求的处理过程进行记录并聚合展示的一种方法。目的是将一次分布式请求的调用情况集中在一处展示如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等。这样就可以轻松了解一个请求在系统中的完整生命周期包括经过的服务、调用的操作以及每个操作的延迟等。 通过链路追踪可以更好地理解系统的性能瓶颈、找出问题的根源以及优化系统的性能。 3.2 常用的链路追踪技术
目前链路追踪方案像Google的Dapper阿里的鹰眼大众点评的CATTwitter的ZipkinLINE的pinpoint国产的skywalking等。市面上的全链路监控理论模型大多都是借鉴Google Dapper论文这里列举下面几种
cat由大众点评开源基于Java开发的实时应用监控平台包括实时应用监控业务监控。集成方案是通过代码埋点的方式实现监控。比如拦截器过滤器等。对业务代码具有一定的侵入性集成成本较大风险较高Zipkin 由Twitter公司开源开放源代码分布式的跟踪系统用于收集服务的定时数据以解决微服务架构中的延迟问题包括数据的收集、存储、查找和展现通常结合springcloud-sleuth一起使用比较简单集成方便但是功能相对简单Pinpoint 一款对Java编写的大规模分布式系统的APM工具由韩国人开源的分布式跟踪组件其底层基于字节码的注入进行调用链的分析以及应用监控分析工具其特点是支持多种插件UI功能强大接入端无代码前任Skywalking 国产的优秀APM组件是一个对JAVA分布式应用程序集群的业务运行情况进行追踪、告警和分析的系统基于字节码注入调用链分析以及应用监控分析工具特点是支持多种插件UI功能强大接入端无代码侵入目前已加入apache孵化sleuth由springcloud提供的分布式系统中链路追踪的解决方案
下面结合两种使用较多的链路追踪工具zipkin和Skywalking 进行对比说明
类型zipkinSKYwalking基本原理拦截请求发送HTTPmq数据至zipkin服务java探针字节码增强接入方式基于linkerd或者sleuth方式引入配置即可Java agent字节码支持OpenTracing是是颗粒度接口级类级别方法级存储ESmysql,Cassandra,内存ESH2TIDBagent到collector的协议httpMQhttp,gRPC 3.3 链路追踪的几个术语
在链路追踪的解决方案中不管是哪一种基本上各个组件底层都使用了相同的规范其中涉及到下面几个非常重要的术语。 3.3.1 span
span代表一组基本的工作单元一次单独的调用链可称为一个span。通俗理解span就是一次请求信息当发送一个远程调用时就会产生一个SpanSpan 由一个64位ID唯一标识的。 举例来说为统计一个请求中各处理单元的延迟当请求到达服务的各个组件时通过一个唯一标识SpanId来标记它的开始、具体过程和结束。通过SpanId的开始和结束时间戳就能统计该span的调用时间除此之外我们还可以获取如事件的名称。请求信息等元数据。 如下图中一个矩形框就是一个 Span前端从发出请求到收到回复就是一个 Span。 3.3.2 trace
由一组TraceId相同的Span串联形成的一个树状结构。一个trace可认为是一次完整的链路内部包含多个spantrace和span之间是一对多的关系。而span与span之间存在父子级关系。 为实现请求跟踪当请求到达分布式系统的入口端点时只需要服务跟踪框架为该请求创建一个唯一的标识即TraceId同时在分布式系统内部流转的时候框架始终保持传递该唯一值直到整个请求的返回。那么我们就可以使用该唯一标识将所有的请求串联起来形成一条完整的请求链路。 举个例子客户端调用服务 A 、服务 B 、服务 C 、服务 F而每个服务例如 C 就是一个 Span如果在服务 C 中另起线程调用了 D那么 D 就是 C 的子 Span如果在服务 D 中另起线程调用了 E那么 E 就是 D 的子 Span这个 C - D - E 的链路就是一条 Trace。如果链路追踪系统做好了链路数据有了借助前端解析和渲染工具可以达到下图中的效果 3.3.3 Annotation
Annotation 用于记录一段时间内的事件内部使用的重要注释
csClient Send客户端发起一个请求这个 annotation 描述了这个 span 的开始srServer Received服务端获得请求并准备开始处理它如果 sr 减去 cs 时间戳便可得到网络延迟ssServer Send请求处理完成当请求返回客户端如果 ss 减去 sr 时间戳便可得到服务端处理请求需要的时间crClient Reveived表示 span 结束客户端成功接收到服务端的回复如果 cr 减去 cs 时间戳便可得到客户端从服务端获取回复的所有所需时间 四、sluth与zipkin概述 4.1 sluth介绍 4.1.1 sluth是什么
Spring Cloud 微服务治理框架中的一个组件专门用于记录链路数据的开源组件官网地址
4.1.2 sluth核心功能
sluth提供的核心功能主要如下
链路追踪通过 Sleuth 可以很清楚的看出一个请求都经过了那些服务可以很方便的理清服务间的调用关系等性能分析通过 Sleuth 可以很方便的看出每个采样请求的耗时分析哪些服务调用比较耗时当服务调用的耗时随着请求量的增大而增大时 可以对服务的扩容提供一定的提醒数据分析优化链路对于频繁调用一个服务或并行调用等可以针对业务做一些优化措施可视化错误对于程序未捕获的异常可以配合 Zipkin 查看
4.1.3 sluth工作原理
下面这张图详细说明了sleuth在工作过程中其内部的运行原理理解了这张图的原理不仅明白了sleuth是如何运行的也对链路追踪中的几个概念也会有更深刻的理解。 关于这张图的调用过程做如下说明
从左到右展示了客户端从发送一个请求到最终请求响应结果的完整链路如果想知道一个接口在哪个环节出现了问题就必须清楚该接口调用了哪些服务以及调用的顺序如果把这些服务串起来看起来就像链条一样我们称之为调用链想要实现调用链就要为每次调用做个标识然后将服务按标识大小排列可以更清晰地看出调用顺序我们暂且将该标识命名为 spanid实际场景中我们需要知道某次请求调用的情况所以只有spanid还不够得为每次请求做个唯一标识这样才能根据标识查出本次请求调用的所有服务而这个标识我们命名为 traceid现在根据 spanid 可以轻易地知道被调用服务的先后顺序但无法体现调用的层级关系正如下图所示多个服务可能是逐级调用的链条也可能是同时被同一个服务调用所以应该每次都记录下是谁调用的我们用 parentid 作为这个标识的名字到现在已经知道调用顺序和层级关系了但是接口出现问题后还是不能找到出问题的环节如果某个服务有问题那个被调用执行的服务一定耗时很长要想计算出耗时上述的三个标识还不够还需要加上时间戳时间戳可以更精细一点精确到微秒级 其实 span 内除了记录这几个参数之外还可以记录一些其他信息比如发起调用服务名称、被调服务名称、返回结果、IP、调用服务的名称等最后我们再把相同 parentid 的 span 信息合成一个大的 span 块就完成了一个完整的调用链。 4.2 zipkin介绍 4.2.1 zipkin是什么
zipkin是一款开源的分布式实时数据追踪系统Distributed Tracking System基于 Google Dapper的论文设计而来由 Twitter 公司开发贡献。它有助于收集对服务架构中的延迟问题进行故障排除所需的计时数据。功能包括收集和查找这些数据。 zipkin是一个开放源代码分布式的跟踪系统它可以帮助收集服务调用中的时间数据以解决微服务架构中的延迟问题。具体来说包括数据收集、存储、查找和展现。 当微服务接入zipkin之后每个服务向zipkin报告计时数据zipkin会根据调用关系通过Zipkin UI生成依赖关系图展示多少跟踪请求经过了哪些服务该系统让开发者可通过一个web前端轻松地收集和分析数据可非常方便的监测系统中存在的瓶颈。 下面是一张关于zipkin的原理图从图中不难发现在真实的环境中zipkin主要是承担收集各个服务上报过来的信息比如日志、服务链路等数据经过内部的处理之后通过ui界面进行展现。 4.2.2 zipkin工作原理与核心组件
下面是zipkin的工作原理图 或者通过下面这张运行原理图可以以全局的视角来了解zipkin 从上面的图中可以发现zipkin在运行过程中其核心组件主要包括下面几种 Collector信息收集器 主要用于处理从外部系统发送过来的跟踪信息将这些信息转换为Zipkin内部处理的Span格式以支持后续的存储、分析、展示等功能。 Storage数据存储组件 主要对处理收集器接收到的跟踪信息默认会将这些信息存储在内存中我们也可以修改此存储策略通过使用其他存储组件将跟踪信息存储到 数据库或es 中。 RESTful APIAPI组件 主要用于提供外部访问接口比如给客户端展示跟踪信息或是外接系统访问以实现监控等。 Web UIUI组件 基于API组件实现的上层应用。通过UI组件用户可以方便而有直观地查询和分析跟踪信息。 小结 1Zipkin 分两端一个是 Zipkin 服务端一个是 Zipkin 客户端客户端也就是微服务应用 2客户端会配置服务端的 URL 地址一旦发生服务间的调用的时候会被配置在微服务里面的 Sleuth 的监听器监听并生成相应的 Trace 和 Span 信息发送给服务端 3发送的方式有两种一种是消息总线的方式如 RabbitMQ 发送还有一种是 HTTP 报文的方式发送 4.3 sluth与zipkin的关系
通过上面的介绍我们了解到Sleuth是将每个请求从开始调用到结束过程中的每一步都进行记录 但这些信息都是分散存在的通过以日志格式输出出来真正进行问题分析定位时并不方便此时就需要有一个工具可以将这些分散的信息进行收集和汇总并且能显示可视化结果便于分析和定位。 有了zipkin之后sleuth的只需要把链路追踪的元数据信息上报给zipkin由zipkin进行存储并将链路信息以可视化的方式进行呈现。 五、微服务集成Sleuth
sleuth可以单独在springboot项目中使用也可以在springcloud、dubbo中进行集成下面介绍sleuth最简单的集成方式。
5.1 Sleuth集成过程
文档地址官方文档地址
git地址sleuth git地址 5.1.1 导入依赖
maven中导入sleuth依赖
!-- spring cloud sleuth 依赖 --
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-sleuth/artifactId
/dependency
5.1.2 添加注解
以之前整合的一个springcloud微服务为例进行说明最简单的集成方式是只需要在需要进行链路追踪的类上面添加 Slf4j注解即可如下服务的调用链路为order - user我们分别在需要调用的类上面添加注解 用户微服务中添加注解在方法的关键入口添加日志输出默认sleuth追踪info级别的日志
RestController
RequestMapping(/user)
Slf4j
public class UserController {Autowiredprivate UserService userService;//http:localhost:9002/user/getById?id001GetMapping(/getById)public User getById(RequestParam String id) {log.info(根据ID获取用户信息);return userService.getById(id);}
}
Slf4j
Service
public class UserServiceImpl implements UserService {Autowiredprivate RedisTemplateString, Object redisTemplate;Autowiredprivate UserMapper userMapper;Overridepublic User getById(String id) {log.info([用户服务] 基于 id 查询用户信息{}, id);String key sw:users: id;Object json redisTemplate.opsForValue().get(key);if (json ! null) {log.info([用户服务] redis 中查询到用户信息key{}, json{}, key, json);return JSON.parseObject(json.toString(), User.class);}User user userMapper.getById(id);if (user ! null) {log.info([用户服务] redis 中不存在从数据库查到数据并缓存{}, user);redisTemplate.opsForValue().set(key, user, 2, TimeUnit.HOURS);return user;}log.warn([用户服务] 基于 id 查询用户失败用户不存在{}, id);return null;}
}
order微服务中添加注解
RequestMapping(/order)
RestController
Slf4j
public class OrderController {Autowiredprivate OrderService orderService;//localhost:9003/order/getById?id001GetMapping(/getById)public Object getById(RequestParam String id) {log.info(根据ID获取订单);return orderService.getById(id);}
}
Slf4j
Service
public class OrderServiceImpl implements OrderService {Autowiredprivate UserFeignService userFeignService;Overridepublic Map getById(String id) {log.info([订单服务] 基于 id 查询订单详情{}, id);Map map new HashMap();Order order new Order();order.setOrderId(0002);order.setProductId(0001);order.setProductName(小米手机);map.put(order,order);User user userFeignService.getById(001);map.put(user,user);return map;}
}
重启两个微服务模块然后调用一下接口 5.1.3 参数说明
接口调用成功后我们观察控制台输出日志信息order模块输出日志信息如下 user模块输出的日志信息如下 关于日志信息做如下几点说明
第一个值spring.application.name 的值第二个值sleuth生成的一个ID即traceId用来标识一条请求链路一条请求链路中包含一个traceId多个spanId第三个值spanId基本工作单元获取元数据比如发送一个http第四个值true/false表示信息输出到zipkin中收集和展示 六、微服务集成sleuth zipkin
通过上文了解到zipkin是一款用于做实时链路数据追踪的应用通过可视化的方式展现从服务中上报的日志等链路追踪数据便于问题的排查定位和分析更加的人性化。 通常以springcloud技术栈的微服务中通常是将sleuth 搭配zipkin一起使用。当然也可以单独在springboo工程中接入zipkin。 6.1 部署zipkin服务端
zipkin服务端是一个独立的可执行的 jar 包jar包下载地址 1、官网下载OpenZipkin · A distributed tracing system 2、ftp下载zipkin各版本下载地址 这里我下载 2.22.1的版本的jar包 下载之后不管是本地还是在linux服务器上最简单的方式直接使用下面的命令启动即可
java -jar zipkin-server-2.20.1-exec.jar 6.1.2 访问UI界面
服务启动之后通过9411端口可以直接访问zipkin的web-ui界面如下图所示后面当微服务接入zipkin之后一旦发生服务间的调用将会展示出调用链路相关信息 6.2 zipkin数据持久化
Zipkin 默认将监控数据存储在内存中很显然如果 Zipkin 挂掉或重启的话监控数据就会丢失。所以生产中肯定是不能直接这样使用需要对Zipkin的监控数据进行持久化存储。zipkin提供了多种数据持久化存储的方式
内存默认mysql推荐es推荐Cassandra
下面以mysql为例进行说明 6.2.1 获取zipkin的建表sql
脚本下载地址在 github zipkin项目里的 zipkin-storage/mysql-v1/src/main/resounce 目录下
mysql脚本地址
为例方便使用下面贴出完整的sql
--
-- 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)
) ENGINEInnoDB ROW_FORMATCOMPRESSED CHARACTER SETutf8 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
) ENGINEInnoDB ROW_FORMATCOMPRESSED CHARACTER SETutf8 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)
) ENGINEInnoDB ROW_FORMATCOMPRESSED CHARACTER SETutf8 COLLATE utf8_general_ci;
创建一个数据库名为zipkin然后执行上面的sql创建表 6.2.2 重启zipkin服务
使用下面的命令重新启动zipkin服务
java -jar zipkin-server-2.22.1-exec.jar --STORAGE_TYPEmysql --MYSQL_HOSTIP地址 --MYSQL_TCP_PORT3306 --MYSQL_DBzipkin --MYSQL_USERroot --MYSQL_PASS密码
启动之后再次访问仍然可以正常访问ui页面 6.3 springcloud客户端集成zipkin
上面的环境准备好之后相当于是搭建了zikpkin的服务端接下来就可以在springcloud微服务工程中客户端集成zpikin将客户端的服务调用链路信息上报zipkin了参考下面的操作步骤
6.3.1 导入zipkin依赖
sleuth的依赖仍然保留同时添加zipkin的依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-sleuth/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-zipkin/artifactId/dependency
6.3.2 添加配置文件
在工程的配置文件中添加如下关于zipkin和sleuth的配置信息如果是云服务器需要提前开通9411的防火墙端口
server:port: 9002spring:application:name: user-servicezipkin:base-url: http://127.0.0.1:9411sleuth:sampler:probability: 1cloud:nacos:discovery:server-addr: nacos地址:8848
6.3.3 重启服务并触发接口调用
确保zipkin服务已经启动然后启动user和order两个服务并调用下面的获取订单接口 调用成功后在zipkin的ui界面上就能看到调用的链路信息了如下图所示 也可以点击进去进一步查看通过其他维度检查这个调用链路的详细信息比如中间经历了哪些步骤各个链路的耗费时间 也可以切换到依赖视图以拓扑图的形式展示服务的调用链路情况 七、写在文末
本文详细介绍了sleuth和zipkin的使用在springcloud的微服务生态中这两个组件的搭配可以快速实现服务链路的追踪接入简单对服务的可观测性来说是一个很好的补充而zipkin的思想也影响甚至促成了应用可观测领域很多解决方案的诞生有必要深入学习和掌握其适用场景本篇到此结束感谢观看。