乐趣区

关于springcloud:SpringCloud入门4Hystrix

通过前 3 节的 SpringCloud 学习,理解了服务的提供者可能不止有一个端口,在当前的真正的工作中可能还不止有一个微服务来提供服务。如果服务崩掉,如果没有措施,会导致很重大的损失。

就比方如果提供的是购物服务,总不可能让顾客买货色。还有生存中最常见的例子是当家庭某个电器短路的时候,为了保障整体电器,保险丝就会进行熔断。

Hystrix 的诞生就是为了解决这个问题。

1 引入 Hystrix

建设 hystrix 父模块,批改父模块 pom 文件使其子模块都导入了依赖,不便当前操作。

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

随后在父模块下新建一个hystrix-consume9301 子模块,最初的我的项目构造目录如下:

2 主启动类和配置文件

配置文件:

spring:
  application:
    name: hystrix-consume9301
server:
  port: 9301

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://localhost:8001/eureka/
  instance:
    instance-id: hystrix-consume9301

其实配置文件简略来说都是一样的,始终反复写进去就是为了大家不便 cv 复现

主启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix        // 开启 Hystrix
@RestController        // 开启业务类
public class HystrixConsume9301 {public static void main(String[] args) {SpringApplication.run(HystrixConsume9301.class, args);
    }

}

3 业务类

再次强调是为了不便入门,间接在主启动类中编写业务类,这是 不标准 的。

为了可能进行服务间的调用,在入门 Eureka 的时候也说到了利用RestTemplate 即可,所以须要增加一个 config 类把RestTemplate 注入到 Spring 容器中。

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced        // 开启负载平衡性能,加了此注解能力通过服务名来拜访服务
    public RestTemplate getRestTemplate() {return new RestTemplate();
    }

}

回过来看主启动类

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix        // 开启 Hystrix
@RestController        // 开启业务类
public class HystrixConsume9301 {public static void main(String[] args) {SpringApplication.run(HystrixConsume9301.class, args);
    }
    
    // 服务名字
    final String PROVIDE_URL = "http://eureka-provide";

    RestTemplate restTemplate;

    public HystrixConsume9301(RestTemplate restTemplate) {this.restTemplate = restTemplate;}

    @GetMapping("/hystrix/consume")
    @HystrixCommand(fallbackMethod = "getInfoFallback")    // 开启降级服务
    public String getInfo() {return "i am hystrix consumer, but actually invoke provide service: [" + restTemplate.getForObject(PROVIDE_URL + "/eureka/provide", String.class) + "]";
    }

    public String getInfoFallback() {return "hello, something wrong, i am getInfo fallback method";}


}

其它所有都一样,只不过是在相应的业务办法中增加了@HystrixCommand 注解,该注解中的fallbackMethod 申明的是服务降级后回调的是哪个办法。

4 测试

开启 Eureka 服务注册核心EurekaServer8001,服务提供者EurekaProvide7001,[7002, 7003],开启HystrixConsume9301

拜访 http://localhost:9301/hystrix…

然而当咱们 把所有的服务提供者 EurekaProvide7001 停掉以模仿服务挂掉的状况,测试后果如图所示。能够看到服务并没有报错,的确降级调用咱们想要调用的办法。

5 扩大

对于扩大方面,这里就略微提下@HystrixProperty 注解,间接看例子。

通过sleep() 函数来模仿服务提供端提早提供服务

首先须要批改的是 服务提供端的代码,服务提供端的代码,服务提供端的代码 也就是本系列第一篇文章中的 eureka-client-provide7001 子模块我的项目

@SpringBootApplication
@RestController
@EnableEurekaClient
public class EurekaProvide7001 {@Value("${server.port}")
    int port;

    @GetMapping("/eureka/provide")
    public String getInfo() {return "hello, i am eureka provide, the provide service. My port:" + port;}
    
    // 上面是增加的内容
    @GetMapping("/eureka/delayProvide")
    public String delayGetInfo() throws InterruptedException {Thread.sleep(3000);
        // 提早 3 秒才执行真正的业务逻辑
        return "hello, delay to do something";
    }
    public static void main(String[] args) {SpringApplication.run(EurekaProvide7001.class, args);
    }
}

