上篇文章:分布式系统漫谈【陆】_SOA和微服务
本文继续说说微服务面临的一些挑战和解决方案。
微服务的挑战
在使用微服务架构后,由于服务间的调用不再是进程内的调用而是通过轻量级的网络协议通信,而众所周知网络不不可信的,因此服务可能出现出错、超时或宕机等问题。因此在微服务架构设计时,我们就要把这部分问题考虑进去,下面说说我们应该采取哪些措施和方案去解决。
舱壁模式
舱壁模式是指,当一艘船沉了,某个舱壁淹水不要影响其他舱壁。由此可见,舱壁的设计主要是为了隔离。在微服务设计中,我们可以考虑使用如下方案来舒心啊舱壁模式:
一、微服务容器分组
将微服务系统分为测试环境、灰度环境和生产环境。使用灰度环境去跑一些普通用户的流量,相当于内测,没问题后,再全量放开到生产环境。
以微博为例。据说某浪微博把名人的流量放到核心池子中,普通用户流量路由到另外一个池子。核心池子的容量以及机器配置都高于另外的普通池子(没错,就是这样区分对待的)。通过这样的实现了隔离普通用户和重要用户的负载。
二、线程池隔离
在搭建微服务系统时,由于团队和财务等因素我们不一定把每个服务拆分到很微小的粒度。所以多个功能可能部署在一个微服务实例中,使用同一个线程池。如果一个功能流程增加耗尽线程池的线程,可能阻塞其他功能的服务。
因此我们尽量让核心的服务享有单独的线程池,将一些边缘的和不重要的服务共享一个线程池。
熔断模式
类似于家里的保险丝原理。当一个服务请求量过大几乎要超过机器性能瓶颈时,我们需要设置一个断路器,让其请求快速返回失败,避免发生系统雪崩效应。熔断模式的大概流程图如下:
限流模式
控制访问的并发量,比如每秒允许处理的并发用户数及查询量、请求量等。主流的方法如下几种:
一、计数器
通过原子变量计算单位时间内的访问次数,超出阈值,拒绝后面请求,等到下一个单位时间重新计数。
二、令牌桶
通过一个线程在单位时间内生产固定数量的令牌,然后把令牌放入队列,每次请求调用需要从桶中拿去一个令牌,有令牌才有资格执行请求调用,否则只能等到拿到令牌再执行,或直接丢弃。
三、漏桶
类似漏斗,请求可以任意速率流入,但流出的流量是有限的。桶容量也有限,当满了后新来的请求被丢弃(或进入等待队列),可考虑使用Semaphore实现。
四、失效转移模式
如果微服务系统中已发生了熔断和限流,可通过如下方式处理已拒绝请求:
1.快速失败策略,直接返回使用方错误,让调用方知道发生问题;
2.切换到备份服务;
3.采用重试机制,但是注意幂等性;
降级模式
在流量高峰到来的时候,可以考虑将一些非核心的服务停掉,或者换成异步处理,来保证核心服务的稳定性以及主业务流程可以跑的通。对于服务的降级,有如下几个要点:
1.设置全局降级开关,可以推送至各个微服务应用,并应用中将服务读取开关的逻辑尽量前置;
2.对读服务的降级,开关开启后可设置为只读本地缓存、分布式缓存或降级数据;
3.对写服务的降级,开关开启后可考虑将服务改为异步调用,直接返回给调用方成功;