SkyWalking全链路追踪(一)部署和初体验

2,710 阅读8分钟

前言

SkyWalking 是什么?

分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。 提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。

简单来说,SkyWalking是一款全链路追踪系统,可以视为OpenTracing的一种实现,类似的还有Zipkin、Jaeger等等,但是SkyWalking的接入方式采用了Java Agent的方式,达到了0代码无侵入,接入成本几乎为零。所以非常推荐使用。

部署

参考官方文档,简要的总结下DockerCompose的部署方式。

新建docker-compose.yaml文件

version: '3.8'
services:
  elasticsearch:
    image: elasticsearch:7.17.6
    container_name: elasticsearch
    ports:
      - "9200:9200"
    volumes:
      - ./esdata01:/usr/share/elasticsearch/data
    healthcheck:
      test: [ "CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1" ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1

  oap:
    image: apache/skywalking-oap-server:8.9.1
    container_name: oap
    depends_on:
      elasticsearch:
        condition: service_healthy
    links:
      - elasticsearch
    ports:
      - "11800:11800"
      - "12800:12800"
    healthcheck:
      test: [ "CMD-SHELL", "/skywalking/bin/swctl ch" ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    environment:
      SW_STORAGE: elasticsearch
      SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
      SW_HEALTH_CHECKER: default
      SW_TELEMETRY: prometheus
      JAVA_OPTS: "-Xms2048m -Xmx2048m"

  ui:
    image: apache/skywalking-ui:8.9.1
    container_name: ui
    depends_on:
      oap:
        condition: service_healthy
    links:
      - oap
    ports:
      - "8090:8080"
    environment:
      SW_OAP_ADDRESS: http://oap:12800

运行docker-compose命令

运行一下命令就可以启动SkyWalking,存储后端是Elasticsearch

docker-compose up -d
...
Container elasticsearch  Started
Container elasticsearch  Waiting
Container elasticsearch  Healthy
Container oap  Starting
Container oap  Started
Container oap  Waiting
Container oap  Healthy
Container ui  Starting
Container ui  Started

然后打开http://localhost:8090/

image.png 这样就部署完成了,是不是非常简单?

更换存储后端

SkyWalking官方推荐使用Elasticsearch作为存储后端,但是还支持其他的作为存储后端。具体可以参考:skyapm.github.io/document-cn…

原生支持的存储

  • H2
  • ElasticSearch 6, 7
  • MySQL
  • TiDB
  • InfluxDB

支持存储的重分发版本。

  • ElasticSearch 5

各个存储后端的配置如下,我们如果要更换,只需要配置docker-compose.yaml的环境变量即可

H2

H2是嵌入式数据库,一般测试使用,生产禁止使用

storage:
  selector: ${SW_STORAGE:h2}
  h2:
    driver: org.h2.jdbcx.JdbcDataSource
    url: jdbc:h2:mem:skywalking-oap-db
    user: sa

ElasticSearch

storage:
  selector: ${SW_STORAGE:elasticsearch}
  elasticsearch:
    # nameSpace: ${SW_NAMESPACE:""}
    user: ${SW_ES_USER:""} # User needs to be set when Http Basic authentication is enabled
    password: ${SW_ES_PASSWORD:""} # Password to be set when Http Basic authentication is enabled
    clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:443}
    trustStorePath: ${SW_SW_STORAGE_ES_SSL_JKS_PATH:"../es_keystore.jks"}
    trustStorePass: ${SW_SW_STORAGE_ES_SSL_JKS_PASS:""}
    protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"https"}
    indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:2}
    indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:0}
    # Batch process setting, refer to https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.5/java-docs-bulk-processor.html
    bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:2000} # Execute the bulk every 2000 requests
    bulkSize: ${SW_STORAGE_ES_BULK_SIZE:20} # flush the bulk every 20mb
    flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:10} # flush the bulk every 10 seconds whatever the number of requests
    concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requests
    advanced: ${SW_STORAGE_ES_ADVANCED:""}

MySQL

