05.Spring Cloud学习笔记之服务容错保护组件Hystrix
2017-09-03 19:55
836 查看
前言
在微服务架构中存在着很多的服务单元,若一个单元出现故障会导致调用方的对外服务出现延迟,若此时调用方的请求不断的增加,最后就会因为等待出现故障的依赖方响应形成任务积压,最终导致自身服务瘫痪,最终导致整个系统瘫痪(雪崩效应),这样的系统架构很不稳定,为了解决这一类问题产生了断路器等一系列的服务保护机制Ribbon使用Hystrix
在服务消费的pom.xml文件中添加hystrix依赖<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
使用@HystrixCommand注解为请求指定fallback方法
@HystrixCommand(fallbackMethod = "indexFallback") @RequestMapping(value = "/index", method = RequestMethod.GET) public String index() { return restTemplate.getForEntity("http://user-service/hello", String.class).getBody(); } public String indexFallback(){ return "Index Fallback"; }
以上配置 当/index请求失败后会调用indexFallback方法。注:indexFallback方法的声明必须与index方法一致
在启动类添加@EnableCircuitBreaker注解
package com.roberto.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableEurekaClient @EnableCircuitBreaker @SpringBootApplication public class SpringCloudMovieService { @Bean @LoadBalanced RestTemplate restTemplate(){ return new RestTemplate(); } public static void main(String args[]) { SpringApplication.run(SpringCloudMovieService.class, args); } }
停止user-service服务后 调用/index接口进行测试
发现在前面几次调用浏览器刷新后返回Index Fallback,随着错误请求次数的增加,Hystrix的断路器状态会自动打开,后来的请求直接返回Index Fallback,而不会再去请求user-service服务
Feign使用Hystrix
在服务消费的pom.xml文件中添加hystrix依赖和Feign依赖<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
Feign失败回调类
package com.roberto.springcloud.feign; import org.springframework.stereotype.Component; @Component public class HystrixClientFallback implements UserFeignClient { @Override public String index() { return "Hello Fallback By Hystrix With Feign"; } }
UserFeignClient接口
package com.roberto.springcloud.feign; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @FeignClient(name = "user-service", fallback = HystrixClientFallback.class) public interface UserFeignClient { @RequestMapping(value = "/hello", method = RequestMethod.GET) String index(); }
Controller调用UserFeignClient
package com.roberto.springcloud.controller; import com.roberto.springcloud.feign.UserFeignClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class MovieController { @Autowired private UserFeignClient userFeignClient; @RequestMapping(value = "/index", method = RequestMethod.GET) public String index() { return userFeignClient.index(); } }
在启动类添加@EnableFeignClients,@EnableCircuitBreaker注解
package com.roberto.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; import org.springframework.cloud.netflix.feign.EnableFeignClients; @EnableEurekaClient @EnableFeignClients @EnableCircuitBreaker @SpringBootApplication public class SpringCloudMovieService { public static void main(String args[]) { SpringApplication.run(SpringCloudMovieService.class, args); } }
在配置文件application.yml中添加配置,启用feign的hystrix机制
feign: hystrix: enabled: true
停止user-service服务后 调用/index接口进行测试
禁用单个FegionClient的Hystrix的支持
新建Feign配置类,该类需不能被@SpringBootApplication注解扫描到,否则会覆盖全局Feign配置package com.roberto.springcloud.feign; import feign.Feign; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration public class FeignConfiguration { @Bean @Scope("prototype") public Feign.Builder feignBuilder() { return Feign.builder(); } }
为指定@FeignClient注解添加configuration属性指向上述Feign配置类
@FeignClient(name = "USER-SERVICE", configuration = FeignConfiguration.class)
Feign使用fallbackFactory属性打印fallback异常
新建HystrixClientFactory类package com.roberto.springcloud.feign; import feign.hystrix.FallbackFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class HystrixClientFactory implements FallbackFactory<UserFeignClient> { private static final Logger LOGGER = LoggerFactory.getLogger(HystrixClientFactory.class); @Override public UserFeignClient create(Throwable cause) { HystrixClientFactory.LOGGER.info("fallback; reason was: {}", cause.getMessage()); return new UserFeignClient() { @Override public String index() { return "Hello HystrixClientFactory fallback"; } }; } }
在@FeignClient注解中添加fallbackFactory属性指向HystrixClientFactory类
package com.roberto.springcloud.feign; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @FeignClient(name = "USER-SERVICE", fallbackFactory = HystrixClientFactory.class) public interface UserFeignClient { @RequestMapping(value = "/hello", method = RequestMethod.GET) String index(); }
配置Hystrix隔离策略
@HystrixCommand(fallbackMethod = "indexFallback", commandProperties = @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")) @RequestMapping(value = "/index", method = RequestMethod.GET) public String index() { return restTemplate.getForEntity("http://user-service/hello", String.class).getBody(); } public String indexFallback(){ return "Index Fallback"; } 在@HystrixCommand添加commandProperties = @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")配置说明/index请求和indexFallback方法是在同一个线程中,execution.isolation.strategy的默认值为THREAD,表示当/index请求失败时会新开一个线程调用indexFallback方法即处于不同线程下 全局配置,在application.yml配置文件中添加如下内容 hystrix.command.default.execution.isolation.strategy:SEMAPHORE
配置Hystrix超时时间
@HystrixCommand(fallbackMethod = "indexFallback", commandProperties = @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")) @RequestMapping(value = "/index", method = RequestMethod.GET) public String index() { return restTemplate.getForEntity("http://user-service/hello", String.class).getBody(); } public String indexFallback(){ return "Index Fallback"; } 在@HystrixCommand添加commandProperties = @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")配置说明当请求服务如果超过了Hystrix配置的超时时间(5秒),会直接进入fallbackMethod方法 全局配置,在application.yml配置文件中添加如下内容 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
health端点查看系统状态
在pom.xml添加以下依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
访问http://hostname:port/health查看系统状态
常见问题:
有时候访问/health端点只出现如下内容
出现该问题的原因是由于没有权限查看,解决该问题的方式有两种。
第一种是在application.yml配置文件下添加如下内容,表示取消认证(不推荐因为不安全)
management: security: enabled: false
第二是配置导入spring-boot-starter-security依赖后,配置认证登录后即可查看详细信息,这个在之前的博客中有提及
注:/health端点并不是为hystrix专门设计的,只是因为这里用到了所以在此博客中讲述
Hystrix Dashboard监控
单体应用监控
新建Dashboard实例工程在pom.xml文件中添加如下依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>spring-cloud-parent</artifactId> <groupId>com.roberto.springcloud</groupId> <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>spring-cloud-dashboard</artifactId> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency> </dependencies> </project>
在启动类添加@EnableHystrixDashboard注解
package com.roberto.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; @EnableHystrixDashboard @SpringBootApplication public class SpringCloudDashboardApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudDashboardApplication.class, args); } }
修改application.yml文件如下
server: port: 9091 spring: application: name: hystrix-dashboard
访问Hystrix Dashboard监控界面,http://localhost:9091/hystrix
Hystrix Dashboard监控单点实例节点需要通过访问实例/hystrix.stream接口来实现,我们需要为服务实例添加这个断点(注:服务实例是指要监控的实例并非dashboard),要开放/hystrix.stream接口只需如下两步
1.在pom.xml文件中添加以下依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
2.确保在服务启动类上添加了@EnableCircuitBreaker注解,开启断路器功能
在Hystrix Dashboard控制面板输入监控实例信息 开始监控
监控单体应用最终效果图如下所示
使用Turbine进行集群应用监控
新建turbine实例,pom.xml文件如下<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>spring-cloud-parent</artifactId> <groupId>com.roberto.springcloud</groupId> <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>spring-cloud-turbine</artifactId> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine</artifactId> </dependency> </dependencies> </project>
启动类添加@EnableTurbine注解
package com.roberto.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.turbine.EnableTurbine; @EnableTurbine @SpringBootApplication public class SpringCloudTurbineApplication { public static void main(String args[]) { SpringApplication.run(SpringCloudTurbineApplication.class, args); } }
application.yml文件配置如下
server: port: 9091 spring: application: name: turbine-service eureka: client: serviceUrl: defaultZone: http://roberto:roberto123@localhost:8761/eureka instance: prefer-ip-address: true turbine: aggregator: clusterConfig: default # 指定聚合哪些集群,多个使用","分割,默认为default。可使用http://.../turbine.stream?cluster={clusterConfig之一}访问 appConfig: MOVIE-SERVICE # 配置Eureka中的serviceId列表,表明监控哪些服务 clusterNameExpression: "'default'" # 1. clusterNameExpression指定集群名称,默认表达式appName;此时:turbine.aggregator.clusterConfig需要配置想要监控的应用名称 # 2. 当clusterNameExpression: default时,turbine.aggregator.clusterConfig可以不写,因为默认就是default # 3. 当clusterNameExpression: metadata['cluster']时,假设想要监控的应用配置了eureka.instance.metadata-map.cluster:ABC,则需要配置,同时turbine.aggregator.clusterConfig: ABC
其中MOVIE-SERVICE为服务名称,Turbine只能用来监控实现了Hystrix的工程项目,所以此处的MOVIE-SERVICE必须实现Hystrix
访问/turbine.stream接口进行数据的监测,将接口地址复制到Dashboard中即可监控集群
监控效果图
常见问题:假设在要监控的某个实例中配置了management.context-path=xxx或server.context-path=xxx那么需要在turbine配置文件中添加如下内容
turbine.instanceUrlSuffix.<cluster-name> = xxx # 如果是全局配置则改为 # turbine.instanceUrlSuffix = xxx
假设在要监控的某个实例中配置了management.port=xxx那么需要在该实例下添加如下配置
eureka.instance.metadata-map.management.port=xxx
相关文章推荐
- spring cloud学习笔记2(负载均衡ribbon,服务容错保护Hystrix)
- 笔记:Spring Cloud Hystrix 服务容错保护
- Spring Cloud学习(4)——服务容错保护Hystrix初研
- 【Spring Cloud】--服务容错保护Hystrix
- Spring Cloud Spring Boot mybatis 企业分布式微服务云(七)服务容错保护(Hystrix服务降级)【Dalston版】
- spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法
- 06.Spring Cloud学习笔记之声明式服务调用组件Feign
- Spring Cloud构建微服务架构:服务容错保护(Hystrix断路器)【Dalston版】
- Spring Cloud Hystrix(服务容错保护)
- Spring Cloud Spring Boot mybatis 企业分布式微服务云(八)服务容错保护(Hystrix依赖隔离)【Dalston版】
- 07.Spring Cloud学习笔记之API服务网关组件Zuul
- 服务容错保护断路器Hystrix之一:入门介绍
- Spring Cloud Spring Boot mybatis 企业分布式微服务云(九)服务容错保护(Hystrix断路器)【Dalston版】
- 服务容错保护断路器Hystrix之七:做到自动降级
- Spring Cloud构建微服务架构:服务容错保护(Hystrix断路器)【Dalston版】
- Spring Cloud架构教程 (十四)服务容错保护(Hystrix服务降级)【Dalston版】
- 7.Spring Cloud:服务容错保护(Hystrix依赖隔离)【Dalston版】
- 服务容错保护断路器Hystrix之三:断路器监控(Hystrix Dashboard)
- Spring Cloud构建微服务架构:服务容错保护(Hystrix依赖隔离)
- sbc(五)Hystrix-服务容错与保护