服务降级及熔断 - Hystrix

1. 方法降级

provider

@RestController
@RequestMapping("/hystrix")
public class ProviderHystrixController {

    @GetMapping("/error")
    public String getInternalError() {
        Random random = new Random();
        boolean flag = random.nextBoolean();
        if (flag) {
            return "normal work";
        } else {
            throw new RuntimeException("wrong parameters");
        }
    }

    @GetMapping("/timeout")
    public String getTimeOut() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        return "after 5s, the result is returned";
    }
}

consumer

# 主启动类上加,开启hystrix服务降级及熔断的功能
#  @EnableHystrix继承了@EnableCricuitBreaker
@EnableCircuitBreaker   或者     @EnableHystrix
package com.nike.consumer.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/consumer")
public class ConsumerHystrixController {

    private RestTemplate template = new RestTemplate();

    private final String providerErrorUrl = "http://localhost:9001/hystrix/error";
    private final String providerTimeOutUrl = "http://localhost:9001/hystrix/timeout";

    /**
     * 出错的业务, 提供了服务降级的方案
     */
    @GetMapping("/error")
    @HystrixCommand(fallbackMethod = "internalErrorHystrix")
    public String getInternalError() {
        return template.getForObject(providerErrorUrl, String.class);
    }

    private String internalErrorHystrix() {
        return "server internal error, check your parameters";
    }


    /**
     * 网络异常业务: 3s 内走正常逻辑, 3s外就走降级逻辑
     */
    @GetMapping("/timeout")
    @HystrixCommand(fallbackMethod = "netWorkBusinessHystrix", commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public String getTimeOut() throws InterruptedException {
        return template.getForObject(providerTimeOutUrl, String.class);
    }

    private String netWorkBusinessHystrix() {
        return "Server Connection Error, Try Again";
    }
}

2. 全局配置

  • 不可能为每一个方法都提供一个服务降级处理的方法
  • 为类中所有方法配置全局服务降级的方法,某些方法可以单独自定义
@RestController
@RequestMapping("/consumer")
@DefaultProperties(defaultFallback = "globalHandler") // 全局变量处理
public class ConsumerHystrixController {
    

    private RestTemplate template = new RestTemplate();

    private final String providerErrorUrl = "http://localhost:9001/hystrix/error";
    private final String providerTimeOutUrl = "http://localhost:9001/hystrix/timeout";

    /**
     * 交给全局服务降级处理的方法,必须加@HystrixCommand,否则全局处理不会生效
     */
    @HystrixCommand
    @RequestMapping("/info")
    public String getInfo() {
        int i = 1 / 0;
        return "math error";
    }

    private String globalHandler() {
        return "global error processed";
    }
    
    @GetMapping("/error")
    @HystrixCommand(fallbackMethod = "internalErrorHystrix")
    public String getInternalError() {
        return template.getForObject(providerErrorUrl, String.class);
    }

    private String internalErrorHystrix() {
        return "server internal error, check your parameters";
    }

    /**
     * 个别方法需要单独特殊处理的,在该方法上再添加具体的配置
     */
    @GetMapping("/timeout")
    @HystrixCommand(fallbackMethod = "netWorkBusinessHystrix", commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public String getTimeOut() throws InterruptedException {
        return template.getForObject(providerTimeOutUrl, String.class);
    }

    /**服务降级的方法必须和处理的接口的参数一致*/
    private String netWorkBusinessHystrix() {
        return "Server Connection Error, Try Again";
    }
}

三、服务熔断

1. 在指定时间窗口期内及请求次数,如果失败率达到60%,则开启服务熔断;  Closed
2. 再次用正确的参数来进行,断路器依然为Closed,直接进行服务降级
3. 慢慢的将断路器更换为  Half Closed,并尝试来调用当前服务
4. 如果服务恢复了,则变为Open,如果依然是失败的,则继续恢复为Closed
@RequestMapping("/breaker")
@RestController
public class ConsumerCircuitController {
    
    @HystrixCommand(fallbackMethod = "backupPlan", 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"), // 失败率达到多少后开启
    })
    @GetMapping("/info")
    public String getInfo(Integer id) {
        if (id < 0) {
            throw new RuntimeException("id不能为负数");
        }
        return new Date() + " ===== " + id + " 正常访问";
    }

    public String backupPlan(Integer id) {
        return new Date() + " ===== " + id + " 服务降级";
    }
}

四、服务监控

4.1 DashBoard服务

  • 单独搭建一个微服务,用来观察指定服务的降级,熔断情况等
<!--1. web模块的starter和健康检查的starter-->
<!--hystrix的dashboard仪表盘-->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
   <version>2.2.9.RELEASE</version>
</dependency>
server:
  port: 9100
# 不配置如下可能出现如下错误:
# Origin parameter: http://localhost:8080/actuator/hystrix.stream is not in the allowed list of proxy host names.  
# If it should be allowed add it to hystrix.dashboard.proxyStreamAllowList.
hystrix:
  dashboard:
    proxy-stream-allow-list: localhost
    # 允许监控的ip,不同版本可能不同
# 主启动类
@EnableHystrixDashboard
# 访问地址
http://localhost:9100/hystrix

在这里插入图片描述

4.2 微服务上监控

# 监控: pom中必须带有下面的依赖
spring-boot-starter-actuator
@SpringBootApplication
@EnableCircuitBreaker // hystrix服务降级及熔断的功能开启
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
    /**
     *  如果不添加下面的bean,监控时候就会链接不到该微服务
     *   报错信息: Unable to connect to Command Metric Stream.
     * @return
     */
    @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;
    }
}

4.3. 数据分析

1. 启动DashBoard和业务微服务,页面输入 微服务 ip, 端口
  http://localhost:8001/hystrix.stream
2. 随机访问微服务业务断,不断发生服务降级及熔断等多种情况
3. 页面的信息是实时变化的,可以统计当前该服务的访问情况

在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值