文章目录
一、雪崩效应
在微服务架构中,各个服务通过注册与发现相互依赖。系统运行时可能会因为某个环节的服务出现故障导致服务间的调用超时或者失败,进而导致整个系统的崩溃,这就是“雪崩效应”。
二、Hystrix介绍
2.1 原理
Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离、信号量隔离、降级策略、熔断技术。 Hystrix就像电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
2.2 服务熔断
断路器最初是关闭状态(Closed),当调用服务连续出错或者超时时,保护器切换为熔断状态(Open),在后面的一段时间内所有的请求将被拒绝(Fail Fast),一段时间后,保护器将尝试进入半熔断状态(Half Open),此时允许一定的请求进行尝试。如果请求成功,则回到关闭状态,吐过请求失败则回到熔断状态。
- 熔断机制的注解是@HystrixCommand。
- 熔断机制是应对雪崩效应的一种链路保护机制,一般存在于服务端。
- 当扇出链路的某个服务出现故障或响应超时,会进行服务降级,进而熔断该节点的服务调用,快速返回“错误”的相应信息。
- Hystrix的熔断存在阈值,缺省是5秒内20次调用失败就会触发
2.2.1 熔断案例
- 创建一个新的provider hystrix(可复制 provider 8001服务)。
- pom.xml加入hystrix依赖(一定要配合Eureka)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
- application.yml中配置端口等信息。
server:
port: 8004
spring:
application:
name: spring-cloud-provider
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
instance:
instance-id: spring-cloud-provider-hystrix-8004 #更改服务客户端显示名
prefer-ip-address: true
info:
author: 陈玉林
app.name: spring-cloud-study
company.name: www.xxxx.com
- Controller类中,在需要配置Fallback的方法上加入@HystrixCommand(fallbackMethod = “XXX”)注解,XXX为FallBack方法名。该方法的参数列表和返回值类型必须与被调用的方法一样
@HystrixCommand(fallbackMethod = "notService")
@RequestMapping("/hello/{name}")
public String index(@PathVariable String name) {
if (name.length()>6) {
throw new RuntimeException("服务出故障了!!");
}
return "Hello "+name+",welcome to study spring-cloud hystrix!!";
}
- 编写对应的FallBack的方法。
public String notService(@PathVariable String name) {
return "Sorry, the waiter are unable to provide services to "+name+" at this time";
}
- 主启动类中加入@EnableCircuitBreaker注解。
- 开启服务,测试。
2.3 FallBack方法解耦与服务降级处理
2.3.1 降级
- 当系统整体资源快不够的时候,忍痛将部分服务暂时关闭,待渡过难关后,再重新开启关闭的服务。
- 降级处理是在客户端完成的,与服务端没有任何关系。
- 理解:所谓降级,一般是从整体负荷考虑,当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的FallBack回调,返回一个缺省值。这样做虽然服务水平下降,但是系统还可以正常运行,实现了高可用。
2.3.2 为什么要解耦
如果按照上面的熔断案例来做的话,Controller下的每个方法,都要给其编写一个FallBack方法,如果方法过多,就会造成Controller代码混乱膨胀,耦合度高,加大了系统维护的难度,代码的耦合度也会高,这是十分不合理的,所以要将其解耦。
2.3.3 解耦和降级案例
- 创建一个consumer hystrix服务。
- 添加pom依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<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>
- 编写配置文件。
server:
port: 80
spring:
application:
name: spring-cloud-consumer-hystrix
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
register-with-eureka: false #作为消费者不提供服务,不应该注册自己
#必须添加这一条
feign:
hystrix:
enabled: true
- 创建fallback类,记得添加扫描注解。
@Component
public class HelloRemoteFallback implements HelloRemote{
@Override
public String hello(@RequestParam(value = "name") String name) {
return "Sorry, the waiter are unable to provide services to "+name+" at this time";
}
}
- 创建调用接口,添加指定fallback类,在服务熔断的时候返回fallback类中的内容。
@FeignClient(name= "spring-cloud-provider", fallback = HelloRemoteFallback.class)
public interface HelloRemote {
@RequestMapping(value = "/hello/{name}")
String hello(@RequestParam(value = "name") String name);
}
- 创建controller类。
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private HelloRemote helloRemote;
@RequestMapping("/hello/{name}")
public String index(@PathVariable("name") String name) {
return helloRemote.hello(name);
}
}
- 创建主启动类。
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SpringCloudConsumerHystrixApplication80 {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumerHystrixApplication80.class, args);
}
}
- 启动,测试,返回正常服务结果。
- 停掉服务提供者再次测试,返回fallback方法处理结果。
看源码点这里