14 链路跟踪:基于 Sleuth+Zipkin 实施链路跟踪体系

在前面几讲我们主要讲解了基于 Sentinel 如何对微服务架构提供限流、熔断保护。从本讲开始,我们继续完善微服务架构,介绍如何在 Spring Cloud 架构下基于 Sleuth+Zipkin 实现微服务链路追踪。本讲咱们将学习以下三方面内容:

  • 介绍微服务链路追踪的原理;

  • 讲解基于 Spring Cloud Sleuth 实现链路追踪;

  • 构建 Zipkin Server 实现链路追踪的可视化管理。

下面咱们先来介绍什么是微服务链路追踪。

微服务链路追踪

我们先看一个图,都知道在微服务架构下,系统的功能是由大量的微服务协调组成的,例如:电商创建订单业务就需要订单服务、库存服务、支付服务、短信通知服务逐级调用才能完成。而每个服务可能是由不同的团队进行开发,部署在成百上千台服务器上。

图片1.png

复杂的调用链路

如此复杂的消息传递过程,当系统发生故障的时候,就需要一种机制对故障点进行快速定位,确认是哪个服务出了问题,链路追踪技术由此而生。所谓的链路追踪,就是运行时通过某种方式记录下服务之间的调用过程,在通过可视化的 UI 界面帮研发运维人员快速定位到出错点。引入链路追踪,是微服务架构运维的底层基础,没有它,运维人员就像盲人摸象一样,根本无法了解服务间通信过程。

在 Spring Cloud 标准生态下内置了 Sleuth 这个组件,它通过扩展 Logging 日志的方式实现微服务的链路追踪。说起来比较晦涩,咱们看一个实例就明白了,在标准的微服务下日志产生的格式是:

