如何通过Zipkin或SKYwalking实现链路追踪

前言

微服务架构将原先业务链条中的各个环节(节点或过程),如用户、产品、订单、支付拆分实现成独立的服务运行,一定程度上提高了系统的容错能力,例如支付服务失败时,用户依然可以通过产品及订单服务,达到查看订单和浏览产品的目的。随着微服务应用开发框架(如springboot)和容器技术(如K8)越来越成熟,微服务的开发和运维趋于标准化。这些都是微服务的愈发流行的原因。同时,随着业务复杂度的提高,越来越多的微服务被开发和集成进来,服务管理的重要性不言而喻。本文以服务调用的链路管理为题,浅谈微服务治理中链路管理的主流技术如何实践。

东区网站建设公司成都创新互联,东区网站设计制作,有大型网站制作公司丰富经验。已为东区1000+提供企业网站建设服务。企业网站搭建\外贸网站建设要多少钱,请找那个售后服务好的东区做网站的公司定做!

链路管理,主要指记录服务的调用链路,通常用来定位不合理的服务设计,如链路过长带来的服务耗时问题、链路过长带来的服务稳定性风险、循环依赖等。链路管理,需要考虑哪些方面的问题,如何实现?

  1. 首先,需要知道有哪些服务以及他们的服务状态(服务注册和发现机制),这个目前可以直接通过spring cloud的Eureka实现,当然也可以通过dubbo+zookeeper实现;
  2. 有了服务清单之后,我们需要在每个服务调用的地方拦截并记录,记录调用堆栈,从发起服务到链尾。这一步自己实现起来有较多的工作,譬如统一服务调用规则、AOP拦截、调用链数据结构定义、调用信息采集发送及存储等。
  3. 最后,是链路数据的采集、存储、发送以及最终的图形化展示。

有了这个思路之后,我们再来看目前主流的链路解决方案,Twitter的Zipkin,以及Apache的在孵化项目SKYwalking。当然还有些比较热的方案,如韩国的开源项目Pinpoint和美团的CAT。这些方案从实现技术上大致可分为两个派系,拦截派,字节码增强派。拦截派做法通过代理类拦截请求,将链路信息发送给服务器,Zipkin和CAT都属于这种类型,不过CAT需要代码侵入,即代码中增加埋点,而Zipkin直接通过SpringCloud的Sleuth无缝对接SpringBoot的微服务。字节码增强技术,通过JVMTI接口提供的javaagent(区别于JDK动态代理和CGLIB代理),利用字节码操作技术(ASM),在类加载并实例化之前对class进行转换,之后运行中将信息采集并发送给代理服务器(探针),如sk*walking的Agent服务。关于两种方式的比较,小结如下:

类型zipkinSKYwalking
基本原理 拦截请求,发送(HTTP,mq)数据至zipkin服务 java探针,字节码增强
接入方式 基于linkerd或者sleuth方式,引入配置即可 avaagent字节码
支持OpenTracing
颗粒度 接口级(类级别) 方法级
存储 ES,MySQL,Cassandra,内存 ES,H2,TIDB
agent到collector的协议 http,MQ http,gRPC

Zipkin实践

Zipkin 分为两端,Zipkin 服务端和Zipkin 客户端,客户端也就是微服务的应用。客户端配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监听,并生成相应的 Trace 和 Span 信息发送给服务端。发送的方式主要有两种,一种是 HTTP 报文的方式,另一种是消息总线的方式如 RabbitMQ。

不论哪种方式,我们都需要:一个 Eureka 服务注册中心,先看下Zipkin运行架构:
如何通过Zipkin或SKYwalking实现链路追踪

左侧应用服务,同时也是Zipkin-clinet,Eureka-client, 中间是依赖,包括Zipkin-server和Eureka-server,最右侧是WebUI展示及开发接口。

Zipkin 的服务端,在使用 Spring Boot 2.x 版本后,官方就不推荐自行定制编译了,反而是直接提供了编译好的 jar 包来给我们使用。
所以官方提供了一键脚本

curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar

如果用 Docker 的话,直接
docker run -d -p 9411:9411 openzipkin/zipkin

这里使用docker环境测试,数据存储选择默认的内存方式。启动zipkinserver后,直接访问9411,看到管理页面:
如何通过Zipkin或SKYwalking实现链路追踪

zipkinserver启动后,启动EurekaServer,先本地启动一个,端口暂定为7777.
如何通过Zipkin或SKYwalking实现链路追踪

好了,现在依赖服务有了,接下来改造两个现有的微服务(为至少两个有调用关系的服务配置),作为zkclient。要做的事情很简单,下面几步:

  1. 配置EurekaClient

1)微服务增加zipkin依赖

compile "org.springframework.cloud:spring-cloud-starter-sleuth"
compile "org.springframework.cloud:spring-cloud-starter-zipkin"

2) 启动类增加EurekaClient注解
@EnableDiscoveryClient

3)application配置文件增加Eureka配置

eureka.instance.hostname=localhost
eureka.client.serviceUrl.defaultZone = http://${eureka.instance.hostname}:7777/eureka/
eureka.instance.preferIpAddress= true
  1. 配置Zipkin

1)开启sleuth client

