4.1、简介
最经典的比喻就是轮船的设计,隔离设计的英文叫”Bulkheads”,被翻译为隔板,我们的轮船的船舱就是通过隔板隔离出来的空间。其中一个船舱进水了,并不会影响其他船舱,也不会造成沉船,是一种很安全的设计。
在我们微服务的设计当中,难免一些服务”进水(故障)”,隔离设计保证其中一个服务出现问题,其他服务可以保证正常提供服务。
4.2 隔离方案
4.2.1、按业务隔离
这里我们我们按照业务分为三个模块。活动页、首页feed、社交关系。很多业务场景,打开首页的时候,弹出活动页,提示你参加活动,进入活动页H5。
同样根据业务分组,我们将DB资源也进行了隔离。不同的业务对应不同的资源。通过这种分组隔离,我们可以保证如果活动页出现了问题。最差的影响是进入App,首页的活动页消失,这种影响对于用户来说,也仅仅是不能参加活动而已,不影响App的正常使用。
设计隔离的粒度在细,也难免出现跨业务的调用。比如首页关注feed流,拉取所有我关注人发布的信息。如果使用pull的方式,必然先去调用”社交关系”业务模块的相关服务。如果社交依赖业务出现问题。同样也会影响feed流。当然你也可以使用push的模式,将资源隔离的粒度更细,甚至完全独立(就是下面分享的多租户模式)。这种会带来资源冗余度高的问题。
- 针对业务之间的交互,首先保证自身业务的高可用,其次可以通过消息队列订阅通知的模式实现业务之间的消息互换。
- 针对业务的依赖,可以采用二阶段提交的方式。
4.2.1.1、小结
- 隔板的设计围绕业务的需求与技术的需求
- 如果生产者与消费者之间被隔离,比如利用消息队列,这个时候通过隔离的粒度来评估实现的成本,管理的复杂度,以及性能的开销。
- 需要考虑因为隔离产生的异常如何处理,重试、熔断、限流。
4.2.2、按用户隔离
根据用户维度进行隔离,就是根据不同的用户进行分区。每个分区对应一个服务实例,或多个服务实例。其中ServiceA中的一个实例挂了,只会影响Client1的用户,Client2与Client3的用户可以继续访问,不被影响。
“多租户”架构设计很因为隔离粒度的不同,产生不同的复杂度。但是一般是已下三种设计方案:
- 接口分区,数据分区
- 接口共享,数据分区
- 接口共享,数据共享
对应的,资源共享度越来越高,复杂度越来越高,隔离性越来越低,资源成本越来越低。从分析中可以看出,接口分区,数据分区,接口共享,数据共享,属于两个极端。一般采用接口共享,数据分区。
接口共享,针对不同的用户,不同用户间的数据进行隔离。例如,做活动相关业务,每个人活动状态,活动进度,就可以完全独立开。甚至是多个不同活动的业务,也可以进行区分隔离。
例如:redis有序集合
1 | key:tasks_accepted_{用户di}_{活动业务id} |
4.3 总结
隔离设计选择根据用户维度进行隔离还是根据业务级别隔离,需要根据业务来恒定。甚至两种都结合使用。在设计中需要注意以下几点:
- 隔离粒度根据业务来权衡
- 隔离设计要保证服务的高可用,因为隔离产生的异常处理,限流,熔断,重试。
- 消费者与生产者之间交互方式,结合复杂度引入如消息队列的技术方案
- 将服务之间隔离,利用容器可以很好的平衡资源。考虑好运维方案。
- 当将服务划分为隔板时,考虑将它们部署到单独的虚拟机、容器或进程中。容器提供了很好的资源隔离平衡和相当低的开销
- 监控每个分区的性能和流量等