storage:
  selector: ${SW_STORAGE:mysql}
  mysql:
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/swtest"}
      dataSource.user: ${SW_DATA_SOURCE_USER:root}
      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root@1234}
      dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
      dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
      dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
      dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
    metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}

TiDB

storage:
  selector: ${SW_STORAGE:mysql}
  mysql:
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/swtest"}
      dataSource.user: ${SW_DATA_SOURCE_USER:root}
      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root@1234}
      dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
      dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
      dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
      dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
    metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}

InfluxDB

storage:
  selector: ${SW_STORAGE:influxdb}
  influxdb:
    url: ${SW_STORAGE_INFLUXDB_URL:http://localhost:8086}
    user: ${SW_STORAGE_INFLUXDB_USER:root}
    password: ${SW_STORAGE_INFLUXDB_PASSWORD:}
    database: ${SW_STORAGE_INFLUXDB_DATABASE:skywalking}
    actions: ${SW_STORAGE_INFLUXDB_ACTIONS:1000} # the number of actions to collect
    duration: ${SW_STORAGE_INFLUXDB_DURATION:1000} # the time to wait at most (milliseconds)
    fetchTaskLogMaxSize: ${SW_STORAGE_INFLUXDB_FETCH_TASK_LOG_MAX_SIZE:5000} # the max number of fetch task log in a request

InfluxDB举例替换存储后端

version: '3.8'
services:
  influxdb:
    image: bitnami/influxdb:1.8.5
    container_name: influxdb-server
    ports:
      - "8086:8086"
    environment:
      - INFLUXDB_ADMIN_USER_TOKEN=FvSo2szLLZ88qJrk
      - INFLUXDB_ADMIN_USER_PASSWORD=FvSo2szLLZ88qJrk
      - INFLUXDB_USER=gcdd
      - INFLUXDB_USER_PASSWORD=FvSo2szLLZ88qJrk
      - INFLUXDB_DB=skywalking
    volumes:
      - "./data:/bitnami/influxdb"

  oap:
    image: apache/skywalking-oap-server:8.9.1
    container_name: oap
    links:
      - influxdb
    ports:
      - "11800:11800"
      - "12800:12800"
    environment:
      SW_STORAGE: influxdb
      SW_STORAGE_INFLUXDB_URL: http://influxdb:8086
      SW_STORAGE_INFLUXDB_USER: admin
      SW_STORAGE_INFLUXDB_PASSWORD: FvSo2szLLZ88qJrk
      SW_HEALTH_CHECKER: default
      SW_TELEMETRY: prometheus
      JAVA_OPTS: "-Xms2048m -Xmx2048m"

  ui:
    image: apache/skywalking-ui:8.9.1
    container_name: ui
    links:
      - oap
    ports:
      - "8090:8080"
    environment:
      SW_OAP_ADDRESS: http://oap:12800

初体验

SkyWalking的UI做的还是非常可以的,美观且实用。

参考:APM-Skywalking UI使用全攻略

img

指标仪表盘

服务指标

点击仪表盘,选择要查询的应用,如“is-file-store”, 再切换仪表盘为“Service”模式,即可查询对应服务的指标

img

服务主要指标包括

  • ApdexScore: 性能指数,Apdex(Application Performance Index)是一个国际通用标准,Apdex 是用户对应用性能满意度的量化值。它提供了一个统一的测量和报告用户体验的方法,把最终用户的体验和应用性能作为一个完整的指标进行统一度量,其中最高为1最低为0;
  • ResponseTime:响应时间,即在选定时间内,服务所有请求的平均响应时间(ms);
  • Throughput: 吞吐量,即在选定时间内,每分钟服务响应的请求量(cpm)
  • SLA: service level agreement,服务等级协议,SW中特指每分钟内响应成功请求的占比。

大盘中会列出以上指标的当前的平均值,和历史走势。

服务慢端点 Service Slow Endpoint

服务指标仪表盘会列举出当前服务响应时间最大的端点Top5,如果有端点的响应时间过高,则需要进一步关注其指标(点击可以复制端点名称)。

img

运行中的实例 Running ServiceInstance

该服务目前所有实例的吞吐量情况,通过此可以推断出实例之间的负载情况。如果发现某个实例吞吐量较低,就需要查询实例指标(如查询该实例是不是发生了GC,或则CPU利用率过高)

img

端点指标

如果发现有端点的响应时间过高,可以进一步查询该端点的指标信息。和服务指标类似,端点指标也包括吞吐量、SLA、响应时间等指标,这里不再赘述。

端点仪表盘会有如下特有信息:

  1. Dependency Map: 依赖关系图,代表哪些服务在依赖(调用)该端点,如果是前端直接调用,会显示为用户(User)依赖中;
  2. Slow Traces: 即慢调用请求记录,SW会自动列出当前时间段内端点最慢的调用记录和TraceID,通过这个ID可以在追踪功能找到具体的调用链信息,便于定位。

img

服务实例指标

选择服务的实例并切换仪表盘,即可查看服务某个实例的指标数据。除了常规的吞吐量、SLA、响应时间等指标外,实例信息中还会给出JVM的信息,如堆栈使用量,GC耗时和次数等。

img

DB 数据指标查询

除了服务本身的指标,SW也监控了服务依赖的DB指标。切换DB指标盘并选择对应DB实例,就可以看到从服务角度(client)来看该DB实例的吞吐量、SLA、响应时间等指标。

更进一步,该DB执行慢SQL会被自动列出,可以直接粘贴出来,便于定位耗时原因。

img

拓扑结构

  • 不同于仪表盘来展示单一服务的指标,拓扑图是来展示服务和服务之间的依赖关系。
  • 用户可以选择单一服务查询,也可以将多个服务设定为一组同时查询。
  • 点击服务图片会自动显示当前的服务指标;
  • SW会根据请求数据,自动探测出依赖的服务,DB和中间件等。
  • 点击依赖线上的圆点,会显示服务之间的依赖情况,如每分钟吞吐量,平均延迟时间,和侦察端模式(client/Server)。

img

请求追踪

当用户发现服务的SLA降低,或者某个具体的端口响应时间上扬明显,可以使用追踪功能查询具体的请求记录。

  • 最上方为搜索区,用户可以指定搜索条件,如隶属于哪个服务、哪个实例、哪个端口,或者请求是成功还是失败;也可以根据上文提到的TraceID精确查询。
  • 整个调用链上每一个跨度的耗时和执行结果都会被列出(默认是列表,也可选择树形结构和表格的形式);
  • 如果有步骤失败,该步骤会标记为红色。

img

  • 点击跨度,会显示跨度详情,如果有异常发生,异常的种类、信息和堆栈都会被自动捕获;

img

  • 如果跨度为数据库操作,执行的SQL也会被自动记录。

img

性能剖析

追踪功能展示出的跨度是服务调用粒度的,如果要看应用实时的堆栈信息,可以选择性能剖析功能。

  • 新建分析任务;
  • 选指定的服务和端点作为分析对象;
  • 设定采样频率和次数;

注意: 如果端点的响应时间小于监控间隔,可能会导致采样分析失败。

img

新建任务后,SW将开始采集应用的实时堆栈信息。采样结束后,用户点击分析即可查看具体的堆栈信息。

  1. 点击跨度右侧的“查看”,可以看到调用链的具体详情;
  2. 跨度目录下方是SW收集到的具体进程堆栈信息和耗时情况。

img

需要提醒的时候,性能剖析功能因为要实时高频率收集服务的JVM堆栈信息,对于服务本身有一定的性能消耗,只适用于耗时端点的行为分析。

指标对比

当用户需要对比不同端点指标的关联情况的话,可以使用性能对比功能。选择待对比的端点和指标,SW将会列出相同时间段的指标记录。如下图中,两个端点虽然属于不同的应用,但是在响应时间的指标,表现出一定的关联性。实际上两个端点有依赖关系,一个响应时间变多,另一个也会变多。

img

参考资料