1、skywalking是什么
skywalking是一个国产开源框架,2015年由吴晟开源,2017年加入Apache孵化器。skywalking是分布式系统的应用程序的性能监视工具,专为微服务、云原生架构和基于容器(Docker、k8s,Mesos)架构而设计。它是一款优秀的APM(Application Performance Management)工具,包括了分布式追踪、性能指标分析、应用和服务依赖分析等。
官网: http://skywalking.apache.org
下载: https://skywalking.apache.org/downloads/
Github: https://github.com/apache/skywalking
文档: https://skyapm.github.io/document-cn-translation-of-skywalking/
1.2、链路追踪框架对比
1、Zipkin是Twitter开源的调用链分析工具,目前基于springcloud sleuth得到了广泛的使用,特点是轻量,使用部署简单
2、Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能强大,接入端无代码侵入。
3、SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。
4、CAT是大众点评开源的基于编码和配置的调用链分析,应用监控分析,日志采集,监控报警等一些列监控平台工具。
1.3、skywalking的主要功能特性
1、多种监控手段,可以通过语言探针和service mesh获得监控的数据
2、支持多种语言的自动探针、包括java 、.NET Core 和 Node.JS
3、轻量高效,无需大数据平台和大量的服务器资源
4、模块化,UI,存储、集群管理都有多种机制可选
5、支持告警
6、优秀的可视化解决方案
2、skywalking环境搭建部署
- skywalking agent和业务系统绑定在一起,负责收集各种监控数据
- skywalking oapservice是负责处理监控数据的,比如接受skywalking agent的监控数据,并存储在数据库中;接受skywalking webapp的前端请求,从数据库查询数据,并返回数据给前端。skywalking oapservice通常以集群的形式存在。
- skywalking webapp 前端界面,用于展示数据。
- 用于存储监控数据的数据库,比如mysql,elasticsearch等
2.1、下载skywalking
下载地址:
https://archive.apache.org/dist/skywalking/8.5.0/【我这里用windows演示】
- webapp: UI前端(web监控页面)的jar包和配置文件
- oap-libs: 后台应用的jar包,以及它的依赖jar包
- config: 启动后台应用程序的配置文件
- bin: 各种启动脚本,一般使用脚本startup.*来启动web页面和对应的后台应用
- oapService.* : 默认使用后台程序的启动脚本(使用的是默认启动,还支持其他模式)
- oapServiceInit.*: 使用init模式启动;在此模式下,OAP服务器启动以执行初始化工作,然后退出
- oapServiceNoInit.*: 使用no init 模式启动;在此模式下,OAP服务器不进行初始化
- webappService.*: UI前端的启动脚本;
- startup.* : 组合脚本,同时启动OApService.* 、webappService.* 脚本
- agent
- skywalking-agent.jar 代理服务jar包
- config: 代理服务启动时使用的配置文件
- plugins: 包含多个插件,代理服务启动时会加载改目录下的所有jar包
- optional-plugins: 可选插件,当需要支持某种功能时,比如Springcloud gateway,则需要把对应jar包拷贝到plugiins目录下;
2.2、搭建SkyWalking OAP服务
1、修改UI地址webapp\webapp.yml
端口号,由于8080我们经常需要用到,所以为了避免以后冲突,我们进行修改
server: port: 8810 collector: path: /graphql ribbon: ReadTimeout: 10000 # Point to all backend's restHost:restPort, split by , listOfServers: 127.0.0.1:12800
双击启动bin/startup.bat
启动成功后,日志存储在logs目录
启动成功后会启动两个服务,一个是skywalking-aop-server
,一个是skywalking-web-ui
skywalking-aop-server服务启动后会暴露11800和12800两个端口,分别为收集监控数据的端口11800和接受前端请求的端口12800
,修改端口可以修改config/application.yml
我们进行访问:localhost:8810
2.3、skywalking—接入微服务
1、在运行的程序配置jvm参数
# 你的 skywalking-agent.jar包地址 -javaagent:D:\a-mysource\apache-skywalking\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar # 在skywalking上显示的服务名 -DSW_AGENT_NAME=springboot-skywalking-demo #你的skywalking-aop-server地址及端口号 -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
启动成功后,随便对一个接口进行访问,然后刷新我们的skywalking UI界面
注意:此处存在bug,跟踪链路不显示gateway
拷贝agent/optional-plugins目录下的gateway插件到agent/plugins目录
然后进行重启(服务也需重启)
然后我们来看看拓补图(服务之间的错综复杂调用关系图)
用户调用网关服务,网关服务转发到我们需要调用的服务
追踪:
可以看到我们请求经过的一些具体信息
2.4、skywalking—接入多个微服务
将我们之前的服务按上述步骤,配置jvm参数即可
# 你的 skywalking-agent.jar包地址 -javaagent:D:\a-mysource\apache-skywalking\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar # 在skywalking上显示的服务名 -DSW_AGENT_NAME=springboot-skywalking-demo #你的skywalking-aop-server地址及端口号 -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
然后打开UI界面
成功多了很多指标,对应服务也都添加进来了
我们再看拓补图:
关系也错综复杂起来了
- 用户
- 网关
- order-service服务
- 数据库
- stock-service服务
- 数据库
我们再看追踪
可以精确定位到哪个服务出的错误。
3、skywalking持久化跟踪数据
默认使用的是H2数据库存储 , 存储在我们的内存中
config/application.yml
3.1、基于mysql持久化
1、修改config目录下的application.yml. 使用mysql作为持久化的残酷
2、修改mysql连接配置
3、创建数据库swtest
,至于表我们不用去关心,它会在我们启动的时候自动为我们建表
4、添加mysql驱动jar包到oap-libs
里面
5、进行重启
发现自动为我们创建了很多表
这个时候我们关闭再打开skywaking
程序就发现原有的数据都还存在。
4、自定义skywalking链路追踪
4.1、@Trace注解
如果我们希望对项目中的业务方法,实现链路追踪,方便我们排查问题。可以使用如下的操作
1、引入依赖
<!--skywalking 工具类,为了自定义链路追踪--> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-toolkit-trace</artifactId> <version>8.5.0</version> </dependency>
2、只需要在业务方法上加入一个注解即可
@Trace public String hello(String str) { return str; }
可以看到我们的业务方法也进入到了链路当中
4.2、@Tags或@Tag注解
还可以为追踪链路增加其额外的信息,比如记录参数和返回信息。实现方式:在方法上增加@Tag和@Tags。
key = 名字,value=returnObj 返回值 arg[0] 参数
@Trace @Tags({@Tag(key = "string",value = "returnedObj"),@Tag(key = "param",value = "arg[0]")}) public String hello(String str) { return str; }
5、skywalking性能剖析
对一个服务的一个接口进行,性能分析,最大采样数即最少访问次数
请求5次以上然后进行刷新
看看具体信息
可以准确定位我们消耗资源的问题所在,因为我在代码中加入了休眠。
6、skywalking日志
1、我们在需要添加日志的服务里引入依赖
<!--apm‐toolkit‐logback‐1.x 日志 --> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-toolkit-logback-1.x</artifactId> <version>8.5.0</version> </dependency>
2、添加文件logback-spring.xml
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <!-- 引入Spring Boot 默认的 logback xml 配置文件--> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <!--日志的格式化--> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <Pattern>-%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}}</Pattern> </layout> </encoder> </appender> <!--设置Appender--> <root level="INFO"> <appender-ref ref="console"/> </root> </configuration>
3、启动项目
可以根据tid定位到对应的链路信息,搜索即可
4、skywalking通过grpc上报日志(需要v8.4.0+)
grpc报告程序可以将收集到的日志转发到skywalking oap服务器上
logback-spring.xml
中添加后的全部内容为
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 引入 Spring Boot 默认的 logback XML 配置文件 --> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <!--日志的格式化--> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <Pattern>-%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}}</Pattern> </layout> </encoder> </appender> <appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"> <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern> </layout> </encoder> </appender> <!--设置 Appender--> <root level="INFO"> <appender-ref ref="console"/> <appender-ref ref="grpc-log"/> </root> </configuration>
重新启动
注意:如果时部署在服务器上的话,日志可能不能正常显示,需要加入以下配置
在agent/config/agent.config
配置文件
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:192.168.3.100} 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}
配置名 | 解释 | 默认值 |
plugin.toolkit.log.grpc.reporter.server_host | 指定要向其报告日志数据的grpc服务器的主机 | 127.0.0.1 |
plugin.toolkit.log.grpc.reporter.server_port | 指定要向其报告日志数据的grpc服务器的端口 | 11800 |
plugin.toolkit.log.grpc.reporter.max_message_size | 指定grpc客户端要报告的日志数据的最大大小 | 10485760 |
plugin.toolkit.log.grpc.reporter.upstream_timeout | 客户端向上游发送数据时将超时多长时间。单位是秒 |
7、skywalking告警
SkyWalking 告警功能是在6.x版本新增的,其核心由一组规则驱动,这些规则定义在config/alarm-settings.yml
文件中。
告警规则的定 义分为两部分:
- 告警规则:它们定义了应该如何触发度量警报,应该考虑什么条件。
- Webhook(网络钩子):定义当警告触发时,哪些服务终端需要被告知
7.1、告警规则
SkyWalking 的发行版都会默认提供config/alarm-settings.yml文件,里面预先定义了一些常用的告警规则。如下:
- 过去 3 分钟内服务平均响应时间超过 1 秒。
- 过去 2 分钟服务成功率低于80%。
- 过去 3 分钟内服务响应时间超过 1s 的百分比
- 服务实例在过去 2 分钟内平均响应时间超过 1s,并且实例名称与正则表达式匹配。
- 过去 2 分钟内端点平均响应时间超过 1 秒。
- 过去 2 分钟内数据库访问平均响应时间超过 1 秒
- 过去 2 分钟内端点关系平均响应时间超过 1 秒
这些预定义的告警规则,打开config/alarm-settings.yml文件即可看到
告警规则配置项的说明:
- Rule name:规则名称,也是在告警信息中显示的唯一名称。必须以_rule结尾,前缀可自定义
- Metrics name:度量名称,取值为oal脚本中的度量名,目前只支持long、double和int类型。详见Official OAL script
- Include names:该规则作用于哪些实体名称,比如服务名,终端名(可选,默认为全部)
- Exclude names:该规则作不用于哪些实体名称,比如服务名,终端名(可选,默认为空)
- Threshold:阈值
- OP: 操作符,目前支持 >、<、= Period:多久告警规则需要被核实一下。这是一个时间窗口,与后端部署环境时间相匹配
- Count:在一个Period窗口中,如果values超过Threshold值(按op),达到Count值,需要发送警报
- Silence period:在时间N中触发报警后,在TN -> TN + period这个阶段不告警。 默认情况下,它和Period一样,这意味着 相同的告警(在同一个Metrics name拥有相同的Id)在同一个Period内只会触发一次
- message:告警消息
7.2、Webhook网路钩子
Webhook可以简单理解为是一种Web层面的回调机制,通常由一些事件触发,与代码中的事件回调类似,只不过是Web层面的。由于是 Web层面的,所以当事件发生时,回调的不再是代码中的方法或函数,而是服务接口。例如,在告警这个场景,告警就是一个事件。当该 事件发生时,SkyWalking就会主动去调用一个配置好的接口,该接口就是所谓的Webhook。 SkyWalking的告警消息会通过 HTTP 请求进行发送,请求方法为 POST,Content-Type 为 application/json,其JSON 数据实基于 List
告警功能实践
1.实体类用来接受数据
@Data public class SwAlarmDTO { private Integer scopeId; private String scope; private String name; private Integer id0; private Integer id1; private String ruleName; private String alarmMessage; private Long startTime; }
2、接口,用来实现告警通知
@RestController @RequiredArgsConstructor @RequestMapping("/alarm") public class SwAlarmController { @PostMapping("/receive") public void receive(@RequestBody List<SwAlarmDTO> alarmList) { System.out.println(getContent(alarmList)); } private String getContent(List<SwAlarmDTO> alarmList) { StringBuilder sb = new StringBuilder(); for (SwAlarmDTO dto : alarmList) { sb.append("scopeId: ").append(dto.getScopeId()) .append("\nscope: ").append(dto.getScope()) .append("\n目标 Scope 的实体名称: ").append(dto.getName()) .append("\nScope 实体的 ID: ").append(dto.getId0()) .append("\nid1: ").append(dto.getId1()) .append("\n告警规则名称: ").append(dto.getRuleName()) .append("\n告警消息内容: ").append(dto.getAlarmMessage()) .append("\n告警时间: ").append(dto.getStartTime()) .append("\n\n‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐\n\n"); } return sb.toString(); } }
3、最后进行配置
config/alarm-settings.yml
文件末尾(也就是添加告警后需要请求的接口)
webhooks: - http://127.0.0.1:8889/alarm/receive
4、重新启动即可,然后对接口进行请求,尽量触发告警,控制台即可打印出告警信息