2021-01-12 17:00:33.441 INFO [nio-7000-exec-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: b-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

但是当引入 Spring Cloud Sleuth 链路追踪组件后就会变成下面的格式:

2021-01-12 17:00:33.441  INFO [a-service,5f70945e0eefa832,5f70945e0eefa832,true] 18404 --- [nio-7000-exec-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: b-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
比较后会发现,在原有日志中额外附加了下面的文本
[a-service,5f70945e0eefa832,5f70945e0eefa832,true]

这段文本就是 Sleuth 在微服务日志中附加的链路调用数据,它的格式是固定的,包含以下四部分:

[微服务 Id,TraceId,SpanId,isExport]

图片2.png

链路追踪数据的组成

  • 微服务 Id,说明日志是由哪个微服务产生的。

  • TraceId,轨迹编号。一次完整的业务处理过程被称为轨迹,例如:实现登录功能需要从服务 A 调用服务 B,服务B再调用服务 C,那这一次登录处理的过程就是一个轨迹,从前端应用发来请求到接收到响应,每一次完整的业务功能处理过程都对应唯一的 TraceId。

  • SpanId,步骤编号。刚才要实现登录功能需要从服务 A 到服务 C 涉及 3 个微服务处理,按处理前后顺序,每一个微服务处理时日志都被赋予不同的 SpanId。一个 TraceId 拥有多个 SpanId,而 SpanId 只能隶属于某一个 TraceId。

  • 导出标识,当前这个日志是否被导出,该值为 true 的时候说明当前轨迹数据允许被其他链路追踪可视化服务收集展现。

下面我们看一个完整的追踪数据实例:

我模拟了服务 A -> 服务 B -> 服务 C的调用链路,下面是分别产生的日志。

#服务 A 应用控制台日志
2021-01-12 22:16:54.394 DEBUG [a-service,e8ca7047a782568b,e8ca7047a782568b,true] 21320 --- [nio-7000-exec-1] org.apache.tomcat.util.http.Parameters   : ...
#服务 B 应用控制台日志
2021-01-12 22:16:54.402 DEBUG [b-service,e8ca7047a782568b,b6aa80fb33e71de6,true] 21968 --- [nio-8000-exec-2] org.apache.tomcat.util.http.Parameters   : ...
#服务 C 应用控制台日志
2021-01-12 22:16:54.405 DEBUG [c-service,e8ca7047a782568b,537098c59827a242,true] 17184 --- [nio-9000-exec-2] org.apache.tomcat.util.http.Parameters   : ...

可以发现,在 DEBUG 级别下链路追踪数据被打印出来,按调用时间先后顺序分别是 A 到 C 依次出现。因为是一次完整业务处理,TraceId 都是相同的,SpanId 却各不相同,这些日志都已经被 Sleuth 导出,可以被 ZipKin 收集展示。

Zipkin 是 推特的一个开源项目,它能收集各个服务实例上的链路追踪数据并可视化展现。刚才 ABC 服务控制台产生的日志在 ZipKin 的 UI 界面中会以链路追踪图表的形式展现。

图片3.png

链路追踪图表

通过这个图表可以非常直观的了解业务处理过程中服务间的依赖关系与处理时间、处理状态等信息,是开发运维人员进行故障分析时必要的工具。

说到这,想必你对服务链路追踪与 Sleuth+Zipkin 组合已经有了初步认识,下面咱们通过实例讲解如何在微服务架构中进行链路追踪。这个过程分为两个阶段:

  • 在服务中加入 Spring Cloud Sleuth 生成链路追踪日志;

  • 通过 ZipKin 收集链路最终日志,生成可视化图表。

微服务整合 Sleuth

为了演示需要,这里创建 a-service、b-service、c-service 三个微服务工程,配置过程十分简单,我们把关键代码拿出来说明。

图片4.png

调用链路示意图

第一步,创建 a-service、b-service、c-service 三个 Spring Boot 工程,pom.xml 依赖如下:

<!--Spring Web应用 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Nacos 客户端 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--服务间通信组件OpenFeign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>
c-service的pom.xml依赖如下:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

因为调用关系是服务 A 调用服务 B,服务 B 调用服务 C,所以在 A、B 两个服务中需要额外依赖 OpenFeign 实现服务间通信。

第二步,配置 ABC 服务的 application.yml,这三个配置文件除了应用名称与服务端口不同外,其他都一样。这里设置 A 服务端口为 7000,B 服务端口 8000,C 服务端口 9000。

server:
  port: 7000 #a:7000/b:8000/c:9000 
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.31.10:8848
        username: nacos
        password: nacos
  application:
    name: a-service #a-service/b-service/c-service
logging:
  level:
    root: debug #为演示需要,开启debug级别日志

第三步,实现业务逻辑,代码如下:

  • c-service 工程。

SampleController,methodC方法产生响应字符串“-> Service C”,方法映射地址“/c”
@RestController
public class SampleController {
    @GetMapping("/c")
    public String methodC(){
        String result = " -> Service C";
        return result;
    }
}
  • b-service 工程。

CServiceFeignClient 通过 OpenFeign 实现了 C 服务的通信客户端,方法名为 methodC。

@FeignClient("c-service")
public interface CServiceFeignClient {
    @GetMapping("/c")
    public String methodC();
}

SampleController 通过 methodB 方法调用 methodC 的同时为响应附加的字符串“-> Service B”,方法映射地址“/b”。

@Controller
public class SampleController {
    @Resource
    private CServiceFeignClient cService;
    @GetMapping("/b")
    @ResponseBody
    public String methodB(){
        String result = cService.methodC();
        result = " -> Service B" + result;
        return result;
    }
}
  • a-service 工程。

BServiceFeignClient通过OpenFeign实现了B服务的通信客户端,方法名为methodB
@FeignClient("b-service")
public interface BServiceFeignClient {
    @GetMapping("/b")
    public String methodB();
}

SampleController 通过 methodA 方法调用 methodB 的同时,成为响应附加的字符串“-> Service A”,方法映射地址“/a”。

@RestController
public class SampleController {
    @Resource
    private BServiceFeignClient bService;
    @GetMapping("/a")
    public String methodA(){
        String result = bService.methodB();
        result = "-> Service A" + result;
        return result;
    }
}

这样一个完整的调用链路已形成。在 3 个服务实例启动后,访问 A 实例
访问 http://localhost:7000/a 得到运行结果。

-> ServiceA -> Service B -> Service C

可以看到 ABC 三个服务按前后顺序依次产生结果,但目前在日志中并没有包含任何链路追踪数据,那如何引入 Sleuth 呢?

很简单,只需要打开三个服务工程的 pom.xml 文件分别引入 spring-cloud-starter-sleuth 依赖。

<!--添加Sleuth依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

加入依赖后,重启服务,无须做任何额外设置,Spring Cloud Sleuth 便自动为日志增加了链路追踪数据,下面是经过我整理后的追踪数据。

#服务 A 应用控制台日志,已附加链路追踪数据
2021-01-12 22:16:54.394 DEBUG [a-service,e8ca7047a782568b,e8ca7047a782568b,true] 21320 --- [nio-7000-exec-1] org.apache.tomcat.util.http.Parameters   : ...
#服务 B 应用控制台日志
2021-01-12 22:16:54.402 DEBUG [b-service,e8ca7047a782568b,b6aa80fb33e71de6,true] 21968 --- [nio-8000-exec-2] org.apache.tomcat.util.http.Parameters   : ...
#服务 C 应用控制台日志
2021-01-12 22:16:54.405 DEBUG [c-service,e8ca7047a782568b,537098c59827a242,true] 17184 --- [nio-9000-exec-2] org.apache.tomcat.util.http.Parameters   : ...

虽然数据已产生,但如果在生产环境靠人工组织数以万计的链路日志显然不现实,我们还需要部署链路追踪数据的分析工具 ZipKin 来简化这个过程。

构建 Zipkin Server 实现链路追踪的可视化管理

Zipkin 是由推特开发的分布式链路追踪系统,用于对 Sleuth 产生的日志加以收集并采用可视化的数据对链路追踪进行分析与图表展示,Zipkin 是典型的 C/S(客户端与服务端)架构模式,需要独立部署 Zipkin 服务器,同时也需要在微服务内部持有Zipkin客户端才可以自动实现日志的推送与展示。

图片5.png

Zipkin 的架构示意图

在部署 Zipkin 服务端后,一旦微服务产生链路追踪日志,Zipkin 客户端便会自动以异步形式将日志数据推送至 Zipkin 服务端,Zipkin 服务端对数据进行组织整理,开发运维人员便可通过 Zipkin 服务端提供的 UI 界面进行查看。下面咱们来讲解 Zipkin 服务端与客户端的部署过程。

部署 Zipkin 服务端

Zipkin 服务端部署非常简单,可以通过官网快速上手。

https://zipkin.io/pages/quickstart.html

图片6.png

快速部署 Zipkin 服务端

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

因为 Zipkin 完全是基于 Java 开发的,在安装好 Java 环境后,只需要使用 Curl 命令下载 Zipkin 最新 Jar 包,并利用 Java 命令启动执行即可。

图片7.png

Zipkin 服务端启动日志

Armeria server started at ports: {/0:0:0:0:0:0:0:0:9411=ServerPort(/0:0:0:0:0:0:0:0:9411, [http])}

这里有一点需要注意,默认 Zipkin 监听本机 9411 端口,如果是网络远程访问,请在系统防火墙放行 9411 端口,否则无法通信。
启动成功后,访问 Zipkin 后台。

http://localhost:9411/zipkin/

图片8.png

Zipkin 服务端 UI

此时映入眼帘的就是 Zipkin 内置的分析 UI 界面,当前因为没有任何服务接入,查询不到任何数据,下面咱们进行 Zipkin 客户端接入。

在微服务安装 Zipkin 客户端

Zipkin 客户端是以 Maven 依赖的形式在微服务中进行安装。

第一步,打开 ABC 工程的 pom.xml 文件,引入 Zipkin 客户端。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

第二步,打开 ABC 工程的 application.yml 配置 Zipkin 通信地址以及采样率。

spring:
  ...
  sleuth:
    sampler: #采样器
      probability: 1.0 #采样率,采样率是采集Trace的比率,默认0.1
      rate: 10000 #每秒数据采集量,最多n条/秒Trace
  zipkin:
    #设置zipkin服务端地址
    base-url: http://localhost:9411

spring.zipkin.base-url 设置可用的 Zipkin 服务端IP端口即可。

另一个采样器的两个设置项需要重点说明:

  • spring.sleuth.sampler.probability 是指采样率,假设在过去的 1 秒 a 服务实例产生了 10 个 Trace,如果采用默认采样率 0.1 则代表只有其中1条会被发送到 Zipkin 服务端进行分析整理,如果设为 1,则 10 条 Trace 都会被发送到服务端进行处理。

  • spring.sleuth.sampler.rate 指每秒最多采集量,说明每条最多允许采集多少条 Trace,超出部分将直接抛弃。

将 ABC 服务都设置好后,启动应用,重新访问http://localhost:7000/a地址,然后打开 Zipkin 服务端 UI 界面http://localhost:9411,点击“查找”按钮,便会出现调用链路。

图片9.png

查询调用链路

图片10.png

查询结果

点击执行之间的蓝条,便会出现对应的链路调用图。

图片11.png

链路条调用图

通过这个图可以直观了解到 ABC 三个服务的执行时间、执行顺序、访问地址、访问方式以及是否执行成功。如果你点击对应的色条,还可以看到更详细的内容。

图片12.png

链路调用明细

下面咱们做一个实验,将 C 服务停止,看链路图会产生什么变化。停止后再次访问 A 服务报 500 错误“java.net.SocketTimeoutException: Read timed out”。此时链路追踪图会显示错误。

图片13.png

异常情况下的链路追踪

通过图表发现最后 b-service 只有 6 纳秒执行时间肯定是有问题的,点击后查看明细。

图片14.png

异常明细

异常信息已经非常清晰的说明 C 服务没有可用的实例导致处理失败,开发人员针对这个问题进行及时补救即可。

讲到这里,我们通过实例的形式带你搭建了基于 Sleuth+Zipkin 的链路追踪的基础架构,下面我们进行一下总结。

小结与总结

本讲咱们学习了三方面内容,首先介绍了链路追踪的作用并分析了 Sleuth+Zipkin 基于日志追踪的原理;其次我们掌握了 Sleuth 的部署方法,只需要引入 Sleuth 的依赖即可;最后介绍了如何引入 Zipkin 实现可视化链路追踪,并模拟了异常情况。

这里咱们留一道讨论题:在日常的开发过程中,研发人员会开发各种不同功能的 RESTful 接口,如何将这些接口的文档化以及如何对这些接口进行版本管理呢?如果你有这方面经验,不妨写在评论中和大家一起分享下。

下一讲,我们将介绍另一款国产的链路跟踪产品 SkyWalking 的使用办法。


15 应用性能监控:通过 SkyWalking 实施链路追踪

上一讲我们掌握了基于 Sleuth+Zipkin 对微服务架构实施基于日志的链路追踪,通过 Sleuth 在微服务应用中附加链路数据,再通过 Zipkin 实现链路数据收集与可视化,从而保证开发与运维人员在生产环境了解微服务的执行过程与具体细节,为产品运维提供了有力的保障。

本讲咱们还是围绕链路追踪这个话题,介绍另一款著名的链路追踪产品 SkyWalking,掌握 SkyWalking 的使用方法。本讲咱们将介绍三方面内容:

  • 介绍 APM 与 SkyWalking;

  • 部署 SkyWalking 服务端与 Java Agent;

  • 介绍 SkyWalking 常用视图。

APM 与 SkyWalking

这些年随着微服务体系的不断完善,链路追踪已经不是什么新兴的概念与技术,很多厂商也提供了自己的链路追踪产品,例如 Spring Cloud Slueth、Zipkin、阿里鹰眼、大众点评 Cat、SkyWalking 等。但这些产品都有一个共同的名字:APM(Application Performance Management),即应用性能管理系统。顾名思义这些产品的根本目的就是对应用程序单点性能与整个分布式应用进行监控,记录每一个环节程序执行状况,通过图表与报表的形式让运维人员随时掌握系统的运行状况,其中在这些著名的产品中我非常推荐各位掌握 SkyWalking 这款 APM 产品,理由很简单,它在简单易用的前提下实现了比 Zipkin 功能更强大的链路追踪、同时拥有更加友好、更详细的监控项,并能自动生成可视化图表。相比 Sleuth+Zipkin 这种不同厂商间混搭组合,SkyWalking 更符合国内软件业的“一站式解决方案”的设计理念,下面咱们来了解下 SKyWalking。

SkyWalking 是中国人吴晟(华为)开源的应用性能管理系统(APM)工具,使用Java语言开发,后来吴晟将其贡献给 Apache,在 Apache 的背书下 SkyWalking 发展迅速,现在已属于 Apache 旗下顶级开源项目,它的官网:http://skywalking.apache.org/

SkyWalking 提供了分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。目前在 GitHub 上 SkyWaking 拥有 15.9K Star,最新版本为:8.3.0。

图片1.png

链路追踪视图

图片2.png

指标监控全局视图

为了能够让各位有个直观认识,我们通过 Sleuth+Zipkin 与 SkyWalking 做对比,看两者的优劣。

202141-155716.png

通过比较我们可以发现,在易用性和使用体验上,SkyWalking 明显好于 Zipkin,功能更丰富的同时也更符合国人习惯,但因为迭代速度较快,社区文档相对陈旧,这也导致很多技术问题需要程序员自己研究解决,因此在解决问题方面需要更多的时间。

部署 SkyWalking 服务端与 Java Agent

在了解 SkyWalking 后,咱们正式进入 SkyWalking 的安装与使用吧。

部署 SkyWalking 服务端

首先咱们要理解 SkyWalking 架构图

图片3.png

SkyWalking 的架构图

SkyWalking 同样采用客户端与服务端架构模式,SkyWalking 服务端用于接收来自 Java Agent 客户端发来的链路跟踪与指标数据,汇总统计后由 SkyWalking UI 负责展现。SkyWalking 服务端同时支持 gRPC 与 HTTP 两种上报方式。其中 gRPC 默认监听服务器 11800 端口,HTTP 默认监听 12800 端口,而 SKyWalking UI 应用则默认监听 8080 端口,这三个端口在生产环境下要在防火墙做放行配置。在存储层面,SkyWalking 底层支持 ElasticSearch 、MySQL、H2等多种数据源,官方优先推荐使用 ElasticSearch,如果此时你不会 ElasticSearch 也没关系,按文中步骤操作也能完成部署。

首先咱们根据架构图部署 SkyWalking 服务端。

第一步,安装 ElasticSearch 全文检索引擎。

ElasticSearch 简称 ES,是业内最著名的全文检索引擎,常用于构建站内搜索引擎,SkyWalking 官方推荐使用 ES 作为数据存储组件。这里直接访问 ES 官网下载页:

https://www.elastic.co/cn/downloads/elasticsearch

下载对应平台的 ES 服务器程序。

图片4.png

ElasticSearch 下载页

下载后会得到 elasticsearch-7.10.2-windows-x86_64.zip 文件,解压缩后无须任何修改直接运行 bin/elasticsearch.bat 文件,如果是 Linux 系统则运行 elasticsearch.sh 文件。

图片5.png

ElasticSearch 启动成功画面

默认 ES 监听 9200 与 9300 端口,其中 9200 是 ES 对外提供服务的端口;9300 是 ES 进行集群间通信与数据传输的端口,请确保这两个端口没有被占用。

第二步,下载 SkyWalking。

访问https://skywalking.apache.org/downloads/,下载最新版 SkyWalking 8.3.0,注意版本选择 v8.3.0 for ES7。

图片6.png

SkyWalking 下载页

下载完毕,解压缩文件得到 apache-skywalking-apm-bin-es7 目录。这里有个重要细节,SkyWalking 路径不要包含任何中文、特殊字符甚至是空格,否则启动时会报“找不到模板文件”的异常。

图片7.png

SkyWalking 目录

第三步,配置 SkyWalking 数据源。

SKyWalking 收集到的数据要被存储在 ElasticSearch 中,因此需要指定数据源。在 config 目录下找到 application.yml,这是 SkyWalking 的核心配置文件。

图片8.png

SkyWalking 核心配置文件

在配置文件 103 行附近可以看到 storage 配置片段。

storage:
  selector: ${SW_STORAGE:h2}
  elasticsearch: #ES6配置 
    ...
  elasticsearch7: #ES7配置
    nameSpace: ${SW_NAMESPACE:""}
    clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
    protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
    ...

默认 SkyWalking 采用内置 H2 数据库存储监控数据,现在需要改为 elasticsearch7,这样就完成了数据源存储的切换,在启动时 SkyWalking 会自动初始化 ES 的索引。

修改前:

selector: ${SW_STORAGE:h2}

修改后:

selector: ${SW_STORAGE:elasticsearch7}

到这里,SkyWalking 数据源配置成功。

第四步,启动 SkyWalking 应用。

在 bin 目录下找到 startup.bat 运行,如果是 Linux 系统运行 startup.sh。

图片9.png

SkyWalking 启动文件

启动后会产生两个 Java 进程:

  • Skywalking-Collector 是数据收集服务,默认监听 11800(gRPC)与 12800(HTTP) 端口。

  • Skywalking-Webapp 是 SkyWalking UI,用于展示数据,默认监听 8080 端口。

图片10.png

Skywalking 应用已启动

启动成功后,访问http://192.168.31.10:8080/,如果看到 SkyWalking UI 首页,则说明服务端配置成功。

图片11.png

SkyWalking UI 首页

到这里,SkyWalking 服务端启动完毕,下面咱们来说明如何通过 SkyWalking Java Agent 上报链路数据。

安装 SkyWalking Java Agent

在前面提到,SkyWalking 可以在不修改应用源码的前提下,无侵入的实现链路追踪与 JVM 指标监控,它是怎么做到的?这里涉及一个 Java1.5 新增的特性,Java Agent 探针技术,想必对于很多工作多年 Java 工程师来说,Java Agent 也是一个陌生的东西。

Java Agent 探针说白了就是 Java 提供的一种“外挂”技术,允许在应用开发的时候在通过启动时增加 javaagent 参数来外挂一些额外的程序。

Java Agent 并不复杂,其扩展类有这严格的规范,必须创建名为 premain 的方法,该方法将在目标应用 main 方法前执行,下面就是最简单的 Java Agent 扩展类。

public class SimpleAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("=========开始执行premain============");
    }
}

