如何使用 Hystrix 服务降级

设置自身调用超时时间的峰值,峰值内可以正常运行,超过了需要有兜底的方法处理,作服务降级fallback

服务降级 fallback 既可以放在服务端,也可以放在客户端,但是我们一般放在客户端,这里两种都演示一下。

(1) 服务提供者服务降级

//业务类启用 @HystrixCommand
package com.atguigu.springcloud.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {
    /**
     * 正常访问
     * @param id
     * @return
     */
    public String paymentInfo_OK(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_OK,id:"+id+"\t"+"O(∩_∩)O哈哈~";
    }

    /**
     * http://localhost:8001/payment/hystrix/timeout/31
     * @HystrixCommand报异常后如何处理:
     * 一旦调用服务方法失败并抛出了错误信息后,
     * 会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
     *
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
            //设置这个线程的超时时间是3s,3s内是正常的业务逻辑,超过3s调用fallbackMethod指定的方法进行处理
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public String paymentInfo_Timeout(Integer id){
        int timeNumber = 5;
        //int age = 10/0;
        try{
            TimeUnit.SECONDS.sleep(timeNumber);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_Timeout,id:"+id+"\t"+"O(∩_∩)O哈哈~"+"   耗时(秒):"+timeNumber;
    }

    public String paymentInfo_TimeOutHandler(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"   系统繁忙,请稍后再试,id:"+id+"\t"+"o(╥﹏╥)o";
    }
}
//主启动类激活 @EnableCircuitBreaker
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    }
}

启动测试,没有报错,而是执行了fallbackMethod指定的方法

在这里插入图片描述
再来测试一下计算错误,也是会调用 fallbackMethod 指定的方法
在这里插入图片描述
总结
在这里插入图片描述
如果我们故意制造两个异常:

  1. int age = 10/0; 运行时异常
  2. 我们能接受3秒钟,它运行5秒钟,超时异常。

当前服务不可用了,做服务降级,兜底的方案都是paymentInfo_TimeOutHandler

(1) 消费者服务降级

#yml添加配置,开启 hystrix
feign:
 hystrix:
   enabled: true
//主启动
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderHystrixMain80.class,args);
    }
}
//业务类
package com.atguigu.springcloud.controller;
import com.atguigu.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderHystrixController {
    @Resource
    private PaymentHystrixService paymentHystrixService;

    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
        return paymentHystrixService.paymentInfo_OK(id);
    }

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    @HystrixCommand(fallbackMethod = "paymentTimeOutFallBackMethod",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")
    })
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
        return paymentHystrixService.paymentInfo_TimeOut(id);
    }

    public String paymentTimeOutFallBackMethod(@PathVariable("id") Integer id){
        return "我是消费者80,对方支付系统繁忙,请稍后再试,o(╥﹏╥)o";
    }
}

测试,超时异常:
在这里插入图片描述
运行时异常:
在这里插入图片描述
在这里插入图片描述
PS: 我们自己配置过的热部署方式对Java代码的改动明显,但对@HystrixCommand内属性的修改建议重启微服务。

问题1:

这样如果每个业务方法都对应一个兜底的方法,100个方法就有100个服务降级,会出现代码膨胀问题,我们需要一个统一的 fallbackMethod,统一的和自定义的分开。

解决问题:

@DefaultProperties(defaultFallback = "")

1 : 1 每个方法配置一个服务降级方法,造成代码膨胀

1 : N 除了个别重要核心业务有专属,其他普通的可以通过@DefaultProperties(defaultFallback = “”) 统一跳转到统一处理结果页面

这样通用的和独享的各自分开,避免了代码膨胀,合理减少了代码量。
在这里插入图片描述
测试
在这里插入图片描述
问题2:

现在客户端与服务端关系紧紧耦合,客户端能跑是因为接口调用了微服务的业务逻辑方法,我们如果针对客户端接口做一些处理,把它调用的所有微服务方法进行降级,就可以解决耦合问题。

解决问题:

这个案例服务降级处理是在客户端80完成的,与服务端8001没有关系,只需要为 Feign 客户端定义的接口添加一个服务降级处理的实现类即可实现解耦。

package com.atguigu.springcloud.service;
@Component
public class PaymentFallbackService implements PaymentHystrixService {
    @Override
    public String paymentInfo_OK(Integer id) {
        return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";
    }
}

接口使用@FeignClient(fallback = xxx.class)指定哪个类来处理异常
在这里插入图片描述
测试

先启动服务端8001,在启动客户端80,客户端正常调用微服务
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值