链路追踪Skywalking应用实战 2

本文涉及的产品
可观测链路 OpenTelemetry 版,每月50GB免费额度
简介: 链路追踪Skywalking应用实战

4.2 Rocketbot-拓扑图

【拓扑图】展示当前整个业务服务的拓扑图。点击拓扑图中的任意节点,可以看到服务相应的状态信息,其中包括响应的平均耗时、SLA 等监控信息。点击拓扑图中任意一条边,还可以看到一条调用链路的监控信息,其中会分别从客户端(上游调用方)和服务端(下游接收方)来观测这条调用链路的状态,其中展示了该条链路的耗时、吞吐量、SLA 等信息。

4.3 追踪

【追踪】主要用来查询 Trace 信息,如下图所示。在①处可以选择 Trace 的查询条件,其中可以指定 Trace 涉及到的 Service、ServiceInstance、Endpoint 以及Trace 的状态继续模糊查询,还可以指定 TraceId 和时间范围进行精确查询。在②处可以直接根据请求连接查找调用链路信息。在③处展示了 Trace 的简略信息。在④处可以选择不同的方式展示追踪信息。在这里,我们不仅能看到调用链路信息,还能看到MySQL操作监控,如下图:

错误异常信息也能追踪,如下图:


4.4 性能分析

在传统的监控系统中,我们如果想要得知系统中的业务是否正常,会采用进程监控、日志收集分析等方式来对系统进行监控。当机器或者服务出现问题时,则会触发告警及时通知负责人。通过这种方式,我们可以得知具体哪些服务出现了问题。但是这时我们并不能得知具体的错误原因出在了哪里,开发人员或者运维人员需要到日志系统里面查看错误日志,甚至需要到真实的业务服务器上查看执行情况来解决问题。


如此一来,仅仅是发现问题的阶段,可能就会耗费相当长的时间;另外,发现问题但是并不能追溯到问题产生具体原因的情况,也常有发生。这样反反复复极其耗费时间和精力,为此我们便有了基于分布式追踪的APM系统。


通过将业务系统接入分布式追踪中,我们就像是给程序增加了一个放大镜功能,可以清晰看到真实业务请求的整体链路,包括请求时间、请求路径,甚至是操作数据库的语句都可以看得一清二楚。通过这种方式,我们结合告警便可以快速追踪到真实用户请求的完整链路信息,并且这些数据信息完全是持久化的,可以随时进行查询,复盘错误的原因。


然而随着我们对服务监控理解的加深,我们发现事情并没有那么简单。在分布式链路追踪中我们有这样的两个流派:代码埋点和字节码增强。无论使用哪种方式,底层逻辑一定都逃不过面向切面这个基础逻辑。因为只有这样才可以做到大面积的使用。这也就决定了它只能做到框架级别和RPC粒度的监控。这时我们可能依旧会遇到程序执行缓慢或者响应时间不稳定等情况,但无法具体查询到原因。这时候,大家很自然的会考虑到增加埋点粒度,比如对所有的Spring Bean方法、甚至主要的业务层方法都加上埋点。但是这种思路会遇到不小的挑战:


第一,增加埋点时系统开销大,埋点覆盖不够全面。通过这种方式我们确实可以做到具体业务场景具体分析。但随着业务不断迭代上线,弊端也很明显:大量的埋点无疑会加大系统资源的开销,造成CPU、内存使用率增加,更有可能拖慢整个链路的执行效率。虽然每个埋点消耗的性能很小,在微秒级别,但是因为数量的增加,甚至因为业务代码重用造成重复埋点或者循环使用,此时的性能开销已经无法忽略。


第二,动态埋点作为一项埋点技术,和手动埋点的性能消耗上十分类似,只是减少的代码修改量,但是因为通用技术的特别,上一个挑战中提到的循环埋点和重复使用的场景甚至更为严重。比如选择所有方法或者特定包下的所有方法埋点,很可能造成系统性能彻底崩溃。


第三,即使我们通过合理设计和埋点,解决了上述问题,但是JDK函数是广泛使用的,我们很难限制对JDK API的使用场景。对JDK过多方法、特别是非RPC方法的监控会造成系统的巨大延迟风险。而且有一些基础类型和底层工具类,是很难通过字节码进行增强的。当我们的SDK使用不当或者出现bug时,我们无法具体得知真实的错误原因。Skywalking中可以使用性能剖析分析特定端点的性能,我们需要先创建一个监控任务:

新建任务后,在右侧可以查看任务性能分析报表,还可以点击分析线程栈信息,如下图:

4.5 告警

SkyWalking 告警功能是在6.x版本新增的,其核心由一组规则驱动,这些规则定义在config/alarm-settings.yml文件中。 告警的定义分为两部分:

  1. 告警规则:它们定义了应该如何触发度量警报,应该考虑什么条件。
  2. Webhook(网络钩子):定义当警告触发时,哪些服务终端需要被告知

4.5.1 警告规则详解

