SpringCloud:使用Hystrix服务熔断-4

 

       Hystrix:英文意思豪猪,全身是刺,是一种保护机制,是Netflix开源的一个延迟和容错库,用于隔离访问远程服务,防止出现级联失败。如微服务中,一个请求,可能需要调用多个微服务的接口才能实现。如果此时,某个服务出现异常(阻塞情况),用户就不会得到响应,则tomcat的这个线程就不会被释放,而越来越多的用户请求到来,越来越多的线程会阻塞,但服务器支持的线程和并发数是有限的,请求一直阻塞,就会导致服务器资源耗尽。例子:
      如工厂生产汽车,如果工厂中一直缺少某个零件,那么这台车就不能完成组装,会处于等待状态,一直到这零件到位。如果此时有很多工人在组装的车都需要这个零件,那么整个工厂都会处于等待状态,工厂生产就会瘫痪。

Hystrix解决雪崩问题的手段有2个:
1,线程隔离
2,服务熔断

线程隔离,服务降级的原理:
        Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满,并不会影响到其他服务,调用将被立即拒绝,默认不采用排队,加速失败判定时间。
用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问。如果线程池已满,或者请求超时,则会进行降级处理。用户请求的服务出现故障是不会被阻塞,更不会一直处于等待或者看到系统崩溃消息,系统会给用户返回一个友好的提示结果,如“”“此时服务器繁忙”等等。


什么是服务降级?
优先保证核心服务,而非核心服务不可用或弱可用。例子:如淘宝,双11活动的时候,可以先把不重要的服务停止了,如关闭淘宝直播等,保证核心服务双11活动正常运行。

触发Hystrix服务的主要条件:
1,线程池满了
2,访问超时

 

下面以consumer-demo、products-service、Eureka-server前面的例子,再记录一下Hystrix,一般是服务的消费方做服务的降级处理。(触发Hystrix:访问超时)
1,consumer-demo引入依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

2,启动类上加注解@EnableCircuitBreaker

//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker //服务的熔断
@SpringCloudApplication //包含上三个注解,所有配置这个注解可替代以上三个
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    @Bean
    @LoadBalanced //负载均衡,加该注解所有的RestTemplate请求会被LoadBanlancerInterceptor拦截
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

3,编写降级逻辑

3.1,方式1,服务降级写在方法上。

@RestController
@RequestMapping("/products")
//方式1,服务降级写在方法上。
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping(value="/{id}")
    
    @HystrixCommand(fallbackMethod = "queryFallback")//开启失败处理的标志
    //请求成功的执行方法
    public String queryByid(@PathVariable("id")String id){
        //负载均衡
        String url="http://products-service/products/"+id;
        String p = restTemplate.getForObject(url, String.class);
        return p;
    }
    //三,编写降级逻辑
    //熔断降级的逻辑的返回值要和原来的方法逻辑保持一致。如果在方法上,那参数也要一致。

    //请求失败的执行方法
    public String queryFallback(String id){
        return "对不起,访问服务超时,请稍后再试";
    }
   
}

3.2,方式2,服务降级写在类上。

@RestController
@RequestMapping("/products")
//方式2,服务降级写在类上,公用一个。
@DefaultProperties(defaultFallback = "defalutQueryFallback")//一旦降级,就会找到queryFallback方法。
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping(value="/{id}")
    //请求成功的信息
    //开启失败处理的标志
/*    @HystrixCommand(commandProperties ={@HystrixProperty(
            name="execution.isolation.thread.timeoutInMilliseconds",value="5000" //局部设置超时
    )} )*/
    @HystrixCommand //声明熔断的方法
    public String queryByid(@PathVariable("id")String id){
        //负载均衡
        String url="http://products-service/products/"+id;
        String p = restTemplate.getForObject(url, String.class);
        return p;
    }
    //三,编写降级逻辑
    //熔断降级的逻辑的返回值要和原来的方法逻辑保持一致。如果在方法上,那参数也要一致。
    //请求失败的执行方法

    public String defalutQueryFallback(){//不能写参数了,因为写在类上公用的方法,参数都是不一样的。
        return "对不起,访问服务超时,请稍后再试";
    }

}

4,测试  , 模拟访问超时,在提供服务方设置Thread.sleep(),超时后走失败执行的方法queryFallback。(也可把服务提供者的程序停止测试)

@Service
public class ProductsService {
    @Autowired
    private ProductsMapper productsMapper;
    public Products queryById(String pid){
        //Thread.sleep(),Hystrix测试模拟超时
        try {
            Thread.sleep(2000L);//Hystrix默认大于等于1s超时。可配置
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return productsMapper.selectByPrimaryKey(pid);
    }
}

测试结果截图:

5,配置超时时长。可在配置文件中配置,也可在类方法上配置。

找到

类方法上配置超时时间:

    //开启失败处理的标志
   @HystrixCommand(commandProperties ={@HystrixProperty(
            name="execution.isolation.thread.timeoutInMilliseconds",value="5000" //局部设置超时
    )} )
    public String queryByid(@PathVariable("id")String id){
        //负载均衡
        String url="http://products-service/products/"+id;
        String p = restTemplate.getForObject(url, String.class);
        return p;
    }

.yml配置文件配置:

#配置全局熔断超时时间。
hystrix:
  command:
    default: #配置默认全局属性
       execution:
          isolation:
             thread:
                timeoutInMilliseconds:  5000
#配置局部熔断超时时间。也可在方法上写
#    products-service: #配置默认局部属性
#      execution:
#        isolation:
#          thread:
#            timeoutInMilliseconds:  5000

 

hystrix小总结:

降级
1,引入hystrix启动器
2,熔断时间,默认1s,6s
3,在引导类上添加一个注解:
4,定义熔断方法:局部(要和被熔断的方法返回值和参数列表一致) 全局(返回值要和被熔断的方法返回值一致,参数列表必须为空)
5,@HystrixCommand(fallbackMethod="局部熔断方法名"):声明被熔断的方法
6, @DefaultProperties(defaultFallback = "全局熔断方法名")

熔断
1,close:集合状态,所有请求正常方法
2,open:打开状态,所有请求都无法访问。如果在一定时间,失败的比例不小于50%或者次数不小于20此
3,half open:半开状态,打开状态默认5s休眠期,在休眠期所有请求无法正常访问。过了休眠期会进入半开状态,放部分请求通过
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值