要完成 Java Agent,还需要提供正确的 MANIFEST.MF,以便 JVM 能够选择正确的类。在 META-INF 目录下找到你的 MANIFEST.MF 文件:

Manifest-Version: 1.0
Premain-Class: com.lagou.agent.SimpleAgent

之后我们将这个类打包为 agent.jar,假设原始应用为 oa.jar,在 oa.jar 启动时需要在额外附加 javaagent 参数,如下所示:

java -javaagent:agent.jar -jar oa.jar

在应用启动时 Java 控制台会输出如下日志。

=========开始执行 premain============
正在启动 OA 办公自动化系统...
....

通过结果你会发现 java agent 在目标应用main执行前先执行了premain,实现了不修改OA源码的前提下增加了新的功能。

SkyWalking 也是利用 Java Agent 的特性,在 premain 中通过字节码增强技术对目标方法进行扩展,当目标方法执行时自动收集链路追踪及监控数据并发往 SkyWalking 服务端。

下面咱们来讲解如何加载并使用 SkyWalking Java Agent,我们还是以实例进行讲解,因为 Java Agent 是无侵入的,并不需要源码,这里我就直接给出调用关系图帮助咱们理解。

图片12.png

调用关系图

简单介绍下,用户访问 a 服务的 a 接口,a 服务通过 OpenFeign 远程调用 b 服务的 b 接口,b 服务通过 OpenFeign 调用 c 服务的 c 接口,最后 c 接口通过 JDBC 将业务数据存储到 MySQL 数据库。

