1.概述:
(1)在前面我们使用SpringCloud 来大家Eureka 服务集群,还是配置服务器,网关节点,都可以扩展,一旦集群中的服务数量增多,并且他们之间存在复杂的依赖关系,那么管理他们将会变成一件很棘手的事情。
当外部用户向集群发送请求时,这些请求将会调用多个服务,每个服务又会依赖其他的服务,此时如果出现了异常,超时等情况,排查问题将会变得很难,所以我们需要清楚的知道哪一个缓解出现了问题。Sleuth可以和Zipkin,Apache HTrace和ELK等数据分析,服务跟踪系统进行整合,为服务跟踪,解决问题提供了便利。
2.Sleuth的基本概念
微服务可以将整个的系统拆分为无数个子系统,于是这样一来就有可能出现几种可怕的场景:
· 代码的调试:
|- 你的系统有可能变慢了,于是这个时候就需要去追踪每一个微服务的执行的速度;
|- 如果现在你的微服务采用了串联的方式进行了互相调用,那么如何确认某一个微服务出现了问题呢?
· 微服务混合调用:
|- 现在微服务变为了环形调用,那么这些关系该如何描述出来?
在创建微服务的时候一定要有一些合适的开发契约,所有的开发者以及服务的调用者要按照统一的方式进行程序的调用处理, 这样才可以成为一个优秀的微服务设计。
所以在 SpringCloud 之中提供的 Sleuth 技术就可以实现微服务的调用跟踪,也就是说它可以自动的形成一个调用连接线,通过这个连接线使得开发者可以轻松的找到所有微服务间关系,同时也可以获取微服务所耗费的时间, 这样就可以进行微服务调用状态的监控以及相应的数据分析。
Span(跨度) 里面包含有如下内容:
· cs-Client Sent:客户端发出一个请求,描述的是一个 Span 开始;
· sr-Server Received:服务端接收请求,利用 sr-cs 就属于发送的网络延迟;
· ss-Server Sent:服务端发送请求(回应处理),ss-sr 就属于服务端的消耗时间;
· cr-Client Received:客户端接收到服务端数据,cr-ss 就表示回复所需要的时间。
3.项目准备
1.创建Eureka服务注册中心微服务,图书微服务,支付微服务,销售微服务
代码在最下面。
2.构建ZipKin服务器项目
搭建ZipkinServer
值得注意的是:
Spring Boot 2.0之后,使用EnableZipkinServer创建自定义的zipkin服务器已经被废弃,将无法启动.ZipkinServer 由官方提供jar包。我们只需要到官网下载即可。地址:https://zipkin.io/pages/quickstart , 找到latest release 进行下载。
我这里是windows 环境,打开cmd java -jar zipkin-server-xxx.jar 启动。 访问 http://localhost:9411/
然后可以看到Zipkin主页了
然后依次启动注册中心, book服务,付款服务,消费服务。
通过消费服务接口进行消费。在依赖中可以看到。
book服务
server: port: 8001 spring: application: name: sleuth-book-service zipkin: base-url: http://localhost:9411 sleuth: sampler: percentage: 1.0 #配置跨度数据的采样百分比,默认值是0.1 为了查看效果这里配置成1 。 #实际中按具体要求配置,避免服务器的负载 eureka: client: service-url: defaultZone: http://localhost:8888/eureka/ logging: level: root: org.springframework.cloud.sleuth: debug
控制器:
@RestController public class BookService { @RequestMapping(value = "/findBookById/{bid}",method = RequestMethod.GET, consumes = MediaType.APPLICATION_JSON_VALUE) public Book findBookById(@PathVariable("bid") Integer bid, HttpServletRequest request){ Book book=new Book(); book.setBid(bid); book.setName("葵花宝典"); book.setMessage("端口号:"+request.getServerPort()); return book; }
付款服务
server: port: 8002 spring: application: name: sleuth-pay-service zipkin: base-url: http://localhost:9411 sleuth: sampler: percentage: 1.0 #配置跨度数据的采样百分比,默认值是0.1 为了查看效果这里配置成1 。 #实际中按具体要求配置,避免服务器的负载 eureka: client: service-url: defaultZone: http://localhost:8888/eureka/
控制器接口:
@RestController
public class PayController {
@RequestMapping(value = "/pay{pid}",method = RequestMethod.GET,consumes = MediaType.APPLICATION_JSON_VALUE)
public String pay(@PathVariable("pid") Integer pid){
System.out.println(pid+"付款成功");
return "success";
}
}
销售服务:
server: port: 9000 eureka: instance: hostname: localhost client: service-url: defaultZone: http://localhost:8888/eureka/ spring: application: name: sleuth-sale-service zipkin: base-url: http://localhost:9411 sleuth: sampler: percentage: 1.0 #配置跨度数据的采样百分比,默认值是0.1 为了查看效果这里配置成1 。 #实际中按具体要求配置,避免服务器的负载 #打开熔断器开关 feign: hystrix: enabled: true #设置Hystrix超时时间为500ms 默认为1000ms 针对某个方法 # 服务提供者接口方法中线程休眠了 800ms 访问服务失败 就会调用回退方法 #如果是针对全局设置, #hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=500 #如果是针对某个客户端 #hystrix.command.CommandKey.execution.isolation.thread.timeoutInMilliseconds=500 #其中的CommandKey格式为:接口名#方法名 hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 1000 circuitBreaker: requestVolumeThreshold: 3 threadpool: default: coreSize: 500 #并发执行的最大线程数,默认10
feign客户端:
@FeignClient(value= "sleuth-book-service") public interface BookClient { @RequestMapping(value = "/findBookById/{bid}",method = RequestMethod.GET, consumes = MediaType.APPLICATION_JSON_VALUE) Book findBookById(@PathVariable("bid") Integer bid); }
@FeignClient(value = "sleuth-pay-service") public interface PayClient { @RequestMapping(value = "/pay{pid}",method = RequestMethod.GET,consumes = MediaType.APPLICATION_JSON_VALUE) public String pay(@PathVariable("pid") Integer pid); }
控制器:
@RestController @Configuration public class InvokerController { @Autowired private BookClient bookClient; @Autowired private PayClient payClient; @RequestMapping(value = "/sale",method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public Book ronter(){ Book book=bookClient.findBookById(1); payClient.pay(1); return book; } }
启动类:
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients @EnableCircuitBreaker//熔断器注解 @EnableHystrixDashboard//Hystrix监控 public class SleuthSaleServiceApplication { public static void main(String[] args) { SpringApplication.run(SleuthSaleServiceApplication.class, args); } }