SkyWalking是分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8S、Mesos)架构而设计;本身也支持OpenTracing规范,优秀的设计提供了良好的扩展性,更支持Java、PHP、.Net、NodeJs等多种探针。
SkyWalking是观察性分析平台和应用性能管理系统。提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。
Skywalking架构模型

整个系统分为三部分:
- agent:采集tracing(调用链数据)和metric(指标)信息并上报
- OAP(Observability Analysis Platform):收集tracing和metric信息通过analysis core模块将数据放入持久化容器中(ES,H2(内存数据库),mysql等等),并进行二次统计和监控告警
- webapp:前后端分离,前端负责呈现,并将查询请求封装为graphQL提交给后端,后端通过ribbon做负载均衡转发给OAP集群,再将查询结果渲染展示
Skywalking也提供了其他的一些特性:
- 配置重载:支持通过jvm参数覆写默认配置,支持动态配置管理
- 集群管理:这个主要体现在OAP,通过集群部署分担数据上报的流量压力和二次计算的计算压力,同时集群也可以通过配置切换角色,分别面向数据采集(collector)和计算(aggregator,alarm),需要注意的是agent目前不支持多collector负载均衡,而是随机从集群中选择一个实例进行数据上报
- 支持k8s和mesh
- 支持数据容器的扩展,例如官方主推是ES,通过扩展接口,也可以实现插件去支持其他的数据容器
- 支持数据上报receiver的扩展,例如目前主要是支持gRPC接受agent的上报,但是也可以实现插件支持其他类型的数据上报(官方默认实现了对Zipkin,telemetry和envoy的支持)
- 支持客户端采样和服务端采样,不过服务端采样最有意义
- 官方制定了一个数据查询脚本规范:OAL(Observability Analysis Language),语法类似Linq,以简化数据查询扩展的工作量
- 支持监控预警,通过OAL获取数据指标和阈值进行对比来触发告警,支持webhook扩展告警方式,支持统计周期的自定义,以及告警静默防止重复告警
数据结构
如果说数据容器决定了上限,那么数据结构则决定了实际到达的高度。Skywalking的数据结构主要为:
- 数据维度(ES索引为skywalking_*_inventory)
- service:服务
- instance:实例
- endpoint:接口
- network_adress:外部依赖
- 数据内容
- 原始数据
- 调用链跟踪数据(调用链的trace信息,ES索引为skywalking_segment,Skywalking主要的数据消耗都在这里)
- 指标(主要是jvm或者envoy的运行时指标,例如ES索引skywalking_instance_jvm_cpu)
- 二次统计指标
- 指标(按维度/时间二次统计出来的例如pxx、sla等指标,例如ES索引skywalking_database_access_p75_month)
- 数据库慢查询记录(数据库索引:skywalking_top_n_database_statement)
- 关联关系(维度/指标之间的关联关系,ES索引为skywalking_relation)
- 特别记录
- 告警信息(ES索引为skywalking_alarm_record)
- 并发控制(ES索引为skywalking_register_lock)
其中数量占比最大的就是调用链跟踪数据和各种指标,而这些数据均可以通过OAP设置过期时间,以降低历史数据的对磁盘占用和查询效率的影响。
基于docker搭建Skywalking
创建skywalking网络(用于个模块间的内部通信,网络名可以是任意名字,这里使用:skywalkingnet这个名字)
docker network create skywalkingnet
创建存放es数据的文件夹,并创建es容器:
mkdir -p data/elasticsearch/data # 容器以es7为别名,加入到了skywalkingnet网络中 docker run -d --name=es7 --network skywalkingnet --network-alias es7 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -v /Users/allen/dev/skywalking-demo/data/elasticsearch/data:/usr/share/elasticsearch/data elasticsearch:7.5.1
创建skywalking-oap-server容器:
# 容器以oap为别名,加入到skywalkingnet网络,且使用前面的es7作为数据源 docker run --name skywalking-oap --network skywalkingnet --network-alias oap -d -e TZ=Asia/Shanghai -p 12800:12800 -p 11800:11800 -e SW_STORAGE=elasticsearch7 -e SW_STORAGE_ES_CLUSTER_NODES=es7:9200 apache/skywalking-oap-server:8.3.0-es7
创建webapp容器:
# 容器以ui为别名,加入到skywalkingnet网络,且连接到前面创建的oap docker run -d --name skywalking-ui --network skywalkingnet --network-alias ui -e TZ=Asia/Shanghai -p 8088:8080 -e SW_OAP_ADDRESS=http://oap:12800 apache/skywalking-ui:8.3.0
Web页面集成:
初始化项目(npm)
npm init # 一路enter......... npm install skywalking-client-js --save npm install webpack --save-dev
webpack.config.js
module.exports = { mode: 'development', entry: './index.js', output: { filename: 'app.js' } };
index.js
import ClientMonitor from 'skywalking-client-js'; // Report collected data to `http:// + window.location.host // + /browser/perfData` in default ClientMonitor.register({ collector: 'http://127.0.0.1:8089',// 这里使用的nignx转发端口 service: 'my-test-app', pagePath: window.location.href, serviceVersion: '1.0.0', // 应用程序版本号 });
webpack打包,生成dist/app.js
webpack
index.html
<html> <script src="dist/app.js"> <body> ..... </body> </html>
nginx 转发规则配置 (主要是增加HTTP response header, 解决前端跨域接口请求问题)
/etc/nginx/conf.d/skywalking.conf
server { listen 8098; location / { # 部分浏览器安全策略问题,直接填 * 来进行通配已经不行 add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Allow-Headers "Authorization,Content-Type"; add_header Access-Control-Allow-Credentials "true"; # 如果是OPTIONS请求,则直接返回 if ($request_method = OPTIONS ) { return 200; } proxy_pass http://localhost:12800; } }
浏览器访问index.html, 稍等片刻,即可看到浏览器发送了skywalking请求,上报性能数据:

在浏览器console中请求一个不存在的HTTP API来触发一个错误后,skywalking也会上报这个错误:
axios.get('/unknow-api')

Skywalking HTTP API:
skywalking/Browser-HTTP-API-Protocol.md at master · apache/skywalking · GitHub