性能监视工具 ,是一个APM(application performance Mange)工具
官网:https://skywalking.apache.org/
文档:https://skywalking.apache.org/docs/main/v8.4.0/readme/
中文文档:https://skyapm.github.io/document-cn-translation-of-skywalking/
无侵入性:即不需要改变代码
使用了java agent(java探针技术) 针对字节码做了增强处理
在类加载前就可以增强 内部方法名为premain (在main方法之前,jdk1.5之后引入的功能)
题外话开始============================= :
注意skywalking 可能出现一个全局的坑,在windows下启动 dos界面可能会卡住,这时需要按下ESC键, 在监控UI界面 有的时候可能不刷新,则需要手动多点击其它页面再切回来
且skywalking截至目前 都不支持mysql5.5的存储,这个和mysql的行格式有关 之前给作者提交过issues 但是很遗憾作者可能有自己的考虑 似乎不打算做修改 往后版本应该也不会支持5.5, 确实这种日志储存也不适合用mysql 我们测试时可以用来玩一玩 下面是我在github的反馈 描述5.5会出现的问题 感兴趣可以看看 不感兴趣可以跳过
Index colum too large . I notice the method of createTableIndexes in MysqlTableInstaller class, it make a distinction between Column.getLength() < 256 and extraQueryIndex. However , the id colum is also index colum default. Such as the inner talbe of skywalking creating: alarm_record , the length of id colum is 512 more than 255, so it occur error : Index colum too large because 512*3 >>767 bytes . And In mysql 5.7 or higher ,it’s right because in those version , creating table sql will append ROW_FORMAT=DYNAMIC default but 5.5 or lower is COMPACT. ROW_FORMAT can only act on table but not database , but the creating table sql is writed by skywalking method in H2TableInstaller#createTable , it seems our user can not change.Our use can only set GLOBAL innodb_large_prefix = ON in mysql ,but it doesn’t act on COMPACT (DYNAMIC is active)
这里有个小细节,如果把已有项目的mysql数据库从5.5换成5.7 ,记得要关闭严格模式,5.7默认是开启的 ,而5.5默认是关闭的
题外话结束===============================
.skywalking oapservice 集群 (服务端 收集处理数据)
.skywalking webapp UI 服务 (和服务端在一个安装包内)
.程序端:要绑定java探针 用于给oapservice收集数据
下载: 官网选择SkyWalking APM ,点击Distribution 下载存储方式带mysql的tar (根据自己存储需要)
(2022年更新: 最近又去了官网看 发现已经没有储存分类了,且目前看到下载界面只有8.8+版本了 ,根据下载网址分析 或许还能找到旧版本 此教程是基于8.5版本的apache-skywalking-apm-bin-es7 ,新版本agent目录独立出去了,要单独下载 其它基本都是一样的 )
bin目录下的startup.bat (会自动启动oapService.bat和webappService.bat;即同时启动了服务端及UI界面)
linux下启动startup.sh
webapp目录:UI界面的jar包及yml配置,在yml 修改界面默认端口(界面默认端口为8080容易冲突)
oap-libs目录: 服务端jar包
config目录:application.yml
agent目录: 和我们的项目服务进行绑定(启动时指定agent jar包) 新版本的skywalking已经独立出去了
logs目录: 日志文件(windows下日志只会输出在文件中,即使报错也不会输出在控制台,所以启动startup 尤其首次启动时 需要观察oap和webapp日志文件是否存在ERROR,linux启动成功会提示start successful)
修改数据存储方式为es7(推荐)或mysql(默认为h2 内存方式存储 重启数据会丢失):
找到application.yml中的
storage:
selector:${SW_STORAGE:h2}
变更为:
storage:
selector:${SW_STORAGE:elasticsearch7}
# 或者
#selector:${SW_STORAGE:mysql}
h2改为es7 并在es7节点下更改指定路径及账号密码
es默认是没有账号密码的,但是我们不能让es裸奔,es账号密码配置在我关于elasticsearch那篇博客有写,不再重复
elasticsearch7:
# 服务名称
nameSpace: ${SW_NAMESPACE:"my-application"}
# es地址
clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:192.168.1.xxx:9200}
protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
# 如果没有该文件需要注释掉
#trustStorePath: ${SW_STORAGE_ES_SSL_JKS_PATH:""}
#trustStorePass: ${SW_STORAGE_ES_SSL_JKS_PASS:""}
dayStep: ${SW_STORAGE_DAY_STEP:1} # Represent the number of days in the one minute/hour/day index.
indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1} # Shard number of new indexes
indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1} # Replicas number of new indexes
# Super data set has been defined in the codes, such as trace segments.The following 3 config would be improve es performance when storage super size data in es.
superDatasetDayStep: ${SW_SUPERDATASET_STORAGE_DAY_STEP:-1} # Represent the number of days in the super size dataset record index, the default value is the same as dayStep when the value is less than 0
superDatasetIndexShardsFactor: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_SHARDS_FACTOR:5} # This factor provides more shards for the super data set, shards number = indexShardsNumber * superDatasetIndexShardsFactor. Also, this factor effects Zipkin and Jaeger traces.
superDatasetIndexReplicasNumber: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_REPLICAS_NUMBER:0} # Represent the replicas number in the super size dataset record index, the default value is 0.
# es的账号
user: ${SW_ES_USER:"elastic"}
# es的密码
password: ${SW_ES_PASSWORD:"xxxxx"}
secretsManagementFile: ${SW_ES_SECRETS_MANAGEMENT_FILE:""} # Secrets management file in the properties format includes the username, password, which are managed by 3rd party tool.
bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:1000} # Execute the async bulk record data every ${SW_STORAGE_ES_BULK_ACTIONS} 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}
profileTaskQueryMaxSize: ${SW_STORAGE_ES_QUERY_PROFILE_TASK_SIZE:200}
oapAnalyzer: ${SW_STORAGE_ES_OAP_ANALYZER:"{\"analyzer\":{\"oap_analyzer\":{\"type\":\"stop\"}}}"} # the oap analyzer.
oapLogAnalyzer: ${SW_STORAGE_ES_OAP_LOG_ANALYZER:"{\"analyzer\":{\"oap_log_analyzer\":{\"type\":\"standard\"}}}"} # the oap log analyzer. It could be customized by the ES analyzer configuration to support more language log formats, such as Chinese log, Japanese log and etc.
advanced: ${SW_STORAGE_ES_ADVANCED:""}
h2改为mysql 并在mysql节点下更改数据库地址密码等配置
一般数据量不大 业务较小,出错较少时 mysql才适用,
库需要我们指定 表会自动创建,但是表非常多 为了不影响现有库查看 需要新建一个库
mysql:
properties:
jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://127.0.0.1:3306/sw"}
注:改成mysql之后会有一个坑 在oap-libs目录中(即sw的服务端jar包目录) 并没有内置mysql驱动jar包,需要我们手动复制一个进去
skywalking-oap-service 服务启动后会暴露两个端口:11800和12800分别为收集监控数据端口 和 接收UI前端请求的端口
(我们的项目配置端口为监控数据端口)
而webapp的端口 上文提到 默认是8080 极容易冲突,需要在webapp目录下 找到webapp.yml进行修改
java项目启动, skywalking的启动在上文 启动skywalking 介绍中
-javaagent 配置agent.jar包路径
-DSW_AGENT_NAME 我们的项目服务名(如果有nacos 最好与nacos保持一致)
-DWS_AGENT_COLLECTOR_BACKEND_SERVICES 配置sw oap服务端监控端口
在IDEA的VM options里面配置示例
-javaagent:D:\apache-skywalking-apm-es7-8.5.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
-DSW_AGENT_NAME=user
-DWS_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
linux示例: 命令启动jar包方式 java -jar xxx.jar 在java和-jar之间加上述配置
java -javaagent:/usr/xxx/xxx/skywalking-agent.jar
-DWS_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
-DSW_AGENT_NAME=user -jar ourProject.jar
windows示例
java -javaagent:D:\apache-skywalking-apm-es7-8.5.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar -DSW_AGENT_NAME=user -DWS_AGENT_COLLECTOR_BACKEND_SERVICES=172.26.92.51:11800,172.26.92.50:11800 -Xmx1024M -Xms512M -jar user-0.0.1-SNAPSHOT.jar
例如希望追踪某个业务方法的入参及返回值(点击链路即可看到信息)
第一步:需要引入依赖
org.apache.skywalking
apm-toolkit-trace
8.5.0
第二步:在业务方法上面加上@Trace注解 (该注解为记录方法注解)
第三步:再追加上@Tags或@Tag注解 (该注解用于记录方法的入参或返回值)
key一般可以指定为方法名或参数名(自定义),
value不能随便填 arg[0]表示下标为0的参数 ,returnedObj表示返回值
@Trace
@Tags({@Tag(key = "param", value = "arg[0]"), @Tag(key = "test", value = "returnedObj")})
private String test(String param) {
return "xxx";
}
可以定位到具体代码 占用时间
操作方法:性能剖析页面点击新建任务
选择实例服务 输入端点名称(接口相对路径url)
需要在oap-libs 目录中加上 log4j-web.jar
(忘记了自己最早为什么写的需要这个包,
后面经过测试可以不加 但基于对自己的信任 这句话先留着 万一就踩坑了呢)
第一步: 在pom文件中添加整合依赖
org.apache.skywalking
apm-toolkit-logback-1.x
第二步: 在resources下新建名为logback-spring.xml 的文件
-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint}%clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} [%tid] %clr(---){faint}%clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint}%m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n
注意:当skyWalking部署在远程服务的时候 需要在./agent/config目录下面对agent.config配置文件追加:
SW_GRPC_LOG_SERVER_HOST 对应服务地址 没有该配置默认为127.0.0.1
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:192.168.0.1}
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}
这里有个坑,如果配置反复检查没有配错,skywalking的控制台仍看不到日志信息(如果能看到直接跳过),那看看是不是和我一样踩坑了:
因为我是在个人项目中搭建的,个人项目之前为了模拟传说中的log4j史诗级bug, 需要把logback等日志的实现给排除 (log4j其实只是接口 真正的bug位于log4j-core包),所以我把springboot中 最常用的这个spring-boot-starter-logging包给排除了,等到需要skywalking和logback整合的时候 又单独引用了slf4j-api,logback-core,logback-classic 三个依赖,结果发现一直显示不了日志。 最后想来想去 应该是日志依赖这边出了问题,删除单独引入的依赖,直接引入starter-logging依赖,成功解决问题。
org.springframework.boot
spring-boot-starter-logging
SkyWalking告警功能是在6.x版本新增的的,其核心由一组规则驱动,这些规则定义在config目录的alarm-settings.yml文件中。
SkyWalking的发行版都会默认提供该配置,里面预先定义了一些常用的告警规则
1. 过去3分钟内服务平均响应时间超过1秒
2.过去2分钟服务成功率低于80%
3.过去3分钟内服务响应时间超过1s的百分比
4,服务实例在过去2分钟内平均响应时间超过1s.并且实例名称与正则表达式匹配,
5.过去2分钟内端点平均响应时间超过1秒
6.过去2分钟内数据库访问平均炯应时间超过1秒
7.过去2分钟内端点关系平均响应时间超过1秒。
规则名称: 告警信息中显示的唯一名称。必须以过 _rule 结尾,前綴可自定义
Metrics name:配置时只需要取 _rule 前的名称;度量名称,取值为oal脚本中的度量,目前只支持long、double和Int型
Include names:该规则作用于哪些实体名称,比如服务名,终端名(可选,默认为全部〕
Exclude names:该规则作不用于哪些实体名称,比如服务名,终惴名(可选,默认为空)
Threshold:阈值, 例如2000为2s
OP:操作符,目前支持> < =
Period:多久告警规则需要被核实一下。这是一个时间窗囗,与后端部署环境时间相匹配
Count: 在一个Period窗口中,如值values超过Threshold值(按op) 达到count值需要发送警报
Silence period : 在时间N中 触发报警后,在TN->TN+ period 这个阶段不告警 ,默认情况下 它和period一样,意味着相同的告警 在同一个period内只会触发一次
webhooks: 网络钩子 可以理解为web回调 出现告警时,可以往我们任意一个服务发送请求,
我们可以在服务里面写业务代码:如发送短信、邮件等 请求方式:http, post, Content-type:application/json
基于List
,可以自定义一个类 字段保持上述一致
配置示例:
rules:
# Rule unique name, must be ended with `_rule`.
service_resp_time_rule:
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
exclude-labels:
# 过滤状态码 200 401 404 注意前面有个小横杠
- "200,401,404"
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
skywalking的告警页面,可以看到我们的告警信息。如果之前的告警 页面突然看不到了,看看是不是时间筛选的问题,默认的时间跨度不会很长,不得不吐槽其它页面上方都有时间筛选 而告警页面只有右下角才有,每次搭建后都以为是出现了bug。
上面介绍的是告警功能,只能在skywalking的控制台面板上看到,那如果我们想要通知功能该怎么办呢? 同样是在config目录的alarm-settings.yml配置中
找到webhooks:节点
注意前面有个 横杠 - ,建议打开注释并修改默认地址 避免出错,指定接口后,skywalking告警消息在短暂的延迟后会调用我们的接口进行通知, 我们可以在接口里面写发送邮件、发送短信 、通知到钉钉群等代码功能,取决于我们需求。
1.skywalking的config目录 application.yml配置文件 指定nacos地址 (两处配置 一处配置集群 一处为动态配置 在配置文件中搜索nacos即可)
cluster:
nacos:
2.配置ui服务 webapp.yml 文件的listOfServers 写多个地址 用逗号隔开
3.在vm options里面 地址同样指定多个地址
skywalking(8.5)在nacos中只会显示一个实例 但实际是正常的
4.注意:如果使用的是springcloud alibaba ,skywalking 默认是不显示gateway服务的,需要在agent/optional-plugins(可选插件目录)找到gateway相关的jar包 选择较新的版本复制进agent/plugins目录中
service维度:
Service Apdex(数字):当前服务的评分
Service Apdex(折线图):不同时间的Apdex评分
Successful Rate(数字):请求成功率
Successful Rate(折线图):不同时间的请求成功率
Servce Load(数字):每分钟请求数
Servce Load(折线图):不同时间的每分钟请求数
Service Avg Response Times:平均响应延时,单位ms
Global Response Time Percentile:百分比响应延时
Servce Instances Load:每个服务实例的每分钟请求数
Show Service Instance:每个服务实例的最大延时
Service Instance Successful Rate:每个服务实例的请求成功率
一、初始化配置: 优先级依次递增 (相同配置项 后者会把前者覆盖)
检查并读取agent.config配置
将配置映射至sw定义的Config实体类
根据配置指定日志解析器
检查opts参数是否存在
二、加载插件:
使用自定义类加载器加载插件jar包
修改中间件源码 对其进行拦截、修改
三、字节码增强
四、启动服务
五、注册关闭服务的钩子
通过traceId,segment,spanId记录完成
Trace: 一整个操作链路内为一个trace (全局唯一)
Segment: 一个jvm进程内的一个线程中的所有操作的集合
span: 每个具体的操作
默认通过gRpc发送到oapService (也支持kafka)