spring.sleuth.web.client.enabled=true
spring.sleuth.sampler.percentage=1.0 

sampler.percentage是采样率,1代表选取全部样本,因为是测试,所以直接设置成1,实际情况可能是个小数,0.3或者0.5,根据需求自行决定。

2)配置zipkinserver地址
spring.zipkin.base-url=http://192.168.72.101:9411/

  1. 调用服务查看结果

1) Eureka服务清单
如何通过Zipkin或SKYwalking实现链路追踪

2) Zipkin服务链路
如何通过Zipkin或SKYwalking实现链路追踪

如何通过Zipkin或SKYwalking实现链路追踪

需要注意的是,由于Sleuth trace filter仅针对Spring内置的Rest调用做拦截,跨服务的调用需要使用Spring官宣方式,如RestTemplate,直接使用apache的httpclient工具包调用,是无法追踪到完整链路。

下面从实现层面了解,Zipkin的工作机制。引入sleuth和zipkin依赖包之后,系统自动扫描所有包中的@configuration,TraceAutoConfiguration是sleuth包的配置入口,看看它的定义,spring.sleuth.enabled开启的时候注解有效。

@Configuration
@ConditionalOnProperty(
    value = {"spring.sleuth.enabled"},
    matchIfMissing = true
)
@EnableConfigurationProperties({TraceKeys.class, SleuthProperties.class})
public class TraceAutoConfiguration {
...

同理,Zipkin的配置如下:

@Configuration
@EnableConfigurationProperties({ZipkinProperties.class, SamplerProperties.class})
@ConditionalOnProperty(value = "spring.zipkin.enabled", matchIfMissing = true)
@AutoConfigureBefore(TraceAutoConfiguration.class)
public class ZipkinAutoConfiguration {
...

TraceFilter作为整个追踪的切入口,针对所有的request进行过滤标记,并通过AsyncReporter进行异步发送报文。下图框起来的部分,分别是接口地址和编码协议(Thrift)
如何通过Zipkin或SKYwalking实现链路追踪

SKYwalking实践

Zipkin使用起来很简单,但是因为是接口级的跟踪,能看到的信息比较有限,另外页面的展示形式也相对简单,缺少多角度或者多样性,所以,我们再试试SKYWalking。
skywalking的工作机制,需要三块协同,一块是skywalking server,负责接收、存储并展示,所以server模块包含一个展示web子模块;第二块是agent,负责代理微服务并收集需要的信息,转发给server;第三块便是微服务本身,需要在启动时指定agent,以便生成代理类。工作原理图大致如下:

如何通过Zipkin或SKYwalking实现链路追踪

先看下效果图,再记录配置过程。
如何通过Zipkin或SKYwalking实现链路追踪

选中其中一个服务,可以查看调用关系及服务基础状态。
如何通过Zipkin或SKYwalking实现链路追踪

拓扑图还有个扁平展示效果(很适合ppt介绍有没有)
如何通过Zipkin或SKYwalking实现链路追踪

仪表盘看服务状态:
如何通过Zipkin或SKYwalking实现链路追踪

追踪栏看调用明细:
如何通过Zipkin或SKYwalking实现链路追踪

失败调用还有错误日志:
如何通过Zipkin或SKYwalking实现链路追踪

告警栏速览全局风险:
如何通过Zipkin或SKYwalking实现链路追踪

吹完疗效,看下怎么配置,先看server。

下载最新的skywalking,选了6.4,一开选的6.1有bug,拓扑图经常出不来。server的运行可以运行在容器内,也可以运行虚拟服务器譬如ECS上。server的配置主要是存储相关,mysql和es任选一个,看数据量和操作便捷性,数据量可控的情况下,简单起见,直接用mysql,换掉innodb引擎即可。

  1. 配置文件applicaiton.yml中打开datasource选项。
    如何通过Zipkin或SKYwalking实现链路追踪
  2. datasource-setting.properties中指向自建的数据库。(只需要建库和访问账号,表在启动时会自动初始化,表很多。。。)

server的访问端口分别是:11800和12800,分别是gRPC和rest端口,如果改了,需要通过修改后面config的访问端口。这里提示开防火墙端口。

Agent的同样有两种方式,一种是将agent打在镜像中,微服务的镜像基于这个镜像;另一种是直接copy到一个共享目录,每个微服务启动参数增加指向。第二种方式在测试环境比较实用,生产环境基本上用镜像更合适,因为微服务运行在容器中,访问共享目录不现实。
不管选择哪种方式,config的配置是关键。
如何通过Zipkin或SKYwalking实现链路追踪

agentName需要和微服务参数指定的一致。后台服务地址指向oapserver。

最后一步,微服务启动参数增加agent指向:
-Dskywalking.agent.application_code=agent-test
这个agent-test就是agentname,需要和agent配置的name一致!

非容器方式的配置主要就这三步,完事就可以看到效果了。当然,服务之前的调用,需要用spring提供的restTemplate,不要直接用apache的httpclient工具包,否则不会被采集。关于容器环境的部署,后面抽空再补记录。


本文标题:如何通过Zipkin或SKYwalking实现链路追踪
本文来源:http://csdahua.cn/article/josdeh.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流