而后批改Hystrix 生产端的代码

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

    final String PROVIDE_URL = "http://eureka-provide";

    RestTemplate restTemplate;

    public HystrixConsume9301(RestTemplate restTemplate) {this.restTemplate = restTemplate;}

    // 省略一部分

    @HystrixCommand(commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
    }, fallbackMethod = "getPropFallback")
    @GetMapping("hystrix/normalConsume")
    public String getNormalConsumeInfo() {long start = System.currentTimeMillis();
        String res = restTemplate.getForObject(PROVIDE_URL + "/eureka/delayProvide", String.class);
        long end = System.currentTimeMillis();
        res += "[cost time:" + (end - start) + "]";
        return res;
    }

    @HystrixCommand(commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
    }, fallbackMethod = "getPropFallback")
    @GetMapping("hystrix/timeoutConsume")
    public String getTimeoutConsumeInfo() {long start = System.currentTimeMillis();
        String res = restTemplate.getForObject(PROVIDE_URL + "/eureka/delayProvide", String.class);
        long end = System.currentTimeMillis();
        res += "[cost time:" + (end - start) + "]";
        return res;
    }

    public String  getPropFallback() {return "timeout, fallback method, do something.";}

}

@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000" 次要示意的是在规定的工夫(5000)如果能调用服务,那么就不 fallback。

下面的服务是提早了 3000ms 执行业务,而后我设置了一个回调阈值是 5000ms,一个是 2000ms。

开始测试前留神 把方才停掉的服务提供者 EurekaProvide7001 开启,模仿的是提早调用服务,并不是服务挂掉了。首先拜访 http://localhost:9301/hystrix…

能够看到转圈圈是大略 3s 后有响应,同时通过耗费的工夫也能够看出。

那么当拜访 超时接口 后 http://localhost:9301/hystrix…

能够看到转圈圈是大略 2s 后有响应,并且调用的是 fallback 办法,并不是服务提供办法。上种状况转 3s 是因为服务调用是 3s,这种状况转 2s 是因为咱们设置了回调阈值是 2s,到 2s 后还没调用服务就调用 fallback。

6 Hystrix Dashboard

这是一款可视化的监控,次要是帮忙咱们直观地看到了 Hystrix Command 无关响应的一些指标

引入依赖

批改hystrix-consume9301 子模块下的 pom 文件,往其中增加依赖

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

批改主启动类,减少 Bean

@SpringBootApplication
@EnableEurekaClient
@EnableHystrixDashboard        // 开启可视化界面,其实就是多加了这个注解
@EnableHystrix
@RestController
public class HystrixConsume9301 {}

此时能够启动主启动类来拜访 http://localhost:9301/hystrix

看到这个界面阐明配置胜利,值得注意的是咱们还须要减少一个 Bean 的配置类才可能正确运行,在 config 包下新建一个类ServletRegisterBeanConfig

@Configuration
public class ServletRegisterBeanConfig {@Bean(name = "registerBean")
    public ServletRegistrationBean getServlet(){HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();

        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);

        registrationBean.setLoadOnStartup(1);

        registrationBean.addUrlMappings("/actuator/hystrix.stream");

        registrationBean.setName("HystrixMetricsStreamServlet");


        return registrationBean;
    }
}

最初重新启动 HystrixConsume9301 主启动类,再次拜访 http://localhost:9301/hystrix…

当点击监控流后,会发现 dashboard 界面和控制台同时报错

批改配置文件

依照控制台报错批改管制文件,退出

hystrix:
  dashboard:
    proxy-stream-allow-list: localhost

重启我的项目,此时反复上述操作能够看到正确运行,期待连贯

测试

开启 Eureka 服务注册核心EurekaServer8001,服务提供者EurekaProvide7001,[7002, 7003],开启HystrixConsume9301。拜访生产接口 http://localhost:9301/hystrix…,http://localhost:9301/hystrix…,http://localhost:9301/hystrix…

能够看到的确可能实时监控到申请,并且有对应的指标。

创作不易,如果对你有帮忙,欢送点赞,珍藏和分享啦!

上面是集体公众号,有趣味的能够关注一下,说不定就是你的宝藏公众号哦,根本 2,3 天 1 更技术文章!!!

退出移动版