微服务系统架构设计:基本原则与理论分析

@[TOC]

一、从不同维度对微服务进行拆分

1、DDD

提起微服务拆分,很多小伙伴立马想起非常火爆的一个概念:DDD,但是互联网应用没有"银弹",除了DDD,还有其他微服务拆分的方式。

本文暂不讨论DDD微服务拆分,后续有时间单独成篇讨论DDD。

2、压力模型

有以下几种服务器压力的模型:

  • 高频高并发流量:用户点击的频次高、并发高。比如说电商项目中的商品详情页
  • 低频突发流量:访问频次不高,但是突发流量高。比如说电商项目中的秒杀商品
  • CPU密集型:占用大量CPU计算资源,比如说一些复杂的计算。
  • IO密集型:占用大量的磁盘IO与网络IO,比如说文件传输。

在这些,对服务器性能和代码的健壮性要求很高的业务模块中,经常需要实现服务隔离而将这些模块单独部署,为了防止突发流量服务器压力过大造成崩溃,导致服务不可用而牵连其他应用。因此,我们通过服务隔离,可以很好地保护其他服务。

再者,将这些模块隔离出来,可以很好地做一些流控措施,比如说一些削峰填谷以及流控的手段。

对于热点数据,通常仅仅隔离服务还远远不够,有时候还需要隔离底层的热点数据。比如说秒杀商品,可以将这些商品使用缓存等单独处理。

还有一些热点新闻等,一般可以通过API调用策略,后台触发这些热点数据的探测,进行动态热点数据的隔离

3、主链路规划

对于用户行为的主链路,一定要将每一个模块单独拆分出来,不用完全的顾及领域模型,这完全是根据业务的角度进行规划的主链路

比如说电商项目,用户搜索->详情->购物车->下单->支付,这一整个主链路,完全可以单独拆分出来。这样做的好处就是,可以做到与边缘业务服务隔离,如果服务器压力过大,可以将这些服务进行弹性伸缩、流控、容错等等更加精细的控制。与边缘业务隔离开之后,也可以避免边缘业务影响到主链路的正常使用。

4、用户群体

比如说很多电商中的用户群体,有商家用户、消费者用户、运营用户、采购用户等等,可以将这些用户进行单独拆分。

还有很多教育平台,分教师、学生等等用户。

其实很多网站,不单单是只有一个APP入口,通常来说不同的用户角色都会对应着不同的系统入口,比如说滴滴就分乘客APP和司机APP。为了使系统更加清晰,可以对不同的用户进行独立拆分,各自维护。

二、设计微服务的无状态化

1、什么是无状态

无状态(stateLess),也就是上下文并没有依赖。

比如说用户登录状态Session,单机环境下,Session存在服务器本地,用户每次登录需要获取到当前登录的用户信息,这就叫有状态。这样的话,该服务就无法做到横向扩容,增加一个服务节点之后无法做到服务节点之间的Session共享。解决方案也很简单,将Session存储到一个公共存储空间即可比如redis。

再比如本地缓存。单机环境下,如果数据库响应过慢,通常会将部分热点数据保存在服务的内存中,但是增加服务节点之后同样会导致多个节点中的内存数据不一致。同样也可以使用一个公共存储空间来解决这个问题。

2、为什么要追求无状态化

无状态化完全是为了实现服务的横向扩缩容。如果服务设计为有状态,这会限制该服务的横向扩缩容。

3、如何设计无状态化

为了保证服务的无状态,需要实现数据的分发、处理、存储,任意节点的可达性

也就是一个用户请求,不论是落在服务器集群中的任意节点上,都可以完成该请求的处理。

通常来说,实现服务的无状态,就需要在其他方面做到有状态,比如说存储、配置等等。

三、接口的版本控制:向后兼容

1、为什么要做接口的向后兼容

当一个新功能迭代较快时,接口的功能会不断完善和优化,但是下游系统有时候并不会同步进行升级。所以为了兼顾老系统,需要同一个接口功能需要进行老旧功能兼顾,做到向后兼容。

2、兼容方式:if-else

很简单的代码逻辑,通过加一个参数,表示我想调用该接口的哪一个版本,通过if-else的方式进行向后兼容。

有的小伙伴可能编码能力很强,使用策略模式等等一系列的手段,对代码进行更细粒度的拆分。

但是这样的情况会导致,该接口的代码会越来越臃肿难以维护。一个小小的改动通常会牵一发而动全身,而且需要保证测试用例要把历史的情况全覆盖。

3、兼容方式:API Version

通过API的版本将不同的访问请求,路由到不同的接口中。

这样做的好处是,可以兼容老业务,并且实现接口的隔离。

如果使用rpc框架的话,通常很多rpc框架都实现了自动根据接口的版本来查找接口,比如说dubbo:

xml 复制代码
<dubbo:reference id="production" version="1.0.1" interface="IProductionService"/>

对于http接口,可以通过path实现:app/v1app/v2app/v3,通过接口的版本进行接口的隔离。 还可以通过使用header的方式,在header中指定一个版本号,通过业务网关根据header,进行接口的路由。

四、可用性保障:限流

1、限流的维度

通常来说,会考虑根据以下几个维度进行流量的限制:访问频率、IP连接数、黑白名单、传输速率

网关层限流资源消耗最小,业务层限流更加精细。通常来说网关层并不会涉及过多的业务逻辑,如果达到限流策略,直接触发快速失败策略。业务层限流可以实现更加精细、自定义的限流处理。

2、网关层限流

网关层限流是资源消耗最小的,通常会实现一些访问频率、IP连接数、黑白名单、传输速率的限流手段。

使用Nginx+Lua组合可以实现非常靠谱的Nginx层限流。并不会牵扯过多的业务逻辑

3、业务层限流

业务层限流,可以实现一些流量更加精细的限制。

业务层网关限流,比如说Gateway,也算是业务层限流,可以做到一些很精密的限制,不光是限流,还有降级、熔断以及复杂的谓词判断。

还可以借助很多限流组件,比如说Sentinel、Redis+Lua、单机的Guava包等等。

五、BASE理论

Base 是三个短语的简写,即基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)。

Base 理论的核心思想是最终一致性,即使无法做到强一致性(Strong Consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual Consistency)。

六、幂等性处理

接口的幂等性------详细谈谈接口的幂等即解决方案

相关推荐
苏打水com3 分钟前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧1 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧1 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧1 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧1 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧1 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng3 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6013 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring
Lisonseekpan3 小时前
Guava Cache 高性能本地缓存库详解与使用案例
java·spring boot·后端·缓存·guava
4 小时前
JUC专题 - 并发编程带来的安全性挑战之同步锁
后端