服务降级——Hystrix

本文介绍了服务降级的概念,通过Hystrix在服务端和客户端的配置实现服务降级。详细阐述了服务端如何配置Hystrix,包括依赖和配置文件,以及在Service层的处理。客户端配置同样关键,设置了超时时间和熔断策略。此外,文章还讨论了服务熔断机制,当异常达到一定比例时,服务将进入熔断状态。最后,展示了通过Hystrix Dashboard进行监控服务状态的方法。
摘要由CSDN通过智能技术生成

服务降级

服务降级指的是在多链路调用的过程中(微服务A调用微服务B,微服务B又调用微服务C,……)某一个服务出现了异常,为了防止消费端报异常或是浪费资源持续等待而直接根据本服务的一些救治措施来返回给消费者内容,不再去请求其他服务的一种策略。

服务端配置Hystrix

需要的依赖:

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

配置文件(正常配置):

server.port=8001
spring.application.name=CLOUD-PROVIDER-HYSTRIX-PAYMENT
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka

主启动类

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

Service层:

@Service
public class PaymentService {
    public String paymentInfo_OK(Integer id) {
        return "线程池: " + Thread.currentThread().getName() + "paymentInfo_OK, id: " + id + " ^ ^";
    }

    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public String paymentInfo_TimeOut(Integer id) {
        try {
            TimeUnit.MILLISECONDS.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//        int age = 10 / 0;
        return "线程池: " + Thread.currentThread().getName() + "paymentInfo_TimeOut, id: " + id + " T T";
    }

    public String paymentInfo_TimeOutHandler(Integer id) {
        return "线程池: " + Thread.currentThread().getName() + "系统繁忙~";
    }
}

当paymentInfo_TimeOut运行超过3秒时,会调用paymentInfo_TimeOutHandler方法继续返回。

客户端配置Hystrix

依赖和服务端一样
配置文件

server.port=80
eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka/
ribbon.ReadTimeout=10000
ribbon.ConnectTimeout=10000

ribbon.ReadTimeout=10000ribbon.ConnectTimeout=10000分别表示客户端从服务端读取数据和进行连接所允许的最大时间,单位是毫秒,即这里都设置为10秒。

主启动类

@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderHystrixMain80.class, args);
    }
}

第一种定义fallback的方式是在Controller层:

@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_fallback",
        commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="2500")})
public class OrderController {
    @Resource
    private PaymentHystrixService paymentHystrixService;

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

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

    @GetMapping(value = "/consumer/payment/connect/test")
    public String connectTest(){
        return "OK";
    }

    private String paymentInfo_TimeOutHandler(Integer id){
        return "线程池: " + Thread.currentThread().getName() + "serverPort: " + "80" +  " 系统繁忙~";
    }

    //全局fallback
    public String payment_Global_fallback(){
        return "Global异常处理信息,请稍后再试~";
    }
}

@HystrixCommand注解中的fallbackMethod属性表示planB用哪个方法,commandProperties是一个类型为HystrixProperty的数组,@HystrixProperty里面可以设置各种初始化的属性值,这里设置的是线程的请求时间不能超过2秒。
@DefaultProperties注解在类上进行修饰,defaultFallback设置了这个类中的所有方法的后备方法,如果某些方法有特定的Fallback方法,只需要使用@HystrixCommand注解进行详细配置即可,如果没有的话,只需要在方法上使用@HystrixCommand注解,不需要进行属性的配置,例如此处的paymentInfo_TimeOut使用的就是默认fall back。

另外一种定义fallback的方式是在Service层:

//PaymentHystrixService
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentHystrixServiceImpl.class)
public interface PaymentHystrixService {
    @GetMapping(value = "/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping(value = "/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}
//PaymentHystrixServiceImpl
@Service
public class PaymentHystrixServiceImpl implements PaymentHystrixService {
    @Override
    public String paymentInfo_OK(Integer id) {
        return "-------------PaymentHystrixServiceImpl ok fall back";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "-------------PaymentHystrixServiceImpl timeout fall back";
    }
}

当调用服务端异常时,会直接调用PaymentHystrixServiceImpl中的fallback方法进行返回。

服务熔断

服务熔断指的是,某个时间段内(例如每10秒)的访问数量达到了阈值,并且出现异常的百分比达到了一定程度,服务就会进行熔断,禁止访问。等到下一个时间段会尝试转换成半开放状态,接收访问,如果还是出现异常则继续熔断。知道某个时间段能够正常访问了,则关闭服务熔断。
Controller层:

@RestController
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;
    
    @GetMapping("/payment/circuit/{id}")
    public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
        String result = paymentService.paymentCircuitBreaker(id);
        log.info("**********result: " + result);
        return result;
    }
}

Service层:

@Service
public class PaymentService {
    //服务熔断
    @HystrixCommand(
            fallbackMethod = "paymentCircuitBreaker_fallback",
            commandProperties = {
                    @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //是否开启服务熔断
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //请求次数
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //时间窗口期
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") //失败率达到多少后跳闸
            }
    )
    public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
        if (id < 0) {
            throw new RuntimeException("*******id不能为负数");
        }
        String serialNumber = IdUtil.simpleUUID();
        return Thread.currentThread().getName() + " 调用成功, 流水号:" + serialNumber;
    }

    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
        return "id 不能为负数,请稍后再试, id: " + id;
    }
}

Hystrix DashBoard图形化界面

依赖:

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

配置

server.port=9001
# 这行一定要加上,不然无法监控其他服务
hystrix.dashboard.proxy-stream-allow-list=localhost

主启动类

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

被监控类的主启动类

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

	//springboot2.0之后,以下代码需要加上
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

接着启动服务,就能够看到图形化界面,填写需要监控的服务:
图形化界面
开启熔断
可以看到此时的异常率达到了100%,也就是说一直在使用fallback,因此开启了熔断:Circuit Open,等10秒后,能够正常访问了,服务关闭熔断:
关闭熔断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值