代码仓库 以Skywalking开头的module
ObservabilityLearning: ObservabilityLearning 整合框架demo (gitee.com)
Skywalking概述 根据官方的解释,Skywalking是一个可观测性分析平台(Observability Analysis Platform简称OAP) 和应用性能管理系统(Application Performance Management简称APM)。 提供分布式链路追踪、服务网格(Service Mesh)遥测分析、度量(Metric)聚合和可视化一体化解决方案。 下面是Skywalking的几大特点:
多语言自动探针,Java,.NET Core和Node.JS。
多种监控手段,语言探针和service mesh。
轻量高效。不需要额外搭建大数据平台。
模块化架构。UI、存储、集群管理多种机制可选。
支持告警。
优秀的可视化效果。 Skywalking整体架构如下:
Skywalking提供Tracing和Metrics数据的获取和聚合。
Metric的特点是,它是可累加的:他们具有原子性,每个都是一个逻辑计量单元,或者一个时间段内的柱状图。 例如:队列的当前深度可以被定义为一个计量单元,在写入或读取时被更新统计; 输入HTTP请求的数量可以被定义为一个计数器,用于简单累加; 请求的执行时间可以被定义为一个柱状图,在指定时间片上更新和统计汇总。用来统计后显示数据,就是指标。
Tracing的最大特点就是,它在单次请求的范围内,处理信息。 任何的数据、元数据信息都被绑定到系统中的单个事务上。 例如:一次调用远程服务的RPC执行过程;一次实际的SQL查询语句; 一次HTTP请求的业务性ID。
总结,Metric主要用来进行数据的统计,比如HTTP请求数的计算。Tracing主要包含了某一次请求的链路数据。
详细的内容可以查看Skywalking开发者吴晟翻译的文章,Metrics, tracing 和 logging 的关系 : http://blog.oneapm.com/apm-tech/811.html
在其中gRPC技术后面要着重使用
gRPC和restful API都提供了一套通信机制,用于server/client模型通信,而且它们都使用http作为底层的传输协议(严格地说, gRPC使用的http2.0,而restful api则不一定)。不过gRPC还是有些特有的优势,如下:
gRPC可以通过protobuf来定义接口,从而可以有更加严格的接口约束条件。关于protobuf可以参见Google Protobuf简明教程](https://www.jianshu.com/p/b723053a86a6)
另外,通过protobuf可以将数据序列化为二进制编码,这会大幅减少需要传输的数据量,从而大幅提高性能。
gRPC可以方便地支持流式通信(理论上通过http2.0就可以使用streaming模式, 但是通常web服务的restful api似乎很少这么用,通常的流式数据应用如视频流,一般都会使用专门的协议如HLS,RTMP等,这些就不是我们通常web服务了,而是有专门的服务器应用。)
需要对接口进行严格约束的情况,比如我们提供了一个公共的服务,很多人,甚至公司外部的人也可以访问这个服务,这时对于接口我们希望有更加严格的约束,我们不希望客户端给我们传递任意的数据,尤其是考虑到安全性的因素,我们通常需要对接口进行更加严格的约束。这时gRPC就可以通过protobuf来提供严格的接口约束。
对于性能有更高的要求时。有时我们的服务需要传递大量的数据,而又希望不影响我们的性能,这个时候也可以考虑gRPC服务,因为通过protobuf我们可以将数据压缩编码转化为二进制格式,通常传递的数据量要小得多,而且通过http2我们可以实现异步的请求,从而大大提高了通信效率。
但是,通常我们不会去单独使用gRPC,而是将gRPC作为一个部件进行使用,这是因为在生产环境,我们面对大并发的情况下,需要使用分布式系统来去处理,而gRPC并没有提供分布式系统相关的一些必要组件。而且,真正的线上服务还需要提供包括负载均衡,限流熔断,监控报警,服务注册和发现等等必要的组件。不过,这就不属于本篇文章讨论的主题了,我们还是先继续看下如何使用gRPC。
整体架构包含如下三个组成部分:
探针(agent)负责进行数据的收集,包含了Tracing和Metrics的数据,agent会被安装到服务所在的服务器上,以方便数据的获取。
可观测性分析平台OAP(Observability Analysis Platform),接收探针发送的数据,并在内存中使 用分析引擎(Analysis Core)进行数据的整合运算,然后将数据存储到对应的存储介质上,比如 Elasticsearch、MySQL数据库、H2数据库等。同时OAP还使用查询引擎(Query Core)提供HTTP查 询接口。
Skywalking提供单独的UI进行数据的查看,此时UI会调用OAP提供的接口,获取对应的数据然后 进行展示。
使用如下案例来进行Skywalking主要概念的介绍,Skywalking主要概念包含:
服务(Service)
端点(Endpoint)
实例(Instance)
我们编写了用户服务,这是一个web项目,在生产中部署了两个节点:192.168.1.100和 192.168.1.101。
用户服务就是Skywalking的服务(Service),用户服务其实就是一个独立的应用(Application),在 6.0之后的Skywalking将应用更名为服务(Service)。
用户服务对外提供的HTTP接口/usr/queryAll就是一个端点,端点就是对外提供的接口。
192.168.1.100和192.168.1.101这两个相同服务部署的节点就是实例,实例指同一服务可以部署多个。
SecureCRT的下载、安装( 过程非常详细!!值得查看)超Ren专属的博客-CSDN博客securecrt
SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单地说是Windows下登录UNIX或Linux服务器主机的软件。SecureCRT支持SSH,同时支持Telnet和rlogin协议。SecureCRT的SSH协议支持DES,3DES和RC4密码和密码与RSA鉴别。在今后的工作和学习中会经常的用到用来连接linux服务器。
agent探针可以让我们不修改代码的情况下,对java应用上使用到的组件进行动态监控,获取运行数据 发送到OAP上进行统计和存储。agent探针在java中是使用java agent技术实现的,不需要更改任何代 码,java agent会通过虚拟机(VM)接口来在运行期更改代码。 Agent探针支持 JDK 1.6 - 12的版本,Agent探针所有的文件在Skywalking的agent文件夹下。文件目录 如下;
Agent探针支持 JDK 1.6 - 12的版本,Agent探针所有的文件在Skywalking的agent文件夹下。文件目录 如下;
+-- agent +-- activations apm-toolkit-log4j-1.x-activation.jar apm-toolkit-log4j-2.x-activation.jar apm-toolkit-logback-1.x-activation.jar ... //配置文件 +-- config agent.config //组件的所有插件 +-- plugins apm-dubbo-plugin.jar apm-feign-default-http-9.x.jar apm-httpClient-4.x-plugin.jar ..... //可选插件 +-- optional-plugins apm-gson-2.x-plugin.jar ..... +-- bootstrap-plugins jdk-http-plugin.jar ..... +-- logs skywalking-agent.jar
部分插件在使用上会影响整体的性能或者由于版权问题放置于可选插件包中,不会直接加载,如果需要使用,将可选插件中的jar包拷贝到plugins包下。
例如optional-plugins bootstrap-plugins 不会加载。
由于没有修改agent探针中的应用名,所以默认显示的是Your_ApplicationName。我们修改下应用名 称,让他显示的更加正确。编辑agent配置文件:
agent/config/agent.config
# The service name in UI agent.service_name=${SW_AGENT_NAME:skywalking_springboot}
创建一个新的springboot项目
Configurations添加以下代码
#指定skywalking-agent -javaagent:D:\ProgramData\Observability\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar -Dskywalking.agent.service_name=serviceA #在skywalking上显示的服务名 # -DSW_AGENT_NAME=springboot-skywalking-demo #skywalking的collector服务的IP及端口 -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
打开自动刷新
删除cookie强制刷新skywalking界面
RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务.
本地过程调用:如果需要将本地student对象的age+1,可以实现一个addAge()方法,将student对象传入,对年龄进行更新之后返回即可,本地方法调用的函数体通过函数指针来指定。
远程过程调用:上述操作的过程中,如果addAge()这个方法在服务端,执行函数的函数体在远程机器上,如何告诉机器需要调用这个方法呢?
链接:https://www.jianshu.com/p/7d6853140e13
RPC(Remote Procedure Call Protocol):远程过程调用: 两台服务器A、B,分别部署不同的应用a,b。当A服务器想要调用B服务器上应用b提供的函数或方法的时候,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义传达调用的数据。 说白了,就是你在你的机器上写了一个程序,我这边是无法直接调用的,这个时候就出现了一个远程服务调用的概念。
RPC是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。 RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。
垂直应用架构(例如:MVC)
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
此时,用于加速前端页面开发的 Web框架(MVC) 是关键。
分布式服务架构(RPC)
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
此时,用于提高业务复用及整合的 分布式服务框架(RPC) 是关键。
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。
Dubbo是什么
Dubbo是:
一款分布式服务框架
高性能和透明化的RPC远程服务调用方案
SOA服务治理方案
每天为2千多个服务提供大于30亿次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点以及别的公司的业务中。
Dubbo优缺点 优点:
透明化的远程方法调用,像调用本地方法一样调用远程方法;只需简单配置,没有任何API侵入。
软负载均衡及容错机制,可在内网替代nginx lvs等硬件负载均衡器。 服务注册中心自动注册 & 配置管理,不需要写死服务提供者地址,注册中心基于接口名自动查询提供者ip。
使用类似zookeeper等分布式协调服务作为服务注册中心,可以将绝大部分项目配置移入zookeeper集群。
服务接口监控与治理 -Dubbo-admin与Dubbo-monitor提供了完善的服务接口管理与监控功能,针对不同应用的不同接口,可以进行 多版本,多协议,多注册中心管理。
缺点:
只支持JAVA语言
/* Navicat Premium Data Transfer Source Server : local_mysql Source Server Type : MySQL Source Server Version : 80027 Source Host : localhost:3306 Source Schema : skywalking Target Server Type : MySQL Target Server Version : 80027 File Encoding : 65001 Date: 06/04/2022 12:43:45 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_user -- ---------------------------- DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of t_user -- ---------------------------- INSERT INTO `t_user` VALUES (1, '张三'); INSERT INTO `t_user` VALUES (2, '李四'); INSERT INTO `t_user` VALUES (3, '王五'); SET FOREIGN_KEY_CHECKS = 1;
实现代码 在 philolor/ObservabilityLearning - 码云 - 开源中国 (gitee.com) skywalking-mysql中
http://localhost:8087/user/select
以其中一个为例
数据库总和性能统计
使用 skywalking. + 配置文件中的配置名作为系统配置项来进行覆盖.
为什么需要添加前缀?
agent的系统配置和环境与目标应用共享,所以加上前缀可以有效的避免冲突。
案例 通过 如下进行agent.service_name 的覆盖。
-Dskywalking.agent.service_name=skywalking_mysql
在JVM参数中的代理路径之后添加属性。
-javaagent:/path/to/skywalking-agent.jar=[option1]=[value1],[option2]=[value2]
案例 通过 如下进行agent.service_name 的覆盖
-javaagent:/path/to/skywalking-agent.jar=agent.service_name=skywalking_mysql
特殊字符 如果配置中包含分隔符( , 或者= ) , 就必须使用引号包裹起来
-javaagent:/path/to/skywalking-agent.jar=agent.ignore_suffix='.jpg,.jpeg'
案例 由于agent.service_name配置项如下所示:
#The service name in UI agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
可以在环境变量中设置SW_AGENT_NAME的值来指定服务名。
探针配置 > 系统配置 >系统环境变量 > 配置文件中的值 所以我们的启动命令可以修改为:(jar包情况下)
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/agent_mysql/skywalking-agent.jar Dskywalking.agent.service_name=skywalking_mysql -jar skywalking_mysql.jar &
或者
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/agent_mysql/skywalking-agent.jar=agent.service_name=skywalking_mysql -jar skywalking_mysql.jar &
代码
package com.yuge.controller; import org.apache.skywalking.apm.toolkit.trace.ActiveSpan; import org.apache.skywalking.apm.toolkit.trace.TraceContext; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author gyy * @date 2022/4/7 **/ @RestController public class PluginTestController { /** * 获取trace id,可以在RocketBot追踪中进行查询 */ @GetMapping("/getTraceId") public String getTraceId() { //使当前链路报错,并且提示报错信息 ActiveSpan.error(new RuntimeException("Test-Error-Throwable")); //打印info信息 ActiveSpan.info("Test-Info-Msg"); // 打印debug信息 ActiveSpan.debug("Test-debug-Msg"); return TraceContext.traceId(); } }
异常的信息包含了以下几个部分:
事件类型为error
调用方法时传递的异常类型RuntimeException
调用方法时传递的异常信息Test-Error-Throwable
异常堆栈
通过上述内容,我们可以根据业务来定制调用异常时的详细信息。
在开发过程中,有一些端点(接口)并不需要去进行监控,比如Swagger相关的端点。这个时候我们就 可以使用Skywalking提供的过滤插件来进行过滤。在skywalking_plugins中编写两个接口进行测试:
package com.yuge.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author gyy * @date 2022/4/7 **/ @RestController public class FilterController { /** * 此接口可以被追踪 * @return */ @GetMapping("/include") public String include() { return "include"; } /** * 此接口不可被追踪 * @return */ @GetMapping("/exclude") public String exclude() { return "exclude"; } }
这里添加-Dskywalking.trace.ignore_path=/exclude
参数来标识需要过滤哪些请求。
支持Ant Path表达式: /path/*
, /path/**
, /path/?
?
匹配任何单字符
*
匹配0或者任意数量的字符
**
匹配0或者更多的目录
调用结果
可以看出没有exclude
简介 Skywalking每隔一段时间根据收集到的链路追踪的数据和配置的告警规则(如服务响应时间、服务响应 时间百分比)等,判断如果达到阈值则发送相应的告警信息。发送告警信息是通过调用webhook接口完成,具体的webhook接口可以使用者自行定义,从而开发者可以在指定的webhook接口中编写各种告 警方式,比如邮件、短信等。告警的信息也可以在RocketBot中查看到。
以下是默认的告警规则配置,位于skywalking安装目录下的config文件夹下alarm-settings.yml文件 中:
直接使用默认规则 不用改
属性 | 含义 |
---|---|
metrics-name | oal脚本中的度量名称 |
threshold | threshold(阈值) 与metrics-name和下面的比较符号相匹配 |
op | 比较操作符,可以设定>,<,= |
period | 多久检查一次当前的指标数据是否符合告警规则,单位分钟 |
count | 达到多少次后,发送告警消息 |
silence-period | 在多久之内,忽略相同的告警消息 |
message | 告警消息内容 |
include-names | 本规则告警生效的服务列表 |
webhooks可以配置告警产生时的回调调用地址。
产生告警时会调用webhook接口,该接口必须是Post类型,同时接口参数使用RequestBody。参 数格式为:
[ { "scopeId": "1", "name": "skywalking-alarm", "id0": "c2t5d2Fsa2luZy1hbGFybQ==.1", "id1": "", "alarmMessage": "Response time of service skywalking-alarm is more than 1000ms in 3 minutes of last 10 minutes.", "startTime": 1649430924990 }, { "scopeId": "1", "name": "skywalking-alarm", "id0": "c2t5d2Fsa2luZy1hbGFybQ==.1", "id1": "", "alarmMessage": "Percentile response time of service skywalking-alarm alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000", "startTime": 1649430924990 } ]
故要写一个实体类接收:
package com.yuge.skywalkingtest.Entity; import lombok.Data; /** * @author gyy * @date 2022/4/8 **/ @Data public class AlarmMessage { private Long scopeId; private String name; private String id0; private String id1; private String alarmMessage; private Long startTime; }
更详细的alarm Apache SkyWalking 告警配置指南_慕课手记 (imooc.com)
开始的时候我们需要在其 VM 参数中添加 “javaagent: XXXX/apache-skywalking-apm-bin/agent/skywalking-agent.jar"。这里就 使用到了java agent技术。
Java agent是java命令的一个参数。参数 javaagent 可以用于指定一个 jar 包。
这个 jar 包的 MANIFEST.MF 文件必须指定 Premain-Class 项。
Premain-Class 指定的那个类必须实现 premain() 方法。 当Java 虚拟机启动时,在执行 main 函数之前,JVM 会先运行 -javaagent所指定 jar 包内 PremainClass 这个类的 premain 方法 。
如何使用java agent? 使用 java agent 需要几个步骤:
定义一个 MANIFEST.MF 文件,必须包含 Premain-Class 选项,通常也会加入Can-RedefineClasses 和 Can-Retransform-Classes 选项。
创建一个Premain-Class 指定的类,类中包含 premain 方法,方法逻辑由用户自己确定。
将 premain 的类和 MANIFEST.MF 文件打成 jar 包。
使用参数 -javaagent: jar包路径 启动要代理的方法。
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}