一。sleuth简介
微服务架构上通过业务来划分服务的,通过REST调用,对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。如何清晰地记录服务的调用链路,方便将来问题的定位,Spring cloud sleuth组件正是为了解决微服务跟踪的组件。
- sleuth在微服务调用时跟踪产生日志
- zipkin是一个链路日志接收服务器(聚合所有日志),拥有ui可以清晰展示链路调用细节,zipkin日志保存
在内存中 只适合保存少量的日志 sleuth一般默认给日志进行 10%的抽样 发送给zipkin
术语(参考http://cloud.spring.io/spring-cloud-static/Dalston.SR5/single/spring-cloud.html#_spring_cloud_sleuth 45.1章节)
Span:基本工作单元,例如,发送一次rpc(一次微服务调用)就会新建一个span,span通过一个64位ID唯一标识,trace以另一个64位ID表示,span还有其他数据信息,比如摘要、时间戳事件、关键值注释(tags)、span的ID、以及进度ID(通常是IP地址)
span在不断的启动和停止,同时记录了时间信息,当你创建了一个span,你必须在未来的某个时刻停止它。
Trace:一系列spans组成的一个树状结构,例如,如果你正在跑一个分布式大数据工程,可以认为一个请求的产生,从第一次微服务调用到多个微服务的调用 直到结果返回 就是一个trace过程 中间 包含多次微服务调用 每次 都是一个Span。
Annotation:用来及时记录一个事件的存在,一些核心annotations用来定义一个请求的开始和结束
- cs - Client Sent -客户端发起一个请求,这个annotion描述了这个span的开始
- sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络延迟
- ss - Server Sent -注解表明请求处理的完成(当请求返回客户端),如果ss减去sr时间戳便可得到服务端需要的处理请求时间
- cr - Client Received -表明span的结束,客户端成功接收到服务端的回复,如果cr减去cs时间戳便可得到客户端从服务端获取回复的所有所需时间
将Span和Trace在一个系统中使用Zipkin注解的过程图形化:
二。sleuth+zipkin追踪链路
模拟项目场景
注册中心 REGCENTER
用户微服务 USERSERVICE
用户界面 USERUI
zipkin服务器 ZIPKINSERVER
USERUI登录界面 登录时 调用USERSERVICE的微服务
USERUI和USERSERVICE添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
添加配置(其他注册和发现参考其他文章)
spring:
zipkin:
base-url: http://localhost:9411
baseUrl: http://localhost:9411
enabled: true
表示两个服务之间相互调用 都需要记录日志 上传到 zipkin服务器上
两个微服务的main方法添加(默认只是抽样 10% 这个bean表示所有的数据都上传)
参考(http://cloud.spring.io/spring-cloud-static/Dalston.SR5/single/spring-cloud.html#_sampling)
@Bean
public AlwaysSampler defaultSampler(){
return new AlwaysSampler();
}
USERSERVICE控制层添加登录方法 用于被调用
@PostMapping("/login")
public Result login(@RequestBody User user) {
User queryUser = service.queryUser(user);
Result r=new Result();
if(queryUser==null) {
r.setCode(1);
r.setMsg("login Fail");
}
return r;
}
USERUI添加登录界面在当前项目控制层调用微服务
String url="http://USERSERVICE/login";
@Autowired
RestTemplate rst;
@RequestMapping("/login")
public Result login(User user) {
ResponseEntity<Result> postForEntity = rst.postForEntity(url, user, Result.class);
Result body = postForEntity.getBody();
return body;
}
添加ZIPKINSERVER项目
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
配置
server:
port: 9411
spring:
application:
name : zipkinserver
主类
package cn.ps;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import zipkin.server.EnableZipkinServer;
@SpringBootApplication
@EnableZipkinServer
public class ZipKinServerMain {
public static void main(String[] args) {
SpringApplication.run(ZipKinServerMain.class, args);
}
}
启动zipkinserver 访问 http://localhost:9411
开始在微服务上互相调用 比如访问 userui调用 userservice 点击 9411上 dependencies导航栏
可以通过 find a trace导航栏 查看所有的trace和span
查看span的事件