目录
一、概述
1、分布式系统面临的问题
复杂分布式体系结构中的应用程序程序有数十个依赖关系,每个依赖关系再某些时候将不可
避免的失败
2、服务雪崩
多个微服务之间调用的时候,假设A调用B和C,B和C有屌用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用时间过长或者不可用,对A的调用就会占用越来越多的资源,进而引起系统崩溃,所谓的雪崩效应。
对于高流量的应用来说,单一的后端依赖可能会导致所有的服务器上的所有资源都在几秒内饱和,比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
所以,通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接收浏览,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障或者叫雪崩。
3、Hystrix介绍
是一个用于处理分布式系统的延迟
和容错
的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证再一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出方法无法处理的异常
,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免了故障再分布式系统的蔓延,乃至雪崩
4、作用
- 服务降级
- 服务熔断
- 接近实时的监控
二、Hystrix重要概念
-
服务降级
服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示,fallback
哪些情况会触发降级
程序运行异常、超时、服务熔断触发、线程池打满也会导致服务降级
-
服务熔断
类似保险丝达到最大的访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回
友好提示,
就是保险丝:服务的降级->进行熔断->恢复调用链路
-
服务限流
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行
三、Hystrix案例
-
超时导致服务器变慢(转圈):超时不在等待
-
出错(宕机或程序运行出错):出错要有兜底
-
解决:
-
对方服务超时了,调用者不能一致卡死等待,必须有服务降级
-
对方服务down机了,调用者不能一致卡死等待,必须由服务降级
-
对方服务ok,调用者自己出故障或者有自我要求(自己等待时间小于服务提供者),自己处理降级
-
四、服务降级
服务降级:通过@HystrixCommand
1、服务端
1、添加pom配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、添加启动类注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClient
@EnableCircuitBreaker //添加断路器注解
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
3、业务类添加降级处理
设置自身调用超时时间的峰值,峰值内可以正常运行,超过了需要由兜底的方法处理,作服务降级fallback,一旦调用服务方法失败并抛出错误信息后,会自动调用@HystrixCommand标注号的fallbackMethod调用类中的指定方法
//execution.isolation.thread.timeoutInmilliseconds 设置超时时间
@HystrixCommand(fallbackMethod="paymentInfo_timeOutHandler",
commandProperties={@HystrixProperty("
name="execution.isolation.thread.timeoutInmilliseconds",valie="3000")})
public String paymentInfo_timeout(Integer id){
try{
//int i=10/0;
TimeUnit.SECONDS.sleep(3);
}catch(Exception e){}
return "模拟超时访问方法";
}
public String paymentInfo_timeOutHandler(Integer id){
return "失败降级方法";
}
2、客户端
如果要降级则同服务的意义配置使用
1、添加pom配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、添加yml配置
代表再Feign中开启hystrix熔断器
feign:
hystric:
enabled: true
3、添加启动类注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClient
@EnableHystrix //添加注解
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
3、做全局失败回调,不需要所有方法都返回自己的错误信息
没有配置过failback的就找全局默认的回调方法
需要在方法上加上@HystrixCommand开启服务降级处理
@DefaultProperties(defaultFallback="paymentFallBack")
public class xxx{
@HystrixCommand
public String paymentInfo_timeout(Integer id){
try{
//int i=10/0;
TimeUnit.SECONDS.sleep(3);
}catch(Exception e){}
return "模拟超时访问方法";
}
public String paymentFallBack(){
return "失败回调";
}
}
-
1对1:每个方法配置一个服务降级方法,技术上可以,但是代码里膨胀
-
1对N:除了个别核心业务有专属,其他普通的可以通过@DefaultProperties来统一处理结果页面
通用和独享的各自分开,避免了代码碰撞,合理减少代码量
4、直接对客户端服务接口做服务降级
@Component
@FeignClient(value="CLOUD-PAYMENT-SERVICE",fallback=PaymentFeignServiceFallBack.class)
public interface PaymentFeignService{
@GetMapping(value="/payment/get/{id}")
String getById(@Pathvariable Long id);
}
//创建一个实现类
@Component
public class PaymentFeignServiceFallBack implements PaymentFeignService{
@Overvide
public String getById(Long id){
return “失败回调方法”;
}
}
五、服务熔断
类似保险丝达到最大的访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示,就是保险丝:服务的降级->进行熔断->恢复调用链路
1、熔断是什么
熔断机制概述:熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务出错不可用或者响应时间太长史,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,恢复调用链路
在spring cloud框架里,熔断机制通过Hystrix实现,Hystrix会监控微服务的调用的状况,当失败的调用到一定阈值时,缺省时5秒内20次调用失败,就会启动熔断机制,熔断机制的注解时@HystrixCommand
2、案例
修改service的配置,在服务的方法的@HystrixCommand注解里添加参数
在10秒内的时间窗口期 10次访问中失败率达到60%则启动断路器,到一定程度成功率高了失败率降了慢慢的在合上熔断器恢复正常。
@HystrixCommand(fallbackMethod="paymentInfo_timeOutHandler",
commandProperties={
//超时时间
@HystrixProperty(
name="execution.isolation.thread.timeoutInmilliseconds",valie="3000").
//是否开启断路器
@HystrixProperty(name="circuitBreaker.enabled",value="true"),
//请求次数
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),
//时间窗口期(时间内,单位毫秒)
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),
//失败率达到多少后跳闸
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="60")
})
3、涉及到的重要参数
-
快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒
-
请求总数阈值:在快照时间窗内,必须满足请求总数阈值才有资格熔断,默认为20,意味着20秒内,如果该Hystrix命令的调用次数不足20次,即使所有的请求超时或者其他原因失败,断路器都不会打开
-
错误百分比阈值:当请求总数在快照时间窗内超过了阈值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过50%的错误百分比,在默认设置50%的情况下,这是会就会将断路器打开
4、结论
当熔断打开后,过一段时候会回到熔断半开状态,如果服务正常了则恢复服务,否则继续进入熔断状态
-
熔断打开:请求不再进行调用当前服务,内部设置时间一般为MTTR(平均故障处理时间),当打开市场达到所设始终则进入版熔断状态
-
熔断关闭:熔断关闭不会对服务进行熔断
-
熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断
六、服务限流
这里略过,去看alibaba的sentinel说明
七、服务监控HystrixDashboard
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续的记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等,netfilx通过hystrix-metrics-event-stream项目实现了对以上指标的监控,springcloud也提供了HystrixDashboard的整合,对监控内容转化为可视化界面
1、添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<!--还必须被监控服务提供方都需要监控依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、修改启动类
//添加注解
@EnableHystrixDashboard
访问测试:http://localhost:8080/hystrix
3、修改被监控的服务项目
注意:新版本Hystrix需要在主启动类中指定监控路径
在主启动类中添加一个Bean配置
@Bean
public ServletRegistionBean getServlet(){
MystrixMetricsStreamServlet streamServlet=new MystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean =new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStratup(1);
registrationBean.addUrlMaapings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
4、填写监控地址
在hystrixDashboard 填写http://localhsost:8001/hystrix.stream进行监控查看