服务熔断与服务降级
-
服务熔断
-
服务雪崩:是一种因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程。
-
雪崩效应:服务提供者因为不可用或者延迟高在成的服务调用者的请求线程,阻塞的请求会占用系统的固有线程数、IO等资源,当这样的被阻塞的线程越来越多的时候,系统瓶颈造成业务系统炎黄崩溃,这种现象成为雪崩效应
-
熔断机制:熔断机制是服务雪崩的一种有效解决方案,当服务消费者请求的服务提供者因为宕机或者网络延迟高等原因造车过暂时不能提供服务时,采用熔断机制,当我们的请求在设定的最常等待响应阀值最大时仍然没有得到服务提供者的响应的时候,系统将通过断路器直接将吃请求链路断开,这种解决方案称为熔断机制
-
-
服务降级
-
理解了上面所说的服务熔断相关的知识,想想在服务熔断发生时,该请求线程仍然占用着系统的资源,为了解决这个问题,在编写消费者[重点:消费者]端代码时就设置了预案,当服务熔断发生时,直接响应有服务消费者自己给出的一种默认的,临时的处理方案,再次注意"这是由服务的消费者提供的",服务的质量就相对降级了,这就是服务降级,当然服务降级可以发生在系统自动因为服务提供者断供造成的服务熔断,也可运用在为了保证核心业务正常运行,将一些不重要的服务暂时停用,不重要的服务的响应都由消费者给出,将更多的系统资源用作去支撑核心服务的正常运行,比如双11期间,收货地址服务全部采用默认,不能再修改,就是收货地址服务停了,把更多的系统资源用作去支撑购物车、下单、支付等服务去了。
-
我们再简单归纳一下:简单来说就是服务提供者断供了,其一为了保证系统可以正常运行,其二为了增加用户的体验,由服务的消费者调用自己的方法作为返回,暂时给用户响应结果的一种解决方案;
-
Hystrix的中文意思是:豪猪,在我们的应用中Hystrix的作用就是充当断路器
在我们SpringCloud中,Feign默认也有对Hystrix的集成,只不过默认情况下是关闭的,需要我们手动开启
feign:
okhttp:
enabled: false # 禁用OkHttp
httpclient:
enabled: true # 启用httpClient
connection-timeout: 10000
connection-timer-repeat: 6000
client:
config:
default: # 默认配置
connectTimeout: 10000 # 连接超时 单位毫秒
readTimeout: 30000 # 读取超时 单位毫秒
compression: # 开启压缩
response:
useGzipDecoder: true
enabled: true
request:
enabled: true
hystrix:
enabled: true
hystrix:
shareSecurityContext: true # 在Feign调用失败时执行fallback方法,在新的线程中共享安全上下文信息
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 160000
服务消费者编写回滚函数
package com.markyang.framework.client.system.fallback;
import com.markyang.framework.client.system.UserClient;
import com.markyang.framework.pojo.auth.AuthenticatedUser;
import com.markyang.framework.pojo.dto.system.OrgUserDto;
import com.markyang.framework.pojo.web.ResultVo;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Client熔断类
* @author yangchangliang
*/
@Component
public class UserClientFallback implements UserClient {
/**
* 根据用户名加载授权用户信息
*
* @param username 用户名
* @return 授权用户
*/
@Override
public ResultVo<AuthenticatedUser> getUserByUsername(String username) {
return ResultVo.error("用户服务连接异常");
}
/**
* 根据用户名加载授权用户信息
*
* @param phone 手机号
* @return 授权用户
*/
@Override
public ResultVo<AuthenticatedUser> getUserByMobilePhone(String phone) {
return ResultVo.error("用户服务连接异常");
}
/**
* 根据用户ID加载授权用户信息
*
* @param userId 用户ID
* @return 授权用户
*/
@Override
public ResultVo<AuthenticatedUser> getUserByUserId(String userId) {
return ResultVo.error("用户服务连接异常");
}
/**
* 获取所有的用户信息
*
* @param orgId 机构ID
* @return 结果对象
*/
@Override
public ResultVo<List<OrgUserDto>> getOrgUsers(String orgId) {
return ResultVo.error("用户服务连接异常");
}
}
Hystrix是什么
在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。
Hystrix为了什么
Hystrix被设计的目标是:
- 对通过第三方客户端库访问的依赖项(通常是通过网络)的延迟和故障进行保护和控制。
- 在复杂的分布式系统中阻止级联故障。
- 快速失败,快速恢复。
- 回退,尽可能优雅地降级。
- 启用近实时监控、警报和操作控制。
Hystrix解决了什么问题
复杂分布式体系结构中的应用程序有许多依赖项,每个依赖项在某些时候都不可避免地会失败。如果主机应用程序没有与这些外部故障隔离,那么它有可能被他们拖垮。
例如,对于一个依赖于30个服务的应用程序,每个服务都有99.99%的正常运行时间,你可以期望如下:
99.9930 = 99.7% 可用
也就是说一亿个请求的0.03% = 3000000 会失败
如果一切正常,那么每个月有2个小时服务是不可用的
现实通常是更糟糕
当一切正常时,请求看起来是这样的:
当其中有一个系统有延迟时,它可能阻塞整个用户请求:
在高流量的情况下,一个后端依赖项的延迟可能导致所有服务器上的所有资源在数秒内饱和(PS:意味着后续再有请求将无法立即提供服务)
Hystrix设计原则是什么
- 防止任何单个依赖项耗尽所有容器(如Tomcat)用户线程。
- 甩掉包袱,快速失败而不是排队。
- 在任何可行的地方提供回退,以保护用户不受失败的影响。
- 使用隔离技术(如隔离板、泳道和断路器模式)来限制任何一个依赖项的影响。
- 通过近实时的度量、监视和警报来优化发现时间。
- 通过配置的低延迟传播来优化恢复时间。
- 支持对Hystrix的大多数方面的动态属性更改,允许使用低延迟反馈循环进行实时操作修改。
- 避免在整个依赖客户端执行中出现故障,而不仅仅是在网络流量中。
Hystrix是如何实现它的目标的
- 用一个HystrixCommand 或者 HystrixObservableCommand (这是命令模式的一个例子)包装所有的对外部系统(或者依赖)的调用,典型地它们在一个单独的线程中执行
- 调用超时时间比你自己定义的阈值要长。有一个默认值,对于大多数的依赖项你是可以自定义超时时间的。
- 为每个依赖项维护一个小的线程池(或信号量);如果线程池满了,那么该依赖性将会立即拒绝请求,而不是排队。
- 调用的结果有这么几种:成功、失败(客户端抛出异常)、超时、拒绝。
- 在一段时间内,如果服务的错误百分比超过了一个阈值,就会触发一个断路器来停止对特定服务的所有请求,无论是手动的还是自动的。
- 当请求失败、被拒绝、超时或短路时,执行回退逻辑。
- 近实时监控指标和配置变化。
当你使用Hystrix来包装每个依赖项时,上图中所示的架构会发生变化,如下图所示:
每个依赖项相互隔离,当延迟发生时,它会被限制在资源中,并包含回退逻辑,该逻辑决定在依赖项中发生任何类型的故障时应作出何种响应
具体实现可移步:git个人开源spring cloud脚手架,快速上手开发