Skywalking每隔一段时间根据收集到的链路追踪的数据和配置的告警规则(如服务响应时间、服务响应时间百分比)等,判断如果达到阈值则发送相应的告警信息。发送告警信息是通过调用webhook接口完成,具体的webhook接口可以使用者自行定义,从而开发者可以在指定的webhook接口中编写各种告警方式,比如邮件、短信等。告警的信息也可以在RocketBot中查看到。


我们可以进入到Skywalking容器中,再进入到config文件夹下就可以看到alarm-settings.yml,如下图:

SkyWalking 的发行版都会默认提供config/alarm-settings.yml文件,里面预先定义了一些常用的告警规则。如下:

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.
# Sample alarm rules.
rules:
  # Rule unique name, must be ended with `_rule`.
  service_resp_time_rule:
    metrics-name: service_resp_time
    op: ">"
    threshold: 1000
    period: 10
    count: 3
    silence-period: 5
    message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
  service_sla_rule:
    # Metrics value need to be long, double or int
    metrics-name: service_sla
    op: "<"
    threshold: 8000
    # The length of time to evaluate the metrics
    period: 10
    # How many times after the metrics match the condition, will trigger alarm
    count: 2
    # How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
    silence-period: 3
    message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
  service_resp_time_percentile_rule:
    # Metrics value need to be long, double or int
    metrics-name: service_percentile
    op: ">"
    threshold: 1000,1000,1000,1000,1000
    period: 10
    count: 3
    silence-period: 5
    message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
  service_instance_resp_time_rule:
    metrics-name: service_instance_resp_time
    op: ">"
    threshold: 1000
    period: 10
    count: 2
    silence-period: 5
    message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
#  Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
#  Because the number of endpoint is much more than service and instance.
#
#  endpoint_avg_rule:
#    metrics-name: endpoint_avg
#    op: ">"
#    threshold: 1000
#    period: 10
#    count: 2
#    silence-period: 5
#    message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes
webhooks:
#  - http://127.0.0.1/notify/
#  - http://127.0.0.1/go-wechat/

告警规则配置项的说明:


**Rule name:**规则名称,也是在告警信息中显示的唯一名称。必须以_rule结尾,前缀可自定义

**Metrics name:**度量名称,取值为oal脚本中的度量名,目前只支持long、double和int类型。

**Include names:**该规则作用于哪些实体名称,比如服务名,终端名(可选,默认为全部)

**Exclude names:**该规则作不用于哪些实体名称,比如服务名,终端名(可选,默认为空)

**Threshold:**阈值

OP: 操作符,目前支持 >、<、=

**Period:**多久告警规则需要被核实一下。这是一个时间窗口,与后端部署环境时间相匹配

**Count:**在一个Period窗口中,如果values超过Threshold值(按op),达到Count值,需要发送警报

**Silence period:**在时间N中触发报警后,在TN -> TN + period这个阶段不告警。 默认情况下,它和Period一样,这意味着相同的告警(在同一个Metrics name拥有相同的Id)在同一个Period内只会触发一次

**message:**告警消息

在配置文件中预先定义的告警规则总结如下:


在过去10分钟内服务平均响应时间超过1秒达3次

在过去10分钟内服务成功率低于80%达2次

在过去10分钟内服务90%响应时间低于1秒达3次

在过去10分钟内服务的响应时间超过1秒达2次

在过去10分钟内端点的响应时间超过1秒达2次

这些警告信息最终会在Skywalking-UI上展示,效果如下:

4.5.2 Webhook规则

Webhook配置其实是警告消息接收回调处理,我们可以在程序中写一个方法接收警告信息,Skywalking会以application/json格式通过http请求发送,消息格式声明为:List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage。


字段如下:


scopeId, scope: 所有的scope实体在 org.apache.skywalking.oap.server.core.source.DefaultScopeDefine 里面声明。

name. 目标scope实体名称。

id0: scope实体ID,匹配名称。

id1: 不使用。

ruleName: 配置在 alarm-settings.yml 里面的规则名称.

alarmMessage: 告警信息.

startTime:触发告警的时间 示例:

[
  {
    "scopeId": 2,
    "scope": "SERVICE_INSTANCE",
    "name": "c00158f28efc45cd813e21b6b8848a3a@192.168.1.104 of hailtaxi-driver",
    "id0": "aGFpbHpdmVy.1_YzAwMAMTkyLjE2OC4xLjEwNA\u003d\u003d",
    "id1": "",
    "ruleName": "service_instance_resp_time_rule",
    "alarmMessage": "Response time of service instance c00158f28efc45cd813e21b6b8848a3a@192.168.1.104 of hailtaxi-driver is more than 1000ms in 2 minutes of last 10 minutes",
    "startTime": 1611612258056
  }
]

4.5.3 自定义Webhook消息接收

我们按照如下步骤,可以在自己程序中接收警告信息:

1)定义消息接收对象

hailtaxi-api中创建com.itheima.skywalking.model.AlarmMessage,代码如下:

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class AlarmMessage {
    private int scopeId;
    private String name;
    private String id0;
    private String id1;
    private String alarmMessage;
    private long startTime;
    String ruleName;
}

2)接收警告方法创建

hailtaxi-driver中创建com.itheima.driver.controller.AlarmMessageController用于接收警告消息,代码如下:

