Hystrix之服务降级代码演示

所有代码都在github上:https://github.com/demonruin/cloud2020/tree/master

 

服务降级就是指服务器忙,请稍候再试,不让客户端等待并立刻返回一个友好提示,fallback

哪些情况会触发降级:程序运行异常,超时,服务熔断触发服务降级,线程池/信号量打满也会导致服务降级;

服务降级分为 服务端降级 和 客户端降级,好比一双筷子,你可以夹肉,也可以夹菜,不过一般是用来在客户端降级使用,具体情况具体分析使用。下面分别举例在服务端降级和 客户端降级代码演示。有个前提啊,就是项目中已经加入了Hystrix的包依赖支持,酌情选择添加

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

服务端降级

1、需要使用@HystrixCommand,设置兜底即fallback降级方法,设置拦截异常信息。8001服务正常timeout时间为6s,但是服务降级做了5秒等待限制,超过了就不再等待,进行服务降级,调用fallback方法;

package com.king.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;

/**
 * created by king on 2020/4/16 3:22 下午
 */
@Service
public class PaymentHystrixService {

    /**
     * 成功访问
     *
     * @param id
     * @return
     */
    public String getOk(Integer id) {
        return "线程池:" + Thread.currentThread().getName() + " ID:" + id + "\t 访问成功";
    }

    /**
     * 访问超时
     *
     * @param id
     * @return
     * 5000是指5s
     */
    @HystrixCommand(fallbackMethod ="paymentFallback_handler",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "5000")
    })
    public String getTimeout(Integer id) {
        int timeout = 6;
        try {
            TimeUnit.SECONDS.sleep(timeout);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池:" + Thread.currentThread().getName() + " ID:" + id + "\t 访问超时,超时时间(秒):" + timeout;
    }

    public String paymentFallback_handler(Integer id){
        return "线程池:" + Thread.currentThread().getName() + " paymentFallback_handler---ID:" + id + "\t ";
    }
}

2、主启动类加注解@EnableCircuitBreaker

package com.king.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;

/**
 * created by king on 2020/4/16 3:21 下午
 */
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
            SpringApplication.run(PaymentHystrixMain8001.class,args);
        }
}

3、测试结果展示

此时服务端的服务降级就完成代码演示开发了,下面介绍客户端服务降级演示

客户端服务降级

80订单微服务,也可以更好的保护自己,自己也依样画葫芦进行客户端降级保护。

服务降级,客户端去调用服务端,碰上服务端宕机或关闭,本次案例服务降级处理是在客户端80实现完成的,与服务端8001没有关系,只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦;未来我们要面对的异常有:运行时异常比如1/0的异常,超时异常 比如sleep(5),宕机 即服务端服务器宕机等等

1、首先需要配置yml,启动feign的hystrix支持

feign:
  hystrix:
    #如果处理自身的容错就开启。开启方式与生产端不一样。
    enabled: true

2、主启动类加上启用注解@EnableHystrix

package com.king.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * created by king on 2020/4/16 5:39 下午
 */
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class OrderFeignHystrixMain80 {
    public static void main(String[] args) {

            SpringApplication.run(OrderFeignHystrixMain80.class,args);
        }
}

3、在controller接口上加注解,配置fallback降级兜底方法,进行请求超时等情况下的服务降级

package com.king.springcloud.controller;

import com.king.springcloud.service.OrderFeignHystrixService;
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;

/**
 * created by king on 2020/4/16 5:43 下午
 */
@RestController
@Slf4j
public class OrderFeignHystrixController {
    @Resource
    private OrderFeignHystrixService orderFeignHystrixService;

    @GetMapping(value = "/payment/ok/{id}")
    public String getOK(@PathVariable("id") Integer id) {
        return orderFeignHystrixService.getOk(id);
    }

    @GetMapping(value = "/payment/timeout/{id}")
    @HystrixCommand(fallbackMethod = "fallbackHystrix_handler_order",
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")})
    public String getTimeout(@PathVariable("id") Integer id) {
        return orderFeignHystrixService.getTimeout(id);
    }

    public String fallbackHystrix_handler_order(@PathVariable("id") Integer id){
        return "80请求服务失败";
    }
}

此处设置的请求超时时间为1500毫秒,而8001提供的服务超时时间是3000毫秒,所以客户端请求会直接请求超时,调用服务降级fallback方法,结果展示

上面是简单的服务降级举例,但是每个业务方法对应一个兜底的fallback方法,会造成代码膨胀。而降级fallback方法和业务代码混乱在一起,所以一般会进行处理,将统一和自定义的进行区分开,或者将fallback方法从业务代码中抽取出来;

统一和自定义分开:

一、在客户端服务降级,统一处理方式

  •   在controller上加统一@DefaultProperties(defaultFallback = "globle_fallbackHystrix_handler")注解
  •   在接口上统一加 @HystrixCommand注解
  •   自定义的降级处理方法,扔参照timeout的接口自定义服务降级处理方法
package com.king.springcloud.controller;

import com.king.springcloud.service.OrderFeignHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
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;

/**
 * created by king on 2020/4/16 5:43 下午
 */
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "globle_fallbackHystrix_handler")
public class OrderFeignHystrixController {
    @Resource
    private OrderFeignHystrixService orderFeignHystrixService;

    @GetMapping(value = "/payment/ok/{id}")
    @HystrixCommand
    public String getOK(@PathVariable("id") Integer id) {
        return orderFeignHystrixService.getOk(id);
    }

    @GetMapping(value = "/payment/timeout/{id}")
    @HystrixCommand(fallbackMethod = "fallbackHystrix_handler_order",
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")})
    public String getTimeout(@PathVariable("id") Integer id) {
        return orderFeignHystrixService.getTimeout(id);
    }

    public String fallbackHystrix_handler_order(@PathVariable("id") Integer id){
        return "80请求服务失败";
    }

    public String globle_fallbackHystrix_handler(){
        return "请求服务失败,返回全局服务降级处理方法";
    }
}

二、将降级方法从业务代码中抽取出来,不再糅合的处理方法

  •   去掉上述方法中 在controller上加统一@DefaultProperties(defaultFallback = "globle_fallbackHystrix_handler")注解
  •   去掉在接口上统一加 @HystrixCommand注解
  •   保留 yml中的feign启用hystrix的配置
  •   新建FallbackServiceHandler类,实现接口OrderFeignHystrixService,并重写每一个方法,作为兜底fallback服务降级
  •   在OrderFeignHystrixService的feign注解配置上,指定兜底fallback服务降级类
package com.king.springcloud.service;

import org.springframework.stereotype.Component;

/**
 * created by king on 2020/4/17 1:31 下午
 */
@Component
public class FallbackServiceHandler implements OrderFeignHystrixService {

    public String getOk(Integer id) {
        return null;
    }

    public String getTimeout(Integer id) {
        return null;
    }
}
package com.king.springcloud.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * created by king on 2020/4/16 5:40 下午
 */
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE-HYSTRIX",fallback = FallbackServiceHandler.class)
public interface OrderFeignHystrixService {


    @GetMapping(value = "/payment/ok/{id}")
    public String getOk(@PathVariable("id") Integer id);

    @GetMapping(value = "/payment/timeout/{id}")
    public String getTimeout(@PathVariable("id") Integer id);
}

测试结果如下

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值