下面咱们演示 SkyWalking Java Agent 的用法,在 skywalking 的 agent 目录下存在 skywalking-agent.jar,这就是 skywalking 提供的 Java Agent 扩展类。

图片13.png

SkyWalking Java Agent

如果是生产环境下在启动应用时附加 javaagent 参数即可。

a 服务启动命令:

java -javaagent:D:\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar -Dskywalking.agent.service_name=a-service -Dskywalking.collector.backend_service=192.168.31.10:11800 -Dskywalking.logging.file_name=a-service-api.log -jar a-service.jar

b 服务启动命令:

java -javaagent:D:\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar -Dskywalking.agent.service_name=b-service -Dskywalking.collector.backend_service=192.168.31.10:11800 -Dskywalking.logging.file_name=b-service-api.log -jar b-service.jar

c 服务启动命令:

java -javaagent:D:\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar -Dskywalking.agent.service_name=c-service -Dskywalking.collector.backend_service=192.168.31.10:11800 -Dskywalking.logging.file_name=c-service-api.log -jar c-service.jar

如果是在 idea 开发环境运行,需要在 VM options 附加 javaagent。

图片14.png

IDEA 中使用 SkyWalking Java Agent

除了 javaagent 指定具体 agent 文件外,agent 本身也支持一系列配置参数,在刚才的启动时涉及 3 个。

  • skywalking.agent.service_name:指定在 SkyWalking 上报数据时的服务名。

  • skywalking.collector.backend_service:指定 SkyWalking 服务端的通信IP与端口。

  • skywalking.logging.file_name:指定 agent 生成的上报日志文件名,日志文件保存 agent 的 logs 目录中。