一般情况下,这种接收告警的api会被放置在比较清闲的后台服务中!!!

@RestController
@RequestMapping(value = "/skywalking")
public class AlarmMessageController {
    /***
     * 接收警告信息
     * @param alarmMessageList
     */
    @PostMapping("/webhook")
    public void webhook(@RequestBody List<AlarmMessage> alarmMessageList) {
        for (AlarmMessage alarmMessage : alarmMessageList) {
            System.out.println("webhook:"+alarmMessage);
        }
    }
}

3)修改Webhook地址

修改alarm-settings.yml中的webhook地址:

webhooks:
#  - http://127.0.0.1/notify/
#  - http://127.0.0.1/go-wechat/
   - http://192.168.200.10:8001/driver/skywalking/webhook

因为skywalking默认有一个告警规则:10分钟内服务成功率低于80%超过2次

所以为了能演示出告警效果,我们在hailtaxi-driver项目中的driver/info接口中添加一个一句话

/****
   * 司机信息
   */
  //@GetMapping(value = "/info/{id}")
  @RequestMapping(value = "/info/{id}")
  public Driver info(@PathVariable(value = "id")String id,HttpServletRequest request){
      int i = 1/ 0; // 产生异常
      Enumeration<String> headerNames = request.getHeaderNames();
      while (headerNames.hasMoreElements()){
          String name = headerNames.nextElement();
          String value = request.getHeader(name);
          System.out.println(name+":"+value);
          System.out.println("--------------------------");
      }
      return driverService.findById(id);
  }

测试时将网关的条件断言给注释一下!!!

此时我们程序中就能接收警告信息了。

相关实践学习
基于OpenTelemetry构建全链路追踪与监控
本实验将带领您快速上手可观测链路OpenTelemetry版,包括部署并接入多语言应用、体验TraceId自动注入至日志以实现调用链与日志的关联查询、以及切换调用链透传协议以满足全链路打通的需求。
分布式链路追踪Skywalking
Skywalking是一个基于分布式跟踪的应用程序性能监控系统,用于从服务和云原生等基础设施中收集、分析、聚合以及可视化数据,提供了一种简便的方式来清晰地观测分布式系统,具有分布式追踪、性能指标分析、应用和服务依赖分析等功能。 分布式追踪系统发展很快,种类繁多,给我们带来很大的方便。但在数据采集过程中,有时需要侵入用户代码,并且不同系统的 API 并不兼容,这就导致了如果希望切换追踪系统,往往会带来较大改动。OpenTracing为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范。OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。Skywalking基于OpenTracing规范开发,具有性能好,支持多语言探针,无侵入性等优势,可以帮助我们准确快速的定位到线上故障和性能瓶颈。 在本套课程中,我们将全面的讲解Skywalking相关的知识。从APM系统、分布式调用链等基础概念的学习加深对Skywalking的理解,从0开始搭建一套完整的Skywalking环境,学会对各类应用进行监控,学习Skywalking常用插件。Skywalking原理章节中,将会对Skywalking使用的agent探针技术进行深度剖析,除此之外还会对OpenTracing规范作整体上的介绍。通过对本套课程的学习,不止能学会如何使用Skywalking,还将对其底层原理和分布式架构有更深的理解。本课程由黑马程序员提供。
目录
相关文章
|
存储 运维 监控
链路追踪Skywalking快速入门1
链路追踪Skywalking快速入门1
275 1
|
4月前
|
监控 Kubernetes Go
全链路追踪 & 性能监控,GO 应用可观测全面升级
当前,大多数面向 Golang 应用的监控能力主要是通过 SDK 方式接入,需要开放人员手动进行埋点,会存在一定问题。对此,可观测 Go Agent 应运而生。本文介绍的阿里云可观测 Go Agent 方案,能通过无侵入的方式实现应用监控能力。
108669 24
|
6月前
|
Java 微服务
skywalking链路追踪时忽略指定异常
skywalking链路追踪时忽略指定异常
|
6月前
|
Java 微服务
skywalking全链路追踪
skywalking全链路追踪
|
监控 Java BI
链路追踪Skywalking应用实战 1
链路追踪Skywalking应用实战
283 0
|
存储 监控 Java
链路追踪Skywalking快速入门2
链路追踪Skywalking快速入门2
272 0
|
Apache
skywalking04 - skywalking自定义链路追踪@Trace
skywalking04 - skywalking自定义链路追踪@Trace
479 0
|
存储 监控 NoSQL
【微服务】分布式如何利用Skywalking实现链路追踪与监控?
微服务下的分布式如何实现链路追踪和监控。
976 1
【微服务】分布式如何利用Skywalking实现链路追踪与监控?
|
存储 监控 Java
链路追踪自从用了SkyWalking,睡的真香!
链路追踪自从用了SkyWalking,睡的真香!
|
3月前
|
存储 监控 开发者
分布式链路监控系统问题之系统拆分后链路追踪技术的问题如何解决
分布式链路监控系统问题之系统拆分后链路追踪技术的问题如何解决
下一篇
无影云桌面