保证系统稳定的技术

保证系统稳定的一些技术

	一个现代化的公司离不开各种系统,而系统的可用性则是最重要的。作为吃这碗饭的我们,如何保证系统的高可用就是我们该研究的东西。

保证系统稳定的技术_第1张图片 通常来说,影响系统的关键因素有几大方面,硬件、软件、资源,我们的本职工作是软件的层面。
我们的软件常称为系统,不同系统之间用的架构风格不同,归根到底是业务量的不同,或者说并发量的差异。要构建高并发系统我们可以选用springcloud的一些东西。

理论篇

保证服务高可用的一些措施:
一、熔断
保证系统稳定的技术_第2张图片
  服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用
上面的解释中有两个很关键的词,一个是暂时,一个是停止。
停止是说:当前服务一旦对下游服务进行熔断,当请求到达时,当前服务不再对下游服务进行调用,而是使用设定好的策略(如构建默认值)直接返回;
暂时是说:熔断后,并不会一直不再调用下游服务,而是以一定的策略(如每分钟调用 10 次,若均返回成功,则增大调用量)试探调用下游服务,
当下游服务恢复可用时,自动停止熔断。
二、限流
  限流是指上游服务对本服务请求 QPS 超过阙值时,通过一定的策略(如延迟处理、拒绝处理)对上游服务的请求量进行限制,以保证本服务不被压垮,从而持续提供稳定服务。常见的限流算法有滑动窗口、令牌桶、漏桶等。
保证系统稳定的技术_第3张图片
上图,当 ServiceB 对 ServiceD 请求过多时,ServiceD 可以放弃一部分请求,保证自身服务的稳定。
三。降级
降级是指当自身服务压力增大时,采取一些手段,增强自身服务的处理能力,以保障服务的持续可用。比如,下线非核心服务以保证核心服务的稳定、降低实时性、降低数据一致性。
总结

措施 产生原因 服务位置
熔断 下游服务不可用 下游服务
降级 自身服务的处理能力不够 自身服务
限流 上游服务请求增多 上游服务

hystrix篇

SpringCloud中,使用Hystrix来实现熔断。Hystrix 是一个帮助解决分布式系统交互时超时处理和容错的类库
保证系统稳定的技术_第4张图片
  它有三种状态:关闭,开启和半开。最开始是关闭状态的,这个时候所有请求都可以通过;如果错误请求达到一定的阈值,就会变成开启状态,就会让所有请求短路,直接返回失败的响应;一段时间后,断路器会变成半开状态,如果下一个请求成功了,就关闭断路器,反之就开启断路器

(1)hystrix.command.default.circuitBreaker.requestVolumeThreshold(当在配置时间窗口内达到此数量的失败后,进行短路。默认20个)
简言之,10s内请求失败数量达到20个,断路器就会变成打开状态。
(2)hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds(短路多久以后开始尝试是否恢复,默认5s)
(3)hystrix.command.default.circuitBreaker.errorThresholdPercentage(出错百分比阈值,当达到此阈值后,开始短路。默认50%)
 /**
 * 获取信息
 * @return
 * @throws InterruptedException 
 */
@ResponseBody
@GetMapping(value="/getInfo")
@HystrixCommand(fallbackMethod="getInfoFallback")
public Map getInfo() throws InterruptedException{
    Thread.sleep(2000);
    Map map=new HashMap();
    map.put("code", 200);
    map.put("info", "业务数据xxxxx");
    return map;
}
 
public Map getInfoFallback() throws InterruptedException{
    Map map=new HashMap();
    map.put("code", 500);
    map.put("info", "系统出错,稍后重试");
    return map;
}

hystrix的容错机制-隔离措施
  资源隔离主要指对线程的隔离。Hystrix提供了两种线程隔离方式:线程池和信号量。将请求按照服务器进行划分,创建不同的线程池。一个服务对应一个线程池,当一个线程池出现阻塞,不影响其他线程池的服务。缺点是维护线程池增加了服务开销,优点是可以避免服务雪崩。信号量隔离:配置一个信号量上限,当并发请求量超过信号量个数时,后续的请求都会直接拒绝,进入fallback流程。信号量隔离主要是通过控制并发请求量,防止请求线程大面积阻塞,从而达到限流和防止雪崩的目的。
常见的限流算法
一、计数器算法
  顾名思义,计数器算法是指在一定的时间窗口内允许的固定数量的请求.比如,2s内允许10个请求,30s内允许100个请求等等.如果设置的时间粒度越细,那么相对而言限流就会越平滑,控制的粒度就会更细.
场景分析
试想,如果设置的粒度比较粗会出现什么样的问题呢?如下图设置一个 1000/3s 的限流计数统计.
在这里插入图片描述
图中的限流策略为3s内允许的最大请求量为1000,那么会出现2个极端:
极端情况:
  第1s请流量为10,
  第2s请流量为10,
  第3s请流量突然激增到980.这意味着在这一刻,有大量的请求蜂拥而至,假设服务每秒能处理的上线为800/1s,但是此刻却有超过这个量级的请求量,那么后果是不堪设想的.
如果用统计计数算法,尽量保持粒度切割精细.
二、漏桶算法
漏桶算法核心概念:
桶的容量是固定的,并且水流以一个固定的速率流出;
流入的水流可以是任意速率;
如果流入的水流超出了桶的容量,则后续流入的水流溢出(请求被丢弃)。
保证系统稳定的技术_第5张图片

相比令牌桶,漏桶算法,访问服务的TPS比较均匀,不会超出最大的TPS,当访问第三方系统时,对方的接口并发数如果限制TPS,那么相对采用令牌桶比较合适。
三、令牌桶算法
保证系统稳定的技术_第6张图片
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

如果在秒杀、抢购、整点打卡签到、微博热点事件这些业务场景用令牌桶的话,会出现大量用户访问出错,因为请求被直接丢弃了;而用漏桶的话,处理可能只是会慢一些,用户体验会更好一些,所以我认为漏桶更适合“突发流量”。

你可能感兴趣的:(java)