微服务的出现,的确解决了一些业务痛点
,但是也造成了新的问题比如随着调用链的拉长,如果想要知道请求为什么这么慢,这个请求到底经历了哪些环节,又依赖了哪些东西,在微服务架构中定位这些问题并且解决是比较麻烦的。
什么是调用链呢?
A服务调用B服务也可以说是一个调用链,即使是同一个服务中的一个方法调用到另一个方法,也可以说是一个调用链。
以前单体应用中,排查问题往往只需要到这台应用的服务,查看日志基本就能把问题解决了。但是在微服务系统中,一般是分布式部署的,这也就给排查增加了难度,如果把一台台服务器登录上找问题,既麻烦又耗时。
为了解决这些问题,业内已经有了分布式链路追踪的解决方案,比如使用ZipKin、SkyWalking等。
SkyWalking是基于OpenTracing实现的开源项目,2017年12月8日已进入Apache孵化器。
是一个APM(应用性能监控)系统,专为微服务、云原生架构和基于容器(Docker、k8s、Mesos)架构而设计。通过探针收集应用的指针,并进行分布式链路追踪。SkyWalking会感知服务之间的调用链路关系,形成相应的统计数据。它的特性如下:
SkyWalking的整体架构:
那么SkyWalking的存储介质,笔者这s选择使用Elasticsearch,先到Elasticsearch的官网下载。
windows版本下载地址,选择下载了一个7.0.0
版本的。
这里笔者就使用windows版本了,需要linux版本或其他可以自行查阅资料。
下载解压后,到config/elasticsearch.yml
中修改下集群名:
cluster.name: my-application
后直接到bin目录下,执行elasticsearch.bat
即可执行es服务,默认端口9200
启动完毕后,访问下localhost:9200
,得到如下信息即是安装成功
完成后,再去安装SkyWalking。注意这里cluster.name
是my-application。后面skywalking需要用。
下载地址:https://skywalking.apache.org/downloads/
下载过慢或者下载无反应的,可以尝试使用国内镜像地址去下载,https://mirrors.cloud.tencent.com/apache/skywalking
笔者使用7.0.0版本的,地址在这里:https://www.apache.org/dyn/closer.cgi/skywalking/7.0.0/apache-skywalking-apm-es7-7.0.0.tar.gz
这里提供下网盘资源:
链接:https://pan.baidu.com/s/1lQoMDFIH3PYGCla3PtIIRg
提取码:2a96
下载解压后,得到如下目录:
start.bat
,linux系统启动.sh的文件到
config/application.yml
中修改配置
storage:
selector: ${SW_STORAGE:elasticsearch7}
修改elsticsearch
的nameSpace和ClusterNodes,这里nameSpace是前面配置的es的集群名称
storage:
selector: ${SW_STORAGE:elasticsearch7}
elasticsearch7:
nameSpace: ${SW_NAMESPACE:"my-application"}
clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
注意:SkyWalking默认使用的端口是8080、11800、12800,如有占有,可去config/application.yml
和webapp/application.yml
中修改
启动
执行startup.bat
启动
访问localhost:8080
即可进入skywalking的可视化界面
IDEA使用agent主要使用于本地开发环境,需要又agent文件夹,然后加上启动参数即可。
找到两个springboot微服务项目,然后在它们的IDEA启动配置中,增加参数:
transaction的
-javaagent:D:\env\envir\skywalking7\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=transaction-distribution
-Dskywalking.collector.backend_service=localhost:11800
order的
-javaagent:D:\env\envir\skywalking7\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=transaction-order
-Dskywalking.collector.backend_service=localhost:11800
完事儿后,启动它们。
调用一个接口,执行它们。
拓扑图
到skywalking的拓扑图页面
可以看到真题的技术架构及调用关系。
追踪
到skywalking的追踪页面
可以看到所有的执行记录,并且将这些详细到:发生在哪个类哪个方法中,如执行sql查询的那条,点击后,我们甚至可以看到sql的执行信息。
还可知接口的执行时间分布,以及采用的技术
如上图:/createOrder
接口总执行2.4s,/distribution
是使用feign调用的,且执行了1s左右。
有时可能不需要采集某个端点的数据,如心跳之类的请求,不是那么重要。可以设置忽略它们,意味着包含这些路径的追踪信息不会被agent发送到collector中。
将skywalking中的agent/optional-plugins
的apm-trace-ignore-plugin-7.0.0.jar
拷贝至我们的agent/plugins
中
在IDEA中做启动配置,我们模拟将/createOrder
和/distribution
接口忽略
-javaagent:D:\env\envir\skywalking7\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=transaction-distribution
-Dskywalking.collector.backend_service=localhost:11800
-Dskywalking.trace.ignore_path=/createOrder
-javaagent:D:\env\envir\skywalking7\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=transaction-order
-Dskywalking.collector.backend_service=localhost:11800
-Dskywalking.trace.ignore_path=/distribution
ignore_path
这个参数可以支持表达式:
/path/*
、path/**
、/path/?
?
表示匹配任意单字符,*
表示匹配0个或任意数量字符,**
表示匹配0或更多的目录
配置后,在调用匹配规则的接口路径时,agent就不会再采集这些接口的数据了。
除此外还有另一种方式
同样是需要先将skywalking中的agent/optional-plugins
的apm-trace-ignore-plugin-7.0.0.jar
拷贝至我们的agent/plugins
中
然后去配置agent/config/agent.config
文件忽略端点,服务每次启动都会去读取这个配置文件。
trace.ignore_path==${SW_AGENT_TRACE_IGNORE_PATH:/createOrder, /distribution}
告警功能是skywalking的一大特色。Skywalking会定时把采集到的数据和配置的告警规则进行对比,如果满足阈值条件,则会出发警告。
Skywalking允许用户基于webhook(网络钩子)的规范,自定义触发告警之后的逻辑,如发短信、发邮件、电话、公众号通知等。
Skywalking程序路径下的config/alarm-settings.yml
文件就是告警的规则。
rules:
service_resp_time_rule: # 服务响应时间规则
metrics-name: endpoint_percent # 名称
threshold: 75 # 阈值
op: < # 小于
period: 10 # 间隔时间
count: 3 # 次数
silence-period: 10 # 告警发送多少分钟内警告不会重复发送
message: Successful rate of endpoint {name} is lower than 75%
#webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
webhooks中就是触发警告后,需要执行的操作。
我们可以自己做个触发钩子后的执行操作接口
public class AlarmMessage {
private Integer scopeId; // 作用域
private String name; // 目标作用域下的实体名称
private Integer id0; // 作用域下的实体ID,与名称相匹配
private Integer id1;
private String ruleName; // alarm-setting.yml中的配置规则
private String alarmMessage; // 告警信息
private Long startTime; // 告警产生时间
// get.set.toString()方法省略
}
@RequestMapping("/notify")
public void alarm(@RequestBody List<AlarmMessage> alarmMessages) {
alarmMessages.forEach(value -> System.out.println(value.toString()));
}
webhooks:
- http://127.0.0.1:9002/notify
重启skywalking及两个微服务项目,多次调用/createOrder
接口(模拟的超时报错),这里记得把忽略的端点给放开,否则skywalking是发不了告警的。
可看到告警
一栏中的
看到控制台打印的数据:
Skywalking的性能分析能帮助用户很容易找到性能问题,并且不需要代码埋点等操作。Skywalking的性能分析是对业务周期性保存快照操作,资源消耗小。
到Skywalking UI的性能剖析窗口,点击新建任务,如创建/createOrder
接口的任务。
然后可以调用几次/createOrder
接口,刷新页面,选中刚刚创建的任务,右侧出现createOrder的信息,选中,点击分析按钮。
调用/createOrder的流程,使用的技术,服务名,耗时,栈信息等一览无余。
点击查看能看到这个步骤的详细信息,执行的具体操作,抛出的异常。
IDEA中使用agent一般用于本地开发环境,若正式环境,一般使用Tomcat或jar包的方式启动应用。
Linux系统Tomcat使用agent
linux系统中修改tomcat的bin/catalina.sh
文件,加入代码
CATALINA_OPTS="$CATALINA_OPTS -javaagent:/root/agent/skywalking-agent.jar -Dskywalking.agent.service_name=transaction-distribution -Dskywalking.collector.backend_service=localhost:11800";
export CATALINA_OPTS
Windows系统Tomcat使用agent
windows系统中修改tomcat的bin/catalina.bat
文件setlocal
下,加入代码
set CATALINA_OPTS="-javaagent:D:\env\envir\skywalking7\agent\skywalking-agent.jar -Dskywalking.agent.service_name=transaction-distribution -Dskywalking.collector.backend_service=localhost:11800";
jar包使用agent
启动时的命令
java -javaagent:D:\env\envir\skywalking7\agent\skywalking-agent.jar -Dskywalking.agent.service_name=transaction-distribution -Dskywalking.collector.backend_service=localhost:11800 -jar transaction-distribution.jar
Skywalking的功能很强大,能看到项目中的很多隐私信息(项目架构、调用链路、sql语句等),自然不希望其他无关人员能看到。那么通常设置账号密码的方式。
在skywalking6.x版本中能配置,但是在7.x版本中被移除了,作者提出可以使用nginx配置账号和密码:
使用nginx配置账号密码登录主要是依靠ngx_http_auth_basic_module
模块。
下面是用nginx的增强版,OpenResty配置账号和密码登录。OpenResty的安装可以自行查阅资料。
安装和配置
yum install -y httpd-tools
htpasswd -b -c /usr/local/openresty/passwd wlh wlh
-b参数:用户创建passwdfile,如果passwdfile存在,那么它会重写
-c参数:允许命令行中一起输入账号和密码
nginx/conf/nginx.conf
配置文件,修改server中的内容就行了server{
listen 80;
server_name localhost;
location / {
auth_basic "Please input password"; # 提示信息
auth_basic_user_file /user/local/openrestry/passwd; # 存放账号密码的文件
proxy_pass http://localhost:8080; # 代理到8080端口
}
}
最后linux系统记得放开需要的端口。重启OpenResty然后访问主机http://192.168.1.41
(默认80端口),就会弹框提示需要输入账号和密码了。