1、SkyWalking的核心概念
1.1 概述
2015年由个人吴晟(华为开发者)开源 , 2017年加入Apache孵化器
分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。
SkyWalking 是观察性分析平台和应用性能管理系统。
提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案.
1.2 架构
SkyWalking 逻辑上分为四部分: 探针, 平台后端, 存储和用户界面.
- 探针基于不同的来源可能是不一样的, 但作用都是收集数据, 将数据格式化为 SkyWalking 适用的格式.
- 平台后端是一个支持集群模式运行的后台, 用于数据聚合, 数据分析以及驱动数据流从探针到用户界面的流程. 平台后端还提供了各种可插拔的能力, 如不同来源数据(如来自 Zipkin)格式化, 不同存储系统以及集群管理. 你甚至还可以使用Observability Analysis Language来进行自定义聚合分析.
- 存储是开放式的. 你可以选择一个既有的存储系统, 如 ElasticSearch, H2 或 MySQL 集群(Sharding-Sphere 管理)
- 用户界面对于 SkyWalking 的最终用户来说非常炫酷且强大. 同样它也是可定制以匹配你已存在的后端的. 使用Graphql查询数据
2、为什么要用SkyWalking?
SkyWalking 提供了在很多不同的场景下用于观察和监控分布式系统的方式。首先,像传统的方法,skywalking为java,c#,Node.js等提供了自动探针代理.同时,它为Go,C++提供了手工探针。随着本地服务越来越多,需要越来越多的语言,掌控代码的风险也在增加,Skywalking可以使用网状服务探针收集数据,以了解整个分布式系统。通常,skywalking提供了观察service,service instance,endpoint的能力。
service: 一个服务
Service Instance: 服务的实例(1个服务会启动多个节点)
Endpoint: 一个服务中的其中一个接口
zipkin | pinpoint | skywalking | cat | |
---|---|---|---|---|
依赖 | Java 6,7,8 Maven3.2+ rabbitMQ | Java 6,7,8 maven3+ Hbase0.94+ | Java 6,7,8 maven3.0+ nodejs zookeeper elasticsearch | Java 6,7,8 Maven 3.2.3+ mysql5.6 Linux 2.6以及之上(2.6内核才可以支持epoll |
实现方式 | 拦截请求,发送(http,mq)数据至zipkin服务 | java探针,字节码增强 | java探针,字节码增强 | 代码埋点(拦截器,注解,过滤器等) |
颗粒度 | 接口级 | 方法级 | 方法级 | 代码级 |
存储选择 | In-memory,mysql,cassandra,elasticsearch | Hbase | Elasticsearch,h2,mysql | Mysql,hdfs |
MQ监控 | 不支持 | 不支持 | 支持 | 不支持 |
报警 | 不支持 | 支持 | 支持 | 支持 |
Jvm监控 | 不支持 | 支持 | 支持 | 不支持 |
使用公司 | Twiter | Naver | 华为,alibaba cloud,天源迪科,当当网,京东金融 | 大众点评,携程,陆金所,同程旅游,猎聘网,拼多多 |
3、如何使用?
3.1 下载
wget http://mirror.bit.edu.cn/apache/skywalking/6.5.0/apache-skywalking-apm-6.5.0.tar.gz
tar xvf apache-skywalking-apm-6.5.0.tar.gz
3.2 SkyWalking目录结构
agent:本地代理模块(探针)
bin:后台、ui启动脚本
config:收集器配置脚本
logs:日志
oap-libs:依赖jar包
webapp:数据展示ui服务
3.3 SkyWalking Collector配置
OAP(Collector)链路数据归集器,主要用于数据落地,OAP配置文件为/config/application.yml,配置如下:
#仅截取需要修改部分代码、storage下有3中选择elasticsearch、h2、mysql
这里使用mysql,修改jdbcurl、user、password
storage:
# elasticsearch:
# nameSpace: ${SW_NAMESPACE:""}
# clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
# protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
# trustStorePath: ${SW_SW_STORAGE_ES_SSL_JKS_PATH:"../es_keystore.jks"}
# trustStorePass: ${SW_SW_STORAGE_ES_SSL_JKS_PASS:""}
# user: ${SW_ES_USER:""}
# password: ${SW_ES_PASSWORD:""}
# indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:2}
# indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:0}
# # Those data TTL settings will override the same settings in core module.
# recordDataTTL: ${SW_STORAGE_ES_RECORD_DATA_TTL:7} # Unit is day
# otherMetricsDataTTL: ${SW_STORAGE_ES_OTHER_METRIC_DATA_TTL:45} # Unit is day
# monthMetricsDataTTL: ${SW_STORAGE_ES_MONTH_METRIC_DATA_TTL:18} # Unit is month
# # 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:1000} # Execute the bulk every 1000 requests
# 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
# resultWindowMaxSize: ${SW_STORAGE_ES_QUERY_MAX_WINDOW_SIZE:10000}
# metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}
# segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}
# h2:
# driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
# url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db}
# user: ${SW_STORAGE_H2_USER:sa}
# metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}
mysql:
properties:
jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/tim?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false"}
dataSource.user: ${SW_DATA_SOURCE_USER:root}
dataSource.password: ${SW_DATA_SOURCE_PASSWORD:123456}
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}
mysql 驱动包放入oap-libs中
3.4 SkyWalking Agent 配置
Skywalking 的 Agent 主要用于收集和发送数据到 OAP(Collector),因此需要进行配置 Skywalking OAP(Collector)的地址,Agent 的配置文件地址为 /agent/config/agent.config,配置如下:
# 设置Agent命名空间,它用来隔离追踪和监控数据,当两个应用使用不同的名称空间时,跨进程传播链会中断。
#agent.namespace=${SW_AGENT_NAMESPACE:default-namespace}
# 设置服务名称,会在 Skywalking UI 上显示的名称
agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
# 忽略监控的url
trace.ignore_path=/eureka/**
# 每 3秒采集的样本跟踪比例,如果是负数则表示 100%采集
agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:-1}
# 启用 Debug ,如果为 true 则将把所有检测到的类文件保存在"/debug"文件夹中
# agent.is_open_debugging_class = ${SW_AGENT_OPEN_DEBUG:true}
# 后端的 collector 端口及地址
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
# 日志级别
logging.level=${SW_LOGGING_LEVEL:DEBUG}
其他配置详见https://github.com/apache/skywalking/blob/master/docs/en/setup/service-agent/java-agent/README.md
3.5 SkyWalking webApp配置
Skywalking 的 WebApp 主要是用来展示落地的数据,因此只需要配置 Web 的端口及获取数据的 OAP(Collector)的IP和端口,webApp 配置文件地址为 /webapp/webapp.yml 配置如下:
# 监听端口
server:
port: 8080
# 后台连接信息
collector:
path: /graphql
ribbon:
# ReadTimeout默认10秒,可能超时,适当加长
ReadTimeout: 60000
# Point to all backend's restHost:restPort, split by ,
# 指向后端所有的collector 的 restHost:restPort,多个使用,分开
listOfServers: 127.0.0.1:12800
3.6 启动 /bin
SkyWalking 的启动包括两部分,一个是 SkyWalking Collector(oapService) ,一个是 SkyWalking UI(webappService)
SkyWalking 解压后的 bin 目录:
bat 为 windows 环境使用,sh 为 linux 环境使用,我们可以分别启动 oapService 和 webappService,也可以通过 startup 一
次性全部启动,从 startup 中的命令可以知道其实就是分别启动 oapService 和 webappService。
如果一切顺利,这时候就可以通过 http://localhost:8080 来查看 SkyWalking UI 了
4、SkyWalking 告警配置
4.1 skywalking发送告警的基本原理
skywalking每隔一段时间轮询skywalking-collector收集到的链路追踪的数据,再根据所配置的告警规则(如服务响应时间、服务响应时间百分比)等,如果达到阈值则发送响应的告警信息。发送告警信息是以线程池异步的方式调用webhook接口完成,(具体的webhook接口可以使用者自行定义),从而开发者可以在指定的webhook接口中自行编写各种告警方式,钉钉告警、邮件告警等等。
4.2 告警配置
开启skywalking相关告警配置,编辑 config/alarm-settings.yml,打开之后如下所示:
# Sample alarm rules.
rules:
# 规则名称不能重复,且必须以`_rule`结尾.
service_resp_time_rule:
# 指定的规则(与规则名不同,这里是对应的告警中的规则map)official_analysis.oal
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_p90_sla_rule:
# Metrics value need to be long, double or int
metrics-name: service_p90
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: 90% response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes
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
# webhook接口url的定义,除了规则制定之外,还有达到告警规则后,需要skywalking调
# 用的webhook接口
webhooks:
- http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
4.3 告警Webhook接口对接
Webhook要求使用web容器对接。警报消息将通过HTTP post按应用程序/json内容类型发送。JSON格式基于List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>。警报消息与以下关键信息。
- scopeId, scope. 告警的范围类型、源码中有定义常量 org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.
- name. 告警服务名称
- id0. 服务名称对应的ID
- id1. Not used today.
- ruleName. 告警消息名称
- alarmMessage. 告警消息内容
- startTime. 时间戳:毫秒
Example as following
[{
"scopeId": 1,
"scope": "SERVICE",
"name": "serviceA",
"id0": 12,
"id1": 0,
"ruleName": "service_resp_time_rule",
"alarmMessage": "alarmMessage xxxx",
"startTime": 1560524171000
}, {
"scopeId": 1,
"scope": "SERVICE",
"name": "serviceB",
"id0": 23,
"id1": 0,
"ruleName": "service_resp_time_rule",
"alarmMessage": "alarmMessage yyy",
"startTime": 1560524171000
}]