主题
服务容错
服务之间的依赖关系导致调用失败,解决的方式通常是:限流 -> 熔断 -> 隔离 -> 降级
限流
当高并发或者瞬时高并发时,为了保证系统的稳定性、可用性,系统以牺牲部分请求为代价或者延迟处理请求为代价,保证系统整体服务可用。
限流算法
令牌桶算法
先有一个桶,系统按照固定速度往桶里面放入令牌,如果桶满了则不再放入。当请求到来时,从桶中取出令牌,获得了令牌的请求可以继续处理,没有令牌的请求就拒绝服务。
在没有请求时,桶会积累一些令牌。当有突发流量时,只要令牌足够,就能一次全部处理。因此,令牌桶算法可以处理突发流量。
令牌桶算法是网络流量整形和速率限制中最常用的一种算法。
漏桶算法
水(请求)先进入到桶里,桶按一定的速度(接口有响应速率)出水,当水流速度过大(请求过多)时,桶会直接溢出(访问频率超过接口响应速率),然后拒绝请求。因为桶的出水速率是固定的,所有漏桶算法对突发流量的处理缺乏效率。
计数器算法
计数器限流算法也是比较常用的,主要用来限制总并发数,比如数据库连接池大小、线程池大小、程序访问并发数等都是使用计数器算法。也是最简单粗暴的算法。
- 统计当前并发数,超过阈值直接返回系统繁忙等响应。
- 基于信号量控制并发次数,超过阈值进入到队列中排队等待,可以给队列设置一个最大值,超过最大值则拒绝请求。
- 固定大小的线程池。
熔断
当错误数超过阈值时快速失败,不调用后端服务,同时隔一段时间放几个请求去重试后端服务是否能正常调用,如果成功则关闭熔断状态,失败则继续快速失败。熔断流程通常使用断路器模式实现。
断路器模式有3个基本状态和1个基本动作trip:
- close 状态:客户端的请求直接无障碍通过断路器到达服务端,服务端的响应也直接无障碍通过断路器返回给客户端。即畅通无阻。
- open 状态:客户端的请求经过断路器后直接返回给客户端,不会将请求转到服务端。
- trip:在 close 状态下,如果服务端持续超时报错,达到规定的阈值后断路器就发生trip,之后断路器由close状态变为open状态。
- half-open 状态:在 open 状态下,断路器会每隔一段时间尝试调用服务端,如果服务端正常则断路器由open状态变为close状态。在断路器重试期间,其处于half-open(半开)状态。
隔离
把每个依赖或调用的服务都隔离起来,防止级联失败引起整个服务不可用。比如使用线程池来隔离资源,一个服务里面要调用另外两个服务A和B,如果这两个服务都使用同一线程池,当服务A卡住时,资源不会被释放,后面的请求又来了,全都卡在这里导致线程池资源耗尽,也影响了服务B的可用性。而如果隔离起来,假设现在有100个线程可用,给A服务和B服务各分配50个线程,这样即使A服务挂了,B服务依然可用。
降级
服务失败或异常后,返回指定的默认消息。