借助 skywalking 搭建自己的 APM 数据展示平台

SkyWalking: an APM(application performance monitor) system, especially designed for microservices, cloud native and container-based (Docker, Kubernetes, Mesos) architectures.

skywaking(本文后续简称 SW) 在如今的 APM 体系建设中逐渐展露头角,国内几乎所有的一线大厂都借助 skywaling 进行了自己的 APM 体系建设。
大厂的建设方案在诸多的大会中都有提及,尤其在刚过去的 《Apache SkyWalking DevCon 2020》,更是带来了诸多的精彩分享。

本文不会就 APM 架构或理论进行详细阐述,更多聚焦在实战环节,围绕下述几点展开:

  1. 分析 SW 架构,确定接入方案
  2. 如何在本地调式官方的 UI 项目
  3. 快速了解 SW 查询协议 GraphQL

Skywalking 架构简介,寻找接入点

几个官方库

在正式分析之前,我们来看下 SW 比较重要的三个官方项目

SW 查询协议 —— 获取数据的桥梁

接下来,我们看下主库的架构图,即 SW 体系的整体架构图:

我们关注的 UI 接入部分,在图的左上角,其中 UI 和 CLI 通过查询协议来和 SW 的后端服务进行交互。正如查询协议库所说:

Query Protocol defines the communication protocol in query stage.
SkyWalking native UI and CLI use this protocol to fetch data from the backend consistently, don’t need to worry about the backend update.

其中重点我们加粗表示了,即:SW 的官方 UI 和 CLI 工具都是通过查询协议和后端服务进行数据交互。

SW 的查询协议通俗简单的理解:定义了一系列 GraphQL 查询定义。甚至可以进一步粗暴的理解,就是一堆定义好的 HTTP API。所以只要了解官方的 API 定义,即可发挥 SW 的数据宝藏威力,
打造属于自己的 APM 展示平台。

快速搭建的第一步,就是参考官方的 UI 项目,一方面我们可以参考它的 UI 组件实现。另一方面,我们可以抓包,参考它的 GraphQL 请求。

官网项目本地调试

本地运行一览

1
2
3
4
5
# 设置后端的请求地址为 SW 官方的北京机房演示地址
➜ skywalking-rocketbot-ui git:(master) export SW_PROXY_TARGET=http://122.112.182.72:8080/

# 启动服务,之后访问 8080 端口
➜ skywalking-rocketbot-ui git:(master) npm run serve

访问 http://localhost:8080/topology

我们看到,服务已成功在本地运行,且可以通过 VueDev Tools 来查看对应的组件实现和传值。对我们自己去实现对应的显示组件,提供了极高的参考意义。

关于如何这个环境变量的设置,大家可以顺着 packages.json 去捋一下 run server 的整个流程

服务抓包格式化

我们还是以这个拓扑为例,抓一个包,简单看下 GraphQL 请求

requestPayload
1
2
3
4
5
6
7
8
9
10
11
{
"query": "query queryTopo($duration: Duration!) {\n topo: getGlobalTopology(duration: $duration) {\n nodes {\n id\n name\n type\n isReal\n }\n calls {\n id\n source\n detectPoints\n target\n }\n }}",
"variables": {
"serviceId": 0,
"duration": {
"start": "2020-11-27 0912",
"end": "2020-11-27 0927",
"step": "MINUTE"
}
}
}

我们进一步格式化 graphQL 的 query 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
query queryTopo($duration: Duration!) {
topo: getGlobalTopology(duration: $duration) {
nodes {
id
name
type
isReal
}
calls {
id
source
detectPoints
target
}
}
}

格式化过后,更方便我们进行对应分析。

分析查询协议

快速了解查询语句含义

GraphQL 的更多用法,本文不提及。文本就上述抓到的协议进行简单说明,便于之前不了解 GraphQL 的同学能够快速了解 SW 查询协议。

  1. 查看 Query,确定查询语句,其中 $ 开头的就是形参,在 variables 里会具体传值
  2. 那上述例子,$duration 的具体值,就是
    1
    2
    3
    4
    5
    {
    "start": "2020-11-27 0912",
    "end": "2020-11-27 0927",
    "step": "MINUTE"
    }

那问题来了,我怎么知道 $duration 是由 start end step 组成?他们的值类型是什么?在哪里定义?这就要看之前我们提到的 SW 查询协议。

查询协议

接着上面的分析,我们去查看 SW 的 Query Protocol.

到这里大家看到,其实 Query Protocol 就是查询的定义,标准。就像我们平时开发中接触的后端标准接口一样。大家在接触这些看似
高大上的 Query Protocol 时,不要被唬到,其实就是相同技术在不同场合的不同叫法罢了。

本例中的拓扑,我们可以查看 https://github.com/apache/skywalking-query-protocol/blob/master/topology.graphqls 定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
extend type Query {
# Query the global topology
getGlobalTopology(duration: Duration!): Topology
# Query the topology, based on the given service
getServiceTopology(serviceId: ID!, duration: Duration!): Topology
# Query the topology, based on the given services.
# `#getServiceTopology` could be replaced by this.
getServicesTopology(serviceIds: [ID!]!, duration: Duration!): Topology
# Query the instance topology, based on the given clientServiceId and serverServiceId
getServiceInstanceTopology(clientServiceId: ID!, serverServiceId: ID!, duration: Duration!): ServiceInstanceTopology
# Query the topology, based on the given endpoint
getEndpointTopology(endpointId: ID!, duration: Duration!): Topology
# v2 of getEndpointTopology
getEndpointDependencies(endpointId: ID!, duration: Duration!): EndpointTopology
}

我们看到其中就有 getGlobalTopology,再看看我们之前的抓包,我能看下第二行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
query queryTopo($duration: Duration!) {
topo: getGlobalTopology(duration: $duration) {
nodes {
id
name
type
isReal
}
calls {
id
source
detectPoints
target
}
}
}

第二行内容 topo: getGlobalTopology(duration: $duration) {

  • topo 是查询结果的别名,查询到 response 会放到 topo 字段下
  • getGlobalTopology 的定义就是 getGlobalTopology(duration: Duration!): Topology

其中 Duration 定义,我们在 https://github.com/apache/skywalking-query-protocol/blob/master/common.graphqls 得到

1
2
3
4
5
input Duration {
start: String!
end: String!
step: Step!
}

就像套娃一样,你也可以找到 Step 的定义

总结

本文聊了我们如何找到自定义 UI 的切入点,同时就如何参考官方的一些开发细节进行了阐述。希望能给大家自定义数据展示平台一些参考。