个人专题目录
Skywalking高级
1. Rpc调用监控
Skywalking(6.5.0)
支持的Rpc框架有以下几种:
- Dubbo 2.5.4 -> 2.6.0
- Dubbox 2.8.4
- Apache Dubbo 2.7.0
- Motan 0.2.x -> 1.1.0
- gRPC 1.x
- Apache ServiceComb Java Chassis 0.1 -> 0.5,1.0.x
- SOFARPC 5.4.0
使用Spring Boot和Dubbo搭建一个简单的服务提供方和服务消费方来测试Skywalking对于
Rpc调用的支持。可以使用资源文件夹下已经完成打包的skywalking_dubbo_consumer.jar
和
skywalking_dubbo_provider.jar
来进行测试。
1.1 服务提供方
pom文件:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.10.RELEASE
com.xubh
skywalking_dubbo_provider
0.0.1-SNAPSHOT
skywalking_dubbo_provider
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
com.alibaba.spring.boot
dubbo-spring-boot-starter
2.0.0
org.springframework.boot
spring-boot-maven-plugin
这里直接使用了dubbo-spring-boot-starter 这一dubbo与spring-boot集成的组件。
官方文档地址:https://github.com/alibaba/dubbo-spring-boot-starter/blob/master/README
_zh.md
application.properties:
spring.application.name=skywalking_dubbo_provider
spring.dubbo.server=true
spring.dubbo.registry=N/A
server.port=8086
为了简化环境搭建,采用了本地直接调用的方式,所以将注册中心写成N/A表示不注册到注册中
心。
IHelloService接口:
public interface IHelloService {
String hello();
}
HelloServiceImpl实现类:
import com.alibaba.dubbo.config.annotation.Service;
import com.itcast.api.IHelloService;
import org.springframework.stereotype.Component;
@Service(interfaceClass = IHelloService.class)
@Component
public class HelloServiceImpl implements IHelloService {
@Override
public String hello() {
return "hello skywalking";
}
}
SkywalkingDubboProviderApplication启动类:
@SpringBootApplication
//添加dubbo生效注解
@EnableDubboConfiguration
public class SkywalkingDubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SkywalkingDubboProviderApplication.class, args);
}
}
1.2 服务消费方
pom文件:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.10.RELEASE
com.xubh
skywalking_dubbo_consumer
0.0.1-SNAPSHOT
skywalking_dubbo_consumer
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
com.alibaba.spring.boot
dubbo-spring-boot-starter
2.0.0
org.springframework.boot
spring-boot-maven-plugin
application.properties:
spring.application.name=skywalking_dubbo_consumer
server.port=8085
TestController:
@RestController
public class TestController {
@Reference(url = "dubbo://127.0.0.1:20880")
private IHelloService helloService;
@GetMapping("/hello")
public String hello(){
return helloService.hello();
}
}
采用直连而非从注册中心获取服务地址的方式,在@Reference注解中声明
url = "dubbo://127.0.0.1:20880"
SkywalkingDubboConsumerApplication启动类:
@SpringBootApplication
//添加dubbo生效注解
@EnableDubboConfiguration
public class SkywalkingDubboConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SkywalkingDubboConsumerApplication.class, args);
}
}
1.3 部署方式
将skywalking_dubbo_consumer.jar 和skywalking_dubbo_provider.jar 上传
至/usr/local/skywalking 目录下。
复制两份agent,防止使用的冲突。
cd /usr/local/skywalking/apache-skywalking-apm-bin/
cp -r agent agent_dubbo_provider
cp -r agent agent_dubbo_consumer
vi agent_dubbo_provider/config/agent.config
修改agent_dubbo_provider配置中的应用名为:
# The service name in UI
agent.service_name=${SW_AGENT_NAME:dubbo_provider}
接着修改agent_dubbo_consumer:
vi agent_dubbo_consumer/config/agent.config
修改应用名:
# The service name in UI
agent.service_name=${SW_AGENT_NAME:dubbo_consumer}
先启动provider,等待启动成功。
#切换到目录下
cd /usr/local/skywalking
#启动provider
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/
agent_dubbo_provider/skywalking-agent.jar -jar
skywalking_dubbo_provider.jar &
启动consumer,等待启动成功。
#启动consumer
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/
agent_dubbo_consumer/skywalking-agent.jar -jar
skywalking_dubbo_consumer.jar &
调用接口,接口地址为:http://虚拟机IP地址:8085/hello
打开skywalking查看dubbo调用的监控情况。
仪表盘:
dubbo_provider 和dubbo_consumer 的服务已经出现,同时出现了两个接口分别是:
- /hello接口,是浏览器调用dubb_consumer的http接口
- com.xubh.api.IHelloService.hello()是dubbo_consumer调用dubbo_provider的dubbo接口
拓扑图:
已经表示出了一个调用的链路关系:
User(浏览器) ----> dubber_consumer ----> dubbo_provider
并且在服务的上方标识出了每个服务代表的内容,dubbo_consumer是SpringMvc的服务,而
dubbo_provider是Dubbo的服务。
追踪:
追踪图中显示本次调用耗时49ms,其中dubbo接口耗时29ms,那么另外的20ms其实是SpringMVC接口的开销,这样就能很好的评估出每个环节的耗时时间。
2. MySql调用监控
2.1 使用docker启动Mysql
systemctl start docker
使用docker命令启动mysql:
docker run -di --name=skywalking_mysql -p 33306:3306 -e
MYSQL_ROOT_PASSWORD=123456 centos/mysql-57-centos7
MYSQL_ROOT_PASSWORD环境变量指定root的密码为123456
在外部访问mysql了。使用工具连接mysql,端口为33306密码为123456。创建数据库skywalking。
执行建表语句:
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
插入几条数据:
insert into `t_user`(`name`) values ('张三'),('李四'),('王五');
2.2 Spring Data JDBC访问Mysql
创建一个Spring Boot工程,集成Spring Data JDBC。可以直接使用资源文件中提供的
skywalking_mysql.jar
。
pom文件:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.10.RELEASE
com.xubh
skywalking_mysql
0.0.1-SNAPSHOT
skywalking_mysql
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-data-jdbc
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
mysql
mysql-connector-java
5.1.46
org.springframework.boot
spring-boot-maven-plugin
引入了spring-boot-starter-data-jdbc ,由于使用了5.7的mysql版本,所以驱动版本固定为
5.1.46。
pojo类:
@Table("t_user")
public class User {
@Id
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
添加Table注解,修改表明为t_user。
dao接口:
public interface UserRepository extends CrudRepository {
}
controller:
@RestController
public class MysqlController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public List findAll(){
List result = new ArrayList<>();
userRepository.findAll().forEach((user) -> {
result.add(user);
});
return result;
}
}
由于Spring Data JDBC的findAll方法返回的是一个迭代器,所以需要遍历迭代器将数据进行返回。
启动类:
@SpringBootApplication
public class SkywalkingMysqlApplication {
public static void main(String[] args) {
SpringApplication.run(SkywalkingMysqlApplication.class, args);
}
}
application.properties:
spring.datasource.url=jdbc:mysql://localhost:33306/skywalking
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
server.port=8087
2.3 部署方式
将skywalking_mysql.jar 上传至/usr/local/skywalking 目录下。
复制agent,防止使用的冲突。
cd /usr/local/skywalking/apache-skywalking-apm-bin/
cp -r agent agent_mysql
vi agent_mysql/config/agent.config
修改agent_mysql配置中的应用名为:
# The service name in UI
agent.service_name=${SW_AGENT_NAME:skywalking_mysql}
启动skywalking_mysql应用,等待启动成功
#切换到目录下
cd /usr/local/skywalking
#启动spring boot
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/
agent_mysql/skywalking-agent.jar -jar skywalking_mysql.jar &
调用接口,接口地址为:http://虚拟机IP地址:8087/users
打开skywalking查看mysql调用的监控情况。
数据库仪表盘可以看到详细的数据库响应时长、吞吐量、SLA等数据。
拓扑图:
该图中已经表示出了一个调用的链路关系:
User(浏览器) ----> skywalking_mysql ----> localhost:33306
并且在服务的上方标识出了每个服务代表的内容,skywalking_mysql是SpringMvc的服务,而
localhost:33306是mysql的服务。
追踪:
追踪图中显示本次调用耗时5ms,其中spring MVC接口耗时4ms,那么另外的1ms是调用Mysql的耗时。
点击mysql的调用,可以看到详细的sql语句。可以很好的定位问题产生的原因,特别是在某些sql语句执行慢的场景下。
3. Skywalking常用插件
3.1 配置覆盖
使用Skywalking提供的配置覆盖功能通过启动命令动态指定服务名,这样agent只需要部署一
份即可。Skywalking支持的几种配置方式:
系统配置(System properties)
使用 skywalking. + 配置文件中的配置名作为系统配置项来进行覆盖.
- agent的系统配置和环境与目标应用共享,所以加上前缀可以有效的避免冲突。
- 通过 如下进行agent.service_name 的覆盖
-Dskywalking.agent.service_name=skywalking_mysql
探针配置(Agent options)
Add the properties after the agent path in JVM arguments.
-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'
系统环境变量(System environment variables)
由于agent.service_name配置项如下所示:
# The service name in UI
agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
可以在环境变量中设置SW_AGENT_NAME的值来指定服务名。
覆盖优先级
探针配置 > 系统配置 >系统环境变量 > 配置文件中的值
所以启动命令可以修改为:
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 &
3.2 获取追踪ID
Skywalking提供我们Trace工具包,用于在追踪链路时进行信息的打印或者获取对应的追踪ID。使用Spring Boot编写一个案例,也可以直接使用资源下的skywalking_plugins.jar 进行测试。
pom:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.10.RELEASE
com.xubh
skywalking_plugins
0.0.1-SNAPSHOT
skywalking_plugins
Demo project for Spring Boot
1.8
6.5.0
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.apache.skywalking
apm-toolkit-trace
${skywalking.version}
org.springframework.boot
spring-boot-maven-plugin
PluginController:
@RestController
public class PluginController {
//获取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();
}
}
使用TraceContext.traceId()可以打印出当前追踪的ID,方便在RocketBot中进行搜索。
ActiveSpan提供了三个方法进行信息的打印:
error方法会将本次调用变为失败状态,同时可以打印对应的堆栈信息和错误提示。
info方法打印info级别的信息。
debug方法打印debug级别的信息。
部署方式
将skywalking_plugins.jar 上传至/usr/local/skywalking 目录下。
启动skywalking_plugins应用,等待启动成功。
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/
agent/skywalking-agent.jar -
Dskywalking.agent.service_name=skywalking_plugins -jar skywalking_plugins.jar &
调用接口,接口地址为:http://虚拟机IP地址:8088/getTraceId
可以看到追踪ID已经打印出来,然后我们在RocketBot上进行搜索。
可以搜索到对应的追踪记录,但是显示调用是失败的,这是因为使用了ActiveSpan.error方法。点开追踪的详细信息:
异常的信息包含了以下几个部分:
1.事件类型为error
2.调用方法时传递的异常类型RuntimeException
3.调用方法时传递的异常信息Test-Error-Throwable
4.异常堆栈
通过上述内容,我们可以根据业务来定制调用异常时的详细信息。除了异常信息之外,还有info信息和debug信息也都会被打印。
3.3 过滤指定的端点
在开发过程中,有一些端点(接口)并不需要去进行监控,比如Swagger相关的端点。这个时候我们就
可以使用Skywalking提供的过滤插件来进行过滤。在skywalking_plugins中编写两个接口进行测试:
@RestController
public class FilterController {
//此接口可以被追踪
@GetMapping("/include")
public String include(){
return "include";
}
//此接口不可被追踪
@GetMapping("/exclude")
public String exclude(){
return "exclude";
}
}
部署方式
将skywalking_plugins.jar 上传至/usr/local/skywalking 目录下。
将agent中的/agent/optional-plugins/apm-trace-ignore-plugin-6.4.0.jar 插件拷贝到plugins目录中。
cd /usr/local/skywalking/apache-skywalking-apm-bin
cp optional-plugins/apm-trace-ignore-plugin-6.4.0.jar plugins/apm-trace-ignoreplugin-
6.4.0.jar
启动skywalking_plugins应用,等待启动成功。
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/
agent/skywalking-agent.jar -
Dskywalking.agent.service_name=skywalking_plugins -
Dskywalking.trace.ignore_path=/exclude jar skywalking_plugins.jar &
这里添加-Dskywalking.trace.ignore_path=/exclude参数来标识需要过滤哪些请求,支持Ant
Path 表达式:/path/* , /path/** , /path/?
- ? 匹配任何单字符
- 匹配0或者任意数量的字符
- ** 匹配0或者更多的目录
调用接口,接口地址为:
http://虚拟机IP地址:8088/exclude
http://虚拟机IP地址:8088/include
在追踪中进行查看:
exclude接口已经被过滤,只有include接口能被看到。
3.4 告警功能
告警功能简介
Skywalking每隔一段时间根据收集到的链路追踪的数据和配置的告警规则(如服务响应时间、服务响应时间百分比)等,判断如果达到阈值则发送相应的告警信息。发送告警信息是通过调用webhook接口完
成,具体的webhook接口可以使用者自行定义,从而开发者可以在指定的webhook接口中编写各种告警方式,比如邮件、短信等。告警的信息也可以在RocketBot中查看到。
以下是默认的告警规则配置,位于skywalking安装目录下的config文件夹下alarm-settings.yml 文件
中:
# Sample alarm rules.
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
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
service_p90_sla_rule:
# Metrics value need to be long, double or int
metrics-name: service_p90
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: 90% response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes
service_instance_resp_time_rule:
metrics-name: service_instance_resp_time
op: ">"
threshold: 1000
period: 10
count: 2
silence-period: 5
message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
# Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
# Because the number of endpoint is much more than service and instance.
#
# endpoint_avg_rule:
# metrics-name: endpoint_avg
# op: ">"
# threshold: 1000
# period: 10
# count: 2
# silence-period: 5
# message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes
webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
以上文件定义了默认的4种规则:
- 最近3分钟内服务的平均响应时间超过1秒
- 最近2分钟服务成功率低于80%
- 最近3分钟90%服务响应时间超过1秒
- 最近2分钟内服务实例的平均响应时间超过1秒
- 端点平均响应时间过去2分钟超过1秒
规则中的参数属性如下:
属性 | 含义 |
---|---|
metrics-name | oal脚本中的度量名称取值为oal脚本中的度量名,目前只支持long 、double 和int 类 |
Rule name | 规则名称,也是在告警信息中显示的唯一名称。必须以_rule 结尾,前缀可自定义 |
Include names | 该规则作用于哪些实体名称,比如服务名,终端名(可选,默认为全部) |
Exclude names | 该规则作不用于哪些实体名称,比如服务名,终端名(可选,默认为空) |
threshold | 阈值,与metrics-name和下面的比较符号相匹配 |
op | 比较操作符,可以设定>,<,= |
period | 多久检查一次当前的指标数据是否符合告警规则,单位分钟 |
count | 在一个Period窗口中,如果values超过Threshold值(按op),达到Count值,需要发送警报 |
silence-period | 在时间N中触发报警后,在TN -> TN + period这个阶段不告警。 默认情况下,它和Period一样,这意味着相同的告警(在同一个Metrics name拥有相同的Id)在同一个Period内只会触发一次 |
message | 告警消息内容 |
webhooks可以配置告警产生时的调用地址。
Webhook可以简单理解为是一种Web层面的回调机制,通常由一些事件触发,与代码中的事件回调类似,只不过是Web层面的。由于是Web层面的,所以当事件发生时,回调的不再是代码中的方法或函数,而是服务接口。例如,在告警这个场景,告警就是一个事件。当该事件发生时,SkyWalking就会主动去调用一个配置好的接口,该接口就是所谓的Webhook。
告警功能测试代码
SkyWalking的告警消息会通过 HTTP 请求进行发送,请求方法为 编写告警功能接口来进行测试,创建skywalking_alarm项目。可以直接使用资源中的 AlarmController: 该接口主要用于模拟超时,多次调用之后就可以生成告警信息。 WebHooks: 产生告警时会调用webhook接口,该接口必须是Post类型,同时接口参数使用RequestBody。参数格式为: 字段说明: AlarmMessage:实体类用于接口告警信息。 部署测试 修改告警规则配置文件,将webhook地址修改为: 然后重启skywalking。 将skywalking_alarm.jar 上传至/usr/local/skywalking 目录下。 启动skywalking_alarm应用,等待启动成功。 不停调用接口,接口地址为:http://虚拟机IP:8089/timeout 直到出现告警:查看告警信息接口:http://虚拟机IP:8089/show 在生产中使用可以在webhook接口中对接短POST
,Content-Type
为 application/json
,其JSON 数据实基于Listskywalking_alarm.jar
。@RestController
public class AlarmController {
//每次调用睡眠1.5秒,模拟超时的报警
@GetMapping("/timeout")
public String timeout(){
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "timeout";
}
}
@RestController
public class WebHooks {
private List
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine
[{
"scopeId": 1,
"scope": "SERVICE",
"name": "serviceA",
"id0": 12,
"id1": 0,
"ruleName": "service_resp_time_rule",
"alarmMessage": "alarmMessage xxxx",
"startTime": 1560524171000
}, {
"scopeId": 1,
"scope": "SERVICE",
"name": "serviceB",
"id0": 23,
"id1": 0,
"ruleName": "service_resp_time_rule",
"alarmMessage": "alarmMessage yyy",
"startTime": 1560524171000
}]
public class AlarmMessage {
private int scopeId;
private String name;
private int id0;
private int id1;
//告警的消息
private String alarmMessage;
//告警的产生时间
private long startTime;
public int getScopeId() {
return scopeId;
}
public void setScopeId(int scopeId) {
this.scopeId = scopeId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId0() {
return id0;
}
public void setId0(int id0) {
this.id0 = id0;
}
public int getId1() {
return id1;
}
public void setId1(int id1) {
this.id1 = id1;
}
public String getAlarmMessage() {
return alarmMessage;
}
public void setAlarmMessage(String alarmMessage) {
this.alarmMessage = alarmMessage;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
@Override
public String toString() {
return "AlarmMessage{" +
"scopeId=" + scopeId +
", name='" + name + '\'' +
", id0=" + id0 +
", id1=" + id1 +
", alarmMessage='" + alarmMessage + '\'' +
", startTime=" + startTime +
'}';
}
}
webhooks:
- http://127.0.0.1:8089/webhook
java -javaagent:/usr/local/skywalking/apache-skywalking-apmbin/
agent/skywalking-agent.jar -Dskywalking.agent.service_name=skywalking_alarm
-jar skywalking_alarm.jar
信、邮件等平台,当告警出现时能迅速发送信息给对应的处理人员,提高故障处理的速度。