介绍 SkyWalking 常用视图

当服务启动后,为了演示需要,我利用 PostMan 对 a 接口模拟 10000次 用户访问,看 SkyWalking UI 中产生哪些变化。

图片15.png

PostMan 压力测试

此时访问http://192.168.31.10:8080/,打开 SKyWalking UI,默认显示全局的应用性能,具体用途我已在图中标出,其中我认为比较重要的是服务状态指数与高延迟端点列表两项,服务状态指数越接近 1 代表该服务运行状况越好,而高延迟端点列表则将处理延迟高的 API 端点列出,这可能是我们重点排查与优化的对象。

图片16.png

全局监控

除了全局监控外,SkyWalking 链路追踪的展示也非常友好,点击“拓扑”按钮可以查看访问拓扑图。服务间依赖关系一目了然。

图片17.png

拓扑图

除此之外,链路追踪的展示也非常强大,服务间的 API 调用关系与执行时间、调用状态清晰列出,而且因为 SkyWalking 是方法层面上的扩展,会提供更加详细的方法间的调用过程。

图片18.png

链路追踪图

图片19.png

提供不同维度的视图

SkyWalking 基于 Java Agent 对数据库的运行指标也进行收集,点击"database"便进入数据库指标监控。

图片20.png

数据库视图

如果你用过 SkyWalking 一定会被它简单的使用方法与强大的功能所折服,在SkyWalking提供了多达几十种不同维度、不同方式的数据展示方案,例如基于服务实例的JVM检测仪表盘就能让我们了解该服务 JVM 的资源分配过程,分析其中潜在的问题。

图片21.png

服务实例的 JVM 监控

JVM 监控

讲到这,咱们已经完成了 SkyWalking 的安装部署与应用接入,同时也对各种监控图表进行了介绍。因为篇幅有限,只能带着大家对 SkyWalking 进行入门讲解。当然 SKyWalking 也不是全能的,在生产环境下 SkyWalking 还需要额外考虑很多问题,如 SkyWalking 的集群管理、访问权限控制、自监控、风险预警等都要逐步完善,因此很多互联网公司也基于 SkyWalking 做二次开发以满足自身的需求,希望你也能在使用过程中对 SkyWalking 的潜力进行挖掘、了解。

小结与预告

本讲咱们学习了三方面内容,首先了解了 APM 与 SkyWalking 的作用;其次讲解了 SkyWalking 的部署过程与接入过程,介绍了 Java Agent 探针技术;最后对 SkyWalking UI 提供的各种图表进行了说明。

在这里我为你准备了一个有趣的讨论题:你的领导希望项目使用 Sleuth+Zipkin 实现链路追踪,而你作为架构师更希望引入 SkyWalking,你有什么办法在不得罪领导的前提下让他改变想法呢?这是所有架构师都要面对的问题,欢迎在评论区一起探讨。

下一讲,咱们开始一个新话题:在微服务(分布式)架构下如何保证数据一致性。


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