Hystrix服务保护
服务雪崩效应
什么是服务雪崩:默认情况下tomcat只有一个线程池去处理客户端发送的服务请求,这样的话在高并发的情况下,如果客户端所有的请求堆积到同一个服务接口上,就会产生tomcat的所有线程去处理该服务接口的情况,可能会导致其他服务接口访问的时候产生延迟和等待
Tomcat有一个线程池,每一个线程处理客户端发送的每次请求
假设Tomcat最大请求数20,客户端发送100个请求,会发生80个请求产生延迟等待
tomcat设置最大线程数:
server: port: 8001 tomcat: max-threads: 10 # 设置最大线程数10
Hystrix简单介绍
Hystrix是国外知名的视频网站Netflix所开源的非常流行的高可用框架。Hystrix能够完美的解决分布式系统架构中打造高可用服务面临的一系列技术难题
1、在微服务中,服务保护框架Hystrix能帮我们解决哪些问题?
- 断路器
- 服务降级
- 服务熔断
- 服务隔离机制
- 服务雪崩效应
2、Hystrix“豪猪”,具有自我保护的能力。hystrix通过如下机制来解决雪崩效应问题:
服务降级
在高并发的情况下,防止用户一直等待,使用服务降级的方式,会返回一个友好的提示直接给客户端,不会去处理请求,而是调用fallBack本地方法,目的是为了提升用户体验
(在Tomcat中没有线程进行处理客户端请求的时候,不应该让用户一直转圈等待)
另外,需要注意的是,如果调用其他接口超时的时候(默认是1秒),如果在这一秒中没有及时响应的话,默认情况下业务逻辑是可以执行的(也就是请求对应的方法还是会走),但是会直接执行服务降级方法
服务熔断
服务熔断的目的是为了保护服务,在高并发的情况下,如果请求达到了一定数量(可以自己设置阈值),如果流量超出了设置的“阈值”,自动开启保护服务功能,然后使用服务降级方式返回一个友好的提示,所以服务熔断跟服务降级是一起使用的
服务隔离
服务隔离分为线程池隔离和信号量隔离,这里主要使用线程池隔离
线程池隔离采用服务隔离机制对线程池进行隔离,即每个服务接口都有自己独立的线程池,每个线程池互不影响。
缺点:CPU占用率非常高。但不是所有的接口都采用线程池隔离,只是核心关键的接口使用
Hystrix环境搭建
Maven依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
开启Hystrix断路器
配置在调用服务的客户端,这里是订单服务调用会员服务,所以放在订单服务中
# 开启hystrix断路器 feign: hystrix: enabled: true
配置服务保护
Hystrix有两种方式配置保护服务:通过注解和接口形式
下面介绍使用注解方式配置,使用注解方式配置非常简单
首先去启动类使用@EnableHystrix开启Hystrix服务保护机制
@SpringBootApplication @EnableEurekaClient @EnableFeignClients @EnableHystrix public class AppOrder { public static void main(String[] args) { SpringApplication.run(AppOrder.class, args); } }
然后在要访问的方法上面加上@HystrixCommand注解
// 解决服务雪崩效应 // fallbackMethod方法的作用:服务降级执行 // HystrixCommand默认开启线程池隔离方式,服务降级,服务熔断 @Override @HystrixCommand(fallbackMethod = "orderToMemberUserInfoHystrixFallback") @RequestMapping("/orderToMemberUserInfoHystrix") public ResponseBase orderToMemberUserInfoHystrix() { // 验证Hystrix默认使用的线程池隔离方式 System.out.println("线程池名称:" + Thread.currentThread().getName()); return memberServiceFeign.getUserInfo(); } public ResponseBase orderToMemberUserInfoHystrixFallback() { return setResultSuccess("返回一个友好的提示:服务器忙,请稍后再试"); }
到此Hystrix搭建完成
Hystrix禁止服务超时时间
在上面的服务降级里面提到过,如果在调用其他接口的时候,超过了1秒没有响应,那么会执行服务降级方法,那么在会员服务中,有一个方法故意等待了1.5秒才返回,因此我们在调用的时候,由于1.5秒大于了1秒,因此会返回服务降级方法的内容,这样就造成了没有高并发的情况下也出现了服务降级的情况,那么如何去避免这个问题呢?其实只要把Hstrix服务超时时间禁止就可以了
# hystrix禁止服务超时时间 hystrix: command: default: execution: timeout: enabled: false
当然,实际开发中不能直接禁止掉,最好设置一个超时时间,可以跟Feign客户端超时时间一致
定义统一的fallback接口
之前做服务降级的时候是在代码里面定义一个fallback方法,在@HystrixCommand中指定fallbackMethod为这个方法,但是这样写未免太过冗余了,所以应该使用一个类做统一的fallback接口
这种使用接口做服务降级的方式就不需要使用@HystrixCommand注解了,只需要在@FeignClient中指定fallback类即可,这个类实现Feign客户端的接口,实现里面的方法,如果哪个方法需要做服务降级,就在fallback类实现的相应方法中写上要提示的友好信息,最后将这个类设置到@FeignClient上即可,这样在调用xxxFeign.method()的时候就能做服务降级了
fallback类
@Component // 一定要将这个类添加到容器中 public class MemberServiceFallback extends BaseApiService implements MemberServiceFeign { @Override public User getMember(String name) { return null; } /** * 当远程调用member服务的getUserInfo()方法的时候需要做服务降级, * 一旦服务降级,就会来本地的这里调用这个方法 * @return */ @Override public ResponseBase getUserInfo() { return setResultSuccess("服务器忙,请稍后重试,使用类调用的fallback"); } }
Feign客户端注解标注上这个类
@FeignClient(name = "jx-member", fallback = MemberServiceFallback.class) public interface MemberServiceFeign extends IMemberService { }
此时再去调用memberFeign.getUserInfo()的时候,出现请求数过大就会自动服务降级调用本地的getUserInfo()了