前言
链路追踪介绍
对于一个大型的几十个,几百个微服务构成的微服务架构系统,通常会遇到下面的一系列问题。
- 如何串联整个调用链路,快速定位问题?
- 如何澄清各个微服务之间的依赖关系?
- 如何进行各个微服务接口的性能分析?
- 如何追踪各个业务流程的调用处理顺序?
Skywalking介绍
Skywalking是一个国产的开源框架,2015年有吴晟个人开源,2017年加入Apache孵化器,国人开源的产品,主要开发人员来自于华为,2019年4月17日Apache董事会批准SkyWalking成为顶级项目,支持Java、.Net、NodeJs等探针,数据存储支持Mysql、Elasticsearch等,跟Pinpoint一样采用字节码注入的方式实现代码的无侵入,探针采集数据粒度粗,但性能表现优秀,且对云原生支持,目前增长势头强劲,社区活跃。
Skywalking是分布式系统的应用程序性能监视工具,专为微服务,云原生架构和基于容器(Docker,K8S,Mesos)架构而设计,它是一款优秀的APM(Application Performance Management)工具,包括了分布式追踪,性能指标分析和服务依赖分析等。
链路追踪框架对比
目前市面上开源的APM系统主要有CAT、Zipkin、Pinpoint、SkyWalking,大都是参考Google的Dapper实现的
功能和技术方案对比
- Zipkin是Twitter开源的调用链路分析工具,目前基于Spingcloud sleuth得到了广泛的应用,特点是轻量,部署简单。
- Pinpoint:一个韩国团队开源的产品,运用了字节码增强技术,只需要在启动时添加启动参数即可,对代码无侵入,目前支持Java和PHP语言,底层采用HBase来存储数据,探针收集的数据粒度非常细,但性能损耗大,因其出现的时间较长,完成度也很高,应用的公司较多
- Skywalking是本土开源的基于字节码注入的调用链路分析以及应用监控分析工具,特点是支持多种插件,UI功能较强,接入端无代码侵入。
- CAT是由国内美团点评开源的,基于Java语言开发,目前提供Java、C/C++、Node.js、Python、Go等语言的客户端,监控数据会全量统计,国内很多公司在用,例如美团点评、携程、拼多多等,CAT跟下边要介绍的Zipkin都需要在应用程序中埋点,对代码侵入性强。
下载
APM包下载地址: https://skywalking.apache.org/downloads/
这边下载的是 v9.0.0 版本
APM 全称为: Application Performance Management (应用程序性能监视工具),下载的APM包里面就已经包含了skywalking 服务端和UI前端,UI前端是一个web项目,用于展示链路追踪的数据;
注意事项:skywalking在8.8.0版本以后将agent单独拆分了出来,所以若要使用8.8.0版本以后的,需要下载apm和agent两个压缩包。因为我选择的是9.0.0版本。刚刚已经下载了apm包,所以还需要在下载 agent 的压缩包,
agent包下载地址:https://dlcdn.apache.org/skywalking/java-agent/8.11.0/apache-skywalking-java-agent-8.11.0.tgz
将这2个文件下载完并且解压缩后会得到2个目录:
apache-skywalking-apm-bin
skywalking-agent
配置
打开 .\apache-skywalking-apm-bin\config\application.yml
文件
skywalking-web-ui服务会占用 8080 端口, 修改端口可以修改webapp/webapp.yml
启动成功后会启动两个服务,一个是skywalking-oap-server,一个是skywalking-web-ui,
skywalking-oap-server服务启动后会暴露11800 和 12800 两个端口:
11800
:收集监控数据的端口12800
:接受前端请求的端口
修改端口可以通过 config/applicaiton.yml 文件来修改
agent 配置
修改探针默认配置 skywalking-agent/config/agent.config
# 将127.0.0.1修改为OAP所在的ip地址
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
# 默认值为:-1 (全量收集链路),在访问量较少时,链路全量收集不会对系统带来太大负担,能够完整的观测到系统的运行状况。但是在访问量较大时,全量的链路收集,对链路收集的客户端(agent探针)、服务端(SkyWalking OAP)、存储器(例如说 Elastcsearch)都会带来较大的性能开销,甚至会影响应用的正常运行。在访问量级较大的情况下,往往会选择抽样采样,只收集部分链路信息。agent.sample_n_per_3_secs 配置项,设置每 3 秒可收集的链路数据的数量。
agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:1}
通过docker安装skywalking 9.0.0
docker中,服务端和 ui是分开的,所以需要安装2个docker
# 服务端
docker run --name oap --restart always -d -p 11800:11800 -p 12800:12800 apache/skywalking-oap-server:9.0.0
# Ui 端
docker run --name oap-ui --restart always -d -e SW_OAP_ADDRESS=http://192.168.31.250:12800 -p 8880:8080 apache/skywalking-ui:9.0.0
启动
根据系统不同,windows双击 startup.bat
,linux 通过命令 nohup ./startup.sh &
后台运行
因为我用的windows,启动后会开启2个黑窗口
在浏览器输入地址: http://localhost:8080
即可访问 skywalking
追踪测试
准备2个服务,user 服务 和 order 服务,通过openfeign远程调用,
order 服务的controller层代码如下
import com.alibaba.cloud.client.OpenFeignOrderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/open/feign")
public class OpenFeignController {
@Autowired
private OpenFeignOrderClient openFeignOrderClient;
/**
* 调用远程openFeign 接口
* @return
*/
@RequestMapping("/getOrderList")
public String getOrderList() {
return openFeignOrderClient.getOrderList();
}
}
openFeign 接口 ,将此文件放到公共模块,user和order服务都引用这个公共模块;
import com.alibaba.cloud.fallback.OpenFeignFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "order-demo",path = "order",fallback = OpenFeignFallBack.class)
public interface OpenFeignOrderClient {
/**
* 获取订单列表
* @return
*/
@RequestMapping("/getOrderList")
String getOrderList();
}
降级回调处理,也放到公共模块中
import com.alibaba.cloud.client.OpenFeignOrderClient;
import org.springframework.stereotype.Component;
/**
* 降级回调类
*/
@Component
public class OpenFeignFallBack implements OpenFeignOrderClient {
@Override
public String getOrderList() {
return "openFeign远程调用暂时不可用,可能的原因是远程服务未开启,或者是远程服务超时或者报错导致";
}
}
order服务添加一个controller,实现openFeign接口,其中,通过代码int i=1/0;
来抛出异常,
import com.alibaba.cloud.client.OpenFeignOrderClient;
import com.alibaba.cloud.dto.UserDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/order")
public class OrderController implements OpenFeignOrderClient {
// openFeign 的实现接口
@Override
public String getOrderList() {
int i=1/0;
return "get Order list success! ";
}
}
在启动前,两个服务都需要添加vm参数
user
-javaagent:D:\java\skywallking\skywalking-agent\skywalking-agent.jar
-Dskywalking.agent.service_name=user_app
order
-javaagent:D:\java\skywallking\skywalking-agent\skywalking-agent.jar
-Dskywalking.agent.service_name=order_app
skywalking-agent.jar
是什么文件
刚刚我们不是下载了2个压缩包吗,skywalking-agent.jar
这个文件就在另一个压缩包内
启动user服务和order服务
启动后,在skywalking上就可以看到这2个服务了
在浏览器访问地址http://localhost:8089/open/feign/getOrderList
, 毫无疑问,报错了,因为有降级路基,所以页面上直接显示了友好提示,
但order服务确实是报错了
接下来我们进入到user服务的链路追踪
然后切换到 Topology 页,这里可以看直观地看到服务之间的调用关系,第一个User表示是客户端,谁调用谁都能看的很清楚; 但是必须先调用过之后 skywalking 才知道是谁调用的谁,没调用的话,是看不到他们之间的关系的,右上角有个调用深度,可以查看最多5级调用,因为我这边只有3个,所以调整到3就够了
然后切换到 Trace 页,这里才是真正的链路追踪,可以看到每个服务之间调用的 controller 层接口; 红色表示报错的接口,蓝色表示正常访问的接口;
然后点击最下面的controller 链接,就可以看到抛出的具体异常了
除零异常,跟order的控制台报的错误是一样一样的