支持istio做服务网格的链路追踪
APM系统概述
什么是APM系统
APM(Application Performance Management)应用性能管理系统,是对企业系统即时监控以实现对应用程序性能管理和故障管理的系统化的解决方案。
APM系统可以帮助理解系统行为,用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。
主流的产品基于Google论文:
Dapper,大规模分布式系统的跟踪系统 by bigbully
实现的功能:
- 日志(Logs)
- 指标(Metrics)
- 链路追踪(Traces)
主流APM系统
日志:ELK Stack
指标:Prometheus
链路追踪:Skywalking
OpenTracing标准
是一个标准,类比:jdbc、
github文档:OpenTracing
Skywalking概述
基本概念
为什么使用Skywalking
它是一个开源的可观测平台,用于从服务和云原生基础设施收集,分析,聚合及可视化数据。
它可以Tracing,Metrics、Logging、EventDetector
核心功能
- 服务,服务实例,锚点(URI)指标分析
- 根本原因分析,在运行时上分析由进程内代理和ebpf分析器支持的代码
- 业务拓扑图分析
- 服务实例和锚点(URI)依赖关系分析
- 服务和锚点检测速度慢
- 性能优化
- 分布式跟踪和上下文传播
- 数据库访问指标,检测滑速数据库访问语句(包括SQL语句)
- 消息队列性能和消耗延迟监视
- 浏览器性能监控
- 基础设施(虚拟机、网络、磁盘等)监控
特点
- 基于JAVA生态,功能丰富
- 社区活跃,迭代迅速
- 链路追踪,拓扑分析的能力强
- 插件丰富,探针无侵入
- 采用先进的流式拓扑分析设计
- 多语言支持
- 微内核+插件的架构,存储,集群管理,使用插件集合都可以进行自由选择
- 为多种开源项目提供了插件,为Tomcat,httpclient,spring,rabbitmq,mysql等常见基础设施和组件提供了自动探针
- 优秀的可视化效果
关键概念
服务与服务实例
一个服务有多个服务实例
端点
对于特定服务所接收的请求路径,如HTTP的URI路径和gRPC服务的类名+方法签名
架构
组件
探针(Agent)
服务端(OAP)
- 分析引擎(Analysis Core)接收上报的数据,进行流式分析,最终将分析结果写入到存储中
- 查询引擎(Query Core)响应UI界面的查询请求,将数据查询出来,返回给界面展示
存储(Storage)
通过开发的插件化的接口存放Skywalking数据,你可以选择一个既有的存储系统,如Elasticsearch,H2或Mysql集群(ShardingSphere管理),也可以选择自己实现一个存储系统。
用户界面(UI)
设计目标
保持可观测性
官方支持多种Agent,可自定义。
拓扑结构
轻量级
可插拔
可移植
Skywalking可以运行在多种环境下,包括:
- 使用传统的注册中心
- 使用包含服务发现的RPC框架,如SpringCloud,Apache Dubbo
- 在现在基础设施中使用服务网格
- 使用云服务
- 跨云部署
快速入门
部署OAP服务
下载安装包
(1)下载Foundations中的Skywalking APM,选择Distribution版本下载,Source为源码版本
(2)在Agents中下载你需要的Agent,这里我们下载Java Agent,同样也选择Distribution版本
负责收集各种监控数据,上报给服务端。
修改配置
config/applications.yaml文件
找到storage > selector 将其修改 ${SW_STORAGE:elasticsearch} 根据自己需求决定是否修改命名空间、es连接地址、用户名密码等。
启动OAP服务
进入bin目录中,选择启动脚本运行
startup.sh:会先后启动OAP服务与UI服务
oapService.sh:单独启动OAP服务,第一次启动需要初始化数据,因此可能会比较慢
webappService.sh:单独启动UI服务
查看任一服务启动是否成功,看<skywalking Home>/logs下面的日志文件即可
在不修改存储位置的情况下默认使用内置H2数据库
Skywalking UI可视化
skywalking-webapp启动要在oap启动之后再启动否则会报错
bin/webappService.sh
基于Agent监控Springboot应用
agent的目的是收集对应服务的数据并上报数据
配置文件
agent.config
启动脚本
#!/bin/bash
# Skywalking Agent启动脚本
export SW_AGENT_NAME=skywalking-demo # 探针名称,一般指定为监控应用的名称
export SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 # collector地址,指向OAP服务
export SW_AGENT_SPAN_LIMIT=1000 # 配置链路的最大span数量,默认为300
export JAVA_AGENT=-javaagent:<探针jar包的位置>
java $JAVA_AGENT -jar skywalking-demo-1.0.0-SNAPSHOT.jar # 启动程序
IDE开发工具
通过idea启动配置,添加如下jvm参数:
- javaagent:[探针jar所在的位置]
- DWS_AGENT_NAME=skywalking-springboot-demo
# 查看OAP gRPC server【在日志中】
# Bind handler SatelliteAccessLogServerGRPCHandlerV3 into gRPC server 0.0.0.0:11800
- DWS_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.113.121:11800
实战进阶
持久化存储
ElasticSearch实现存储(推荐)
修改配置文件:skywalking-apm-9.3/config/application.yml
storage:
selector: ${SW_STORAGE:elasticsearch}
在skywalking9.0以前的配置文件中,关于Elasticsearch的配置分为elasticsearch7以下的版本及elasticsearch7及7以上版本的不同的配置。
Mysql
配置
修改配置文件:skywalking-apm-9.3/config/application.yml
storage:
selector: ${SW_STORAGE:mysql}
mysql:
[按实际情况修改相应的值]
复制jar包
默认是不支持mysql的,需要将mysql数据库驱动包拷贝到oap-libs目录下才可以
微服务项目链路追踪
Dubbo
SpringCloud
有一个注意地方是:
存放的地方:skywalking-agent/plugins/中将apm对于SpringCloud Gateway支持的jar包加入
具体是两个包:(这两个包应该是在skywalking-agent/optional-plugins/中)
- apm-spring-cloud-gateway-x.x-8.14.0.jar
- apm-spring-webflux-5.x-plugin-8.14.0.jar
这样才能支持网关
日志采集
目标:将日志与链路关联起来
引入依赖
加入skywalking与logback相结合的包
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.14.0</version>
</dependency>
Logback配置
通过gRPC将日志信息输出到oap服务中
告警通知
规则
通过skywalking-apm-9.3/config/alarm-setting.yaml文件配置规则
告警规则
参数:
- metrics-name:指标名称,也是OAL脚本中的指标名,可以配置告警的指标有:服务、实例、锚点、服务关系、实例关系、端点关系、只支持long,double,int类型
- op:操作符
- threshold:阈值,单位ms
- period:告警规则多久被检查一次,是一个时间窗口
- count:在一个时间窗口内,满足op超过阈值的次数达到count值,就会触发告警
- silence-period:在时间N中触发告警后,在N+silence-period这段时间内不告警
- message:告警时通知的消息
指标中常见的术语:
p50:50%的请求
p75:75%请求
p90:90%请求
webhooks
通过skywalking-apm-9.3/config/alarm-setting.yaml文件配置
当触发告警时会触发webhook,将告警信息发送出来
public class AlarmMessage {
private int scopeId;
private String name;
private String id0;
private String id1;
private String alertMessage;
private long startTime;
private String ruleName;
}
会以集合方式发送
@RequestMapping("/alerting")
@RestController
public class AlertController {
@PostMapping("/notify")
public void alertingNotify(@RequestBody List<AlarmMessage> messages) {
Log.info("[告警通知]告警消息:{}",JSON.toJSONString(messages))
}
}
告警通知到钉钉
https://skywalking.apache.org/docs/main/v9.3.0/en/setup/backend/backend-alarm/#dingtalk-hook
自定义链路追踪
想知道服务内部中的链路关系(例如:controller->多个Service)
引入依赖
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.14.0</version>
</dependency>
获取TraceId
@RequestMapping("/traceid")
public void traceid(){
//可以向追踪上下文对象中绑定key/value数据
TraceContext.putCorrelation("name","xiaoliu");
//获取绑定的值
log.info("获取绑定的值:{}",TraceContext.getCorrelation("name"))
//获取traceId
log.info("获取traceId:{}",TraceContext.traceId())
}
@Trace
可以放到方法上面,表示当前的方法需要被追踪的。
//这个值会出现在追踪的链路中,他会成为链路中的某一项的值
@Trace(operationName="PLACE_ORDER")
@Tags
@Trace
@Tags({
//可以获取方法参数
@Tag(key="productId",value="arg[0]"),
//获取方法返回的数据
@Tag(key="orderNo",value="returnedObj")
})
public String placeOrder(String s){
}
集群环境搭建
搭建ES环境
搭建Nacos集群
搭建OAP服务集群
- storage改为elasticsearch存储
- 配置nacos
注意:为了使得不同OAP服务能够正常注册到nacos中,需要将配置文件中奖gRPCHost修改为不同ip地址
core:
gRPCHost: ${SW_CORE_GFRPC_HOST:192.168.113.120}
- 在多个节点运行OAP服务
/bin/oapService.sh
部署Skywalking UI
skywalking-apm-9.3/webapp/application.yml
oapServices: ${SW_OAP_ADDRESS:-http://A,http://B,http://C}
微服务Agent配置
- javaagent:[探针jar所在的位置]
- DWS_AGENT_NAME=skywalking-springboot-demo
# 查看OAP gRPC server【在日志中】
# Bind handler SatelliteAccessLogServerGRPCHandlerV3 into gRPC server 0.0.0.0:11800
# 因为搭建的是集群,所有这个位置配置多个OAP服务
- DWS_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.113.121:11800,192.168.113.122:11800,192.168.113.123:11800
k8s部署实战
SWCK组件
swck:(skywalking cloud on kubernetes)
他是部署在Kubernetes环境中为skywalking用户提供服务的平台。用户可以基于该平台使用,升级和维护skywalking相关组件。
SWCK是基于kubebuilder开发的operator,为用户提供自定义的资源及管理资源的控制器,所有自定义资源的定义(CRD)如下所示:
- JavaAgent
- OAP
- UI
- Storage
https://github.com/apache/skywalking-swck
安装cert-manager
swck安装依赖于cert-manager。
要注意cert-manager版本与k8s版本存在对应关系。
Supported Releases - cert-manager Documentation
安装SWCK
GitHub - apache/skywalking-swck at v0.8.0
安装OAPServer和UI
Java应用自动注入探针
构建应用镜像
下载官方演示代码
git clone GitHub - dashanji/swck-spring-cloud-k8s-demo
进入目标并构建镜像
cd swck-spring-cloud-k8s-demo && make
为镜像打标签并推送到远程仓库
docker tag app:v0.0.1 xxxxxxx
docker tag gateway:v0.0.1 xxxxx
Java agent配置的相关信息需要写到annotation中
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: demo-gateway
name: demo-gateway
namespace: gateway-system
spec:
selector:
matchLabels:
app: demo-gateway
template:
metadata:
labels:
swck-java-agent-injected: "true"
app: demo-gateway
annotations:
# 配置collector收集的地址
agent.skywalking.apache.org/collector.backend_service: "default-oap.default:11800"
strategy.skywalking.apache.org/agent.Overlay: "true"
agent.skywalking.apache.org/agent.service_name: "gateway-service"
optional.skywalking.apache.org: "cloud-gateway-3.x" # add spring cloud gateway plugin
spec:
containers:
- image: 10.170.33.57/library/gateway:v0.0.1
name: gateway
command: ["java"]
args: ["-jar","/gateway.jar"]
---
apiVersion: v1
kind: Service
metadata:
name: service-gateway
namespace: gateway-system
spec:
type: NodePort
ports:
- name: 9999-tcp
port: 9999
protocol: TCP
targetPort: 9999
selector:
app: demo-gateway
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: demo-gateway
name: demo-gateway
namespace: gateway-system
spec:
selector:
matchLabels:
app: demo-gateway
template:
metadata:
labels:
swck-java-agent-injected: "true"
app: demo-gateway
annotations:
# 配置collector收集的地址
agent.skywalking.apache.org/collector.backend_service: "default-oap.default:11800"
strategy.skywalking.apache.org/agent.Overlay: "true"
agent.skywalking.apache.org/agent.service_name: "gateway-service"
# 需要额外的plugin
optional.skywalking.apache.org: "cloud-gateway-3.x" # add spring cloud gateway plugin
spec:
containers:
- image: 10.170.33.57/library/gateway:v0.0.1
name: gateway
command: ["java"]
args: ["-jar","/gateway.jar"]
---
apiVersion: v1
kind: Service
metadata:
name: service-gateway
namespace: gateway-system
spec:
type: NodePort
ports:
- name: 9999-tcp
port: 9999
protocol: TCP
targetPort: 9999
selector:
app: demo-gateway
部署应用
工程中有两个应用:Springboot应用、网关应用。
项目中有资源部署的yaml文件
要想自动注入,需要为你运行应用所在的命名空间打上标签
kubectl label ns springboot-system swck-injection=enabled
还有需要注意的是应用部署的yaml文件中的annotations:
查看java agent是否被自动创建
验证追踪状态
将service用nodeport方式暴露出来
如何使用java探针注入器? | Apache SkyWalking
分布式调用链标准-OpenTracing
数据模型
Trace
Span
操作名称
开始与结束的时间间隔
key/value属性
Tags
Logs
Baggage
父span标识
SpanContext
Trace的全局上下文信息,如里面有traceid、spanid、baggage等,会进行跨服务进行传递。
API
Skywalking原理及架构设计
架构设计
自动采集&无侵入
依赖于:
- 基于agent(例如:Java agent)—— 无侵入采集的核心
- 插件化:
跨进程传递Context
- 在跨进程调用之前,当前进程会通过inject()方法将当前Context的全部内容注入到指定的ContextCarrier,然后才能将当前Context的信息发送出去。
- 在跨进程调用的接收方,会通过extract()方法将接收到的Context从ContextCarrier中提取出来
TraceId唯一性
性能影响
设置采样频率,只采样部分数据,skywalking默认设置3秒采样3次,其余请求不采样。为了防止链路不完整情况发生,如果上游有携带Context过来(说明上游采样了),则下游强制采集数据。
实现原理
Agent与Plugin
Skywalking Agent为了能够让更多开发者加入开发,并且能够有足够的自由度,使用插件的机制,Agent启动时会加载所有plugins,进行字节码增强。
可自定义Plugin,需要满足plugins有两个核心目标:
- 创建Span加入Trace调用链
- 数据的传输(如何将数据加入到Header中)
TraceSegment【Skywalking独有概念】
skywalking没有使用传统的span模型,处于性能考虑,将span保存为数组,存放到TraceSegment结构中批量发送:同时Segment可以很好地在UI上展示信息。
一个TraceSegment是Trace在一个进程内所有span的集合,如果是多个线程协同产生1个Trace(例如:多次RPC调用不同的方法),它们只会共同创建1个TraceSegment。
由于支持多个入口,因此Skywalking去掉了RootSpan的概念,skywalking提出了以下3种span类型:
EntrySpan
LocalSpan
ExitSpan
TraceId设计
类似雪花算法:存在时间回拨问题。skywalking解决了这个问题
Java Agent
基本概念
启动方式
静态启动
通过添加JVM参数 -javaagent挂载Agent
入口方法:premain()
字节码操作限制
- 服务号字节码规范
- 对字节码做任意修改
适用场景:需要对字节码进行大量修改(APM)
Skywalking目前仅支持该种方式
动态启动
JVM运行时使用Attach API 挂载Agent
入口方法:agentmain()
字节码操作限制
- 不能增减父类
- 不能增加接口
- 不能增减字段
使用场景:系统诊断(阿里Arthas)
字节码编辑
- byte-buddy
- ASM
- javassist