SpringCloud简介
Spring Cloud是Spring旗下的项目之一
Spring Cloud并不是一个组件 而是许多组件的集合
其将当下非常流行的一些技术整合到了一起 实现了多个分布式开发中的重要功能
协调了分布式环境中各个系统 并且为各类服务提供模板性的配置
其主要涉及的组件包括:
- Eureka:注册中心
- Zuul或Spring Cloud Gateway:服务网关
- Ribbon:负载均衡
- Feign:服务调用
- Hystrix或Resilience4j:熔断器
【在本篇中 将介绍Hystrix熔断器】
Hystrix熔断器
Hystrix熔断器在微服务系统中是一款提供保护机制的组件
是开源的一个延迟和容错库 用于隔离访问远程服务和第三方库 以防止出现级联失败
说到这里 就不得不提雪崩问题了
雪崩问题
在微服务中 服务间的调用关系错综复杂 一个请求可能需要调用多个微服务接口才能实现 这会形成非常复杂的调用链路
如下图:一次业务请求 需要调用A、P、H、I四个服务 而这四个服务又可能调用其它服务
那么问题来了
若此时 某个服务出现了异常
如下图:微服务I 发生异常 请求阻塞了 那么用户请求就不会得到响应 则tomcat的这个线程不会释放
于是 越来越多的用户请求到来 越来越多的线程会被阻塞:
服务器支持的线程和并发数有限 若请求一直阻塞 则会导致服务器资源耗尽 从而导致所有其它服务都不可用 形成 【雪崩效应】
此时 就需要用到Hystrix熔断器了
Hystrix解决雪崩问题的手段主要是服务降级 其包括:
- 线程隔离
- 服务熔断
一、线程隔离
Hystrix为每个依赖服务调用分配一个小的线程池 用户请求不直接访问服务 而是使用线程池中空闲的线程来访问服务
若线程池已满调用将被立即拒绝 默认不采用排队 加速失败判定时间
当判断到服务不可用(无论什么原因导致的) 即可告诉该线程该服务不可用 不再无限等待了 以提早返回结果
二、服务降级
服务降级:优先保证核心服务 而 非核心服务不可用或弱可用
用户的请求故障时不会被阻塞 更不会无休止的等待或者看到系统崩溃
至少可以看到一个执行结果(例如 返回友好的提示信息)
服务降级虽然会导致请求失败 但是不会导致阻塞 且最多会影响这个依赖服务对应的线程池中的资源 对其它服务没有影响
三、使用步骤
1、服务降级
①、添加依赖:
在消费端添加Hystrix的依赖:
<!-- Hystrix熔断器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netfilx-hystrix</artifactId>
</dependency>
<!-- hystrix-javanica是一个Hystrix contrib库
是Hystrix的子项目 用于简化Hystrix的使用 提供@HystrixCommand注解 -->
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>RELEASE</version>
</dependency>
②、添加注解
在启动类上添加@EnableCircuitBreaker注解以开启Hystrix的熔断功能:
@SpringBootApplication
// 开启Eureka客户端的发现功能
@EnableDiscoveryClient
// 开启Hystrix的熔断功能
@EnableCircuitBreaker
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);;
}
// 注册RestTemplate
@Bean
@LoadBalanced
public RestTemplate restTemplate()
{
return new RestTemplate();
}
}
@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker
这三个注解可以以一个注解来代替:@SpringCloudApplication
@SpringCloudApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);;
}
// 注册RestTemplate
@Bean
@LoadBalanced
public RestTemplate restTemplate()
{
return new RestTemplate();
}
}
③、编写降级逻辑
在要设置降级逻辑的接口方法上添加@HystrixCommand
注解:
fallbackMethod属性用于指定失败结果 填写的是方法名
@GetMapping("/{id}")
// @HystrixCommand注解用于编写Hystrix的降级逻辑
// fallbackMethod属性用于指定失败结果 填写的是方法名
@HystrixCommand(fallbackMethod = "queryByIdFallback")
public String queryById(@PathVariable Long id)
{
// Ribbon负载均衡
String url="http://user-service/user/"+id;
return restTemplate.getForObject(url,String.class);
}
然后再在同个类下编写一个名称对应的降级方法:
需要注意的是 返回的是字符串类型
且设置了Hystrix降级逻辑的方法的返回值必须与该方法的返回值一致 都需为String字符串 参数也可一致
// 降级失败方法 返回字符串类型
// 设置了Hystrix降级逻辑的方法的返回值必须与该方法的返回值一致 都需为String字符串
// 参数也可一致
public String queryByIdFallback(Long id)
{
System.out.println("查询用户信息失败,编号为:"+id);
return "网络拥挤,访问失败。";
}
④、测试:
还可以对一整个类里的所有方法编写降级方法:
避免了单个编写的麻烦
在该类上添加@DefaultProperties
注解 defaultFallback属性用于指定方法名
// 全类的降级方法
@DefaultProperties(defaultFallback = "defaultFallback")
然后 在该类中的要使用Hystrix熔断的方法上添加@HystrixCommand
注解
虽然是对所有方法熔断 但还是要添加该注解的 唯一区别就是注解里不再指定方法了
@GetMapping("/{id}")
// 虽然是全类的降级方法 但该注解还是要加的
@HystrixCommand
public String queryById(@PathVariable Long id)
{
// Ribbon负载均衡
String url="http://user-service/user/"+id;
return restTemplate.getForObject(url,String.class);
}
最后 再编写一个处理方法即可:
// 对全类的降级失败方法
public String defaultFallback()
{
return "访问人数过多,请稍候重试。";
}
测试:
超时时长的配置:
Hystrix默认的超时时间为1秒 即1秒后访问依旧失败 则进行熔断
可以配置超时时长
application.yml:
hystrix:
command:
default:
execution:
isolation:
thread:
# Hystrix超时时长 默认为1秒 单位为毫秒
timeoutInMilliseconds: 3000
2、服务熔断
在服务熔断中使用的熔断器也叫断路器 其英文单词为Circuit Breaker
熔断机制与电路熔断原理类似 若电路发生短路的时候能立刻熔断电路 避免发生灾难
在分布式系统中应用服务熔断后 服务调用方可以自己进行判断哪些服务反应慢或存在大量超时 可以针对这些服务进行主动熔断 以防止整个系统被拖垮
Hystrix的服务熔断机制可以实现弹性容错:当服务请求情况好转之后可以自动重连
通过断路的方式将后续请求直接拒绝 一段时间 (默认为5秒) 之后允许部分请求通过 若调用成功则回到断路器关闭状态 否则继续打开 拒绝请求的服务
下图为Hystrix的熔断机制模型:
Closed
:关闭状态(断路器关闭) 此时所有请求都可正常访问Open
:打开状态(断路器打开) 所有请求都会被降级
Hystrix会对请求情况计数 当一定时间内失败请求百分比达到阈值 则触发熔断 断路器会完全打开
默认失败比例的阈值是50% 请求次数最少不低于20次Half Open
:半开状态 该状态不是永久的 断路器打开后会进入休眠时间(默认为5S)
随后断路器会自动进入半开状态 此时会释放部分请求通过 若这些请求都是健康的 则会关闭断路器 否则继续保持打开 再次进行休眠计时
服务熔断的配置:
在服务消费端进行配置
application.yml:
hystrix:
command:
default:
circuitBreaker:
# 触发熔断错误的比例阈值 默认值为50%
errorThresholdPercentage: 50
# 熔断后的休眠时长 默认为5秒 单位为毫秒
sleepWindowInMilliseconds: 10000
# 熔断触发最小请求次数 默认为20
requestVolumeThreshold: 10