今天,我们将从存储上层“服务维度”学习架构师的第二个通用能力——微服务设计与治理。如何设计合理的微服务架构?如何保持微服务健康运行?这是我们在微服务架构设计过程中非常关心的两个问题。本文为微服务的生命周期定义了七个阶段,如下图所示。围绕这七个阶段总结出16条共同原则。一、微服务规划原则1:根据业务能力规划或拆解微服务。康威定律:康威定律:设计系统的组织[...]被迫产生设计,这些设计是这些组织的通信结构的副本。.)组织沟通与系统设计之间存在密切联系,尤其是在复杂系统中。只有解决了人与人之间的沟通,才能实现更好的系统设计。《人月神话》总结了通信成本随着人员的增加呈指数增长的规律:通信成本=n(n-1)/2。例如:5人项目组,沟通渠道为5*(5-1)/2=1015人项目组,沟通渠道为15*(15-1)/2=10550人项目组,以及需要沟通的渠道是50*(50–1)/2=1225,系统越复杂,人越多,沟通成本会成倍增加。因此,分而治之是大多数公司选择的解决方案。分为不同的层级,分成不同的小团队,让团队完成自治。原则二:按照领域驱动设计(DDD)规划或拆解微服务。领域驱动设计是微服务领域的热门话题。本文不做解释,只讲几个重要的:基本流程:抽象业务,分析流程,识别边界,建立模型,映射到服务和代码避免过度耦合,存在于贫血领域的对象等。划分边界明确上下文之间的映射关系,如合作关系、共享内核、客户-供应商开发、防腐层、开放主机服务等。细化上下文对象、区分实体、值对象、聚合根、领域服务和域事件。原则2与原则1的区别在于,原则1侧重于组织结构领域,而原则2更倾向于软件工程设计领域。2、微服务设计原则3:微服务的设计要遵循“单一职责”的原则。所谓单一职责原则,就是对于一个服务来说,它的功能应该是单一的,只做与其相关的事情。在微服务的设计过程中,需要按职责进行设计,保持相互正交,互不干扰。什么样的具有单一领域对象的单一职责微服务是有价值的?是业务不断变化,能保持业务持久性,具有业务生命力的领域对象。比如:相对于其他功能点,如果调用频率很高或者数据量很大,数据增长速度很快,TB级别甚至PB级别,那么独立成为微服务实现独立是非常有价值的进化,个性化弹性伸缩。因此,我们在设计微服务的时候,需要能够分析和预测需求在哪里发生变化?高并发点在哪里?数据增长在哪里?结合DDD分析,找出最有价值的单一职责,进行合理适度的域、子域、限界上下文分解,更好地应对复杂多变的业务。原则四:微服务的设计要遵循“高内聚”的原则。过分追求“单一职责”或将微服务拆分得太细,往往会导致不良后果。微服务的设计并不是越详细越好。过多的拆分会导致调用性能变差,数据一致性难以保证,系统可用性降低。因此,“高内聚”原则要求:完全独立:微服务粒度的下界是至少要满足独立性,能够独立发布、独立部署、独立运行、独立测试。足够的内聚性:强相关的功能和数据在同一个服务中处理。足够完整:一项服务至少包含一个业务实体和对应的完整操作。原则五:微服务的设计要遵循“低耦合”的原则。避免过多的数据暴露。避免数据库共享。尽量减少同步调用。如有必要,引入事件驱动的异步调用。三、微服务实现原则6:服务无状态。什么是“状态”?如果一个数据需要被多个服务共享来完成一个事务,那么这个数据就叫做状态。依赖于这种“有状态”数据的服务称为有状态服务,反之则称为无状态服务。“无状态”原则并不是说微服务架构中不允许有状态,而是要把有状态的业务服务变成无状态的计算服务,然后将状态数据迁移到对应的“有状态状态数据服务”。场景描述:比如我们之前在本地内存中建立的数据缓存和会话缓存,在现在的微服务架构中,这些数据应该迁移到分布式缓存中存储,让业务服务成为一个无状态的计算节点。迁移后可以实现按需动态伸缩,微服务应用可以在运行时动态增删节点,无需考虑如何同步缓存数据。只有服务无状态,才能实现快速弹性伸缩,应对流量高峰和低谷。原则7:高服务可用性。接入高可用中间件(如sentinal),实现限流、熔断、降级、增强可用性。原则8:服务是可观察的。除了默认的系统监控,微服务还需要梳理定义必要的“业务监控指标”。原则9:服务配置是可管理的。微服务相关的配置需要统一接入配置中心进行管理和控制。4、微服务调用原则10:避免“分布式大单体”。只进行单向调用,避免循环调用。多个服务周期依赖调用,形成一个中心化的“分布式大单元”,违背了微服务的原则。原则11:异步解耦。按需接入消息队列实现“依赖解耦”和“流量调峰”串行同步调用异步化,提高响应能力和响应速度应对突发流量,实现流量调峰和流控解耦核心业务逻辑不consistent业务设计中必须依赖最终一致性原则12:引入BFF层,降低客户端与后端微服务的耦合度。尽可能设计BFF层,把前端的特殊需求交给BFF层,让后端业务逻辑有精简的核心逻辑,高内聚,高复用。5、微服务发布原则13:服务发布遵循安全发布三原则。保证“灰度”、“可监控”和“可回滚”。6、微服务治理原则14:正视“架构腐败”,遵循“持续进化”原则。“架构腐败”的常见场景:多人维护一个微服务,出现“频繁的代码冲突”,影响快速迭代,需要拆分这个微服务。当你修改了一个小的角落功能,但又不敢马上上线,因为你所依赖的其他模块才开发了一半,存在大量的“功能耦合”,那么这个微服务就需要拆分了。当你发现微服务A中聚合A的功能变成了海量的高频业务。这时候聚合A会拖累整个微服务A,而且由于聚合A面临性能瓶颈,微服务A进行弹性伸缩时,也会造成资源浪费。此时,我们可以将AggregationA从微服务A中拆分出来,作为一个整体,独立创建一个新的微服务B。在资源分配上,微服务B也可以更有针对性的投入,可以满足高性能需求-频率随时访问。当你发现在领域建模时错误地将聚合d放在了微服务C中,或者随着业务的发展聚合d更适合放在微服务D中。由于领域模型不合适,可能会导致微服务之间频繁调用,进而导致微服务之间形成“紧耦合关系”。这时候我们就可以对领域模型进行调整,将聚合d从微服务C整体迁移到微服务D。原则15:参照“AKFExpansionCube”模型,服务除了“横向扩展”,还可以考虑“功能拆分”或“数据分区”。1)X轴:服务和数据的横向扩展“横向扩展”比较容易理解。说白了就是加机器。根据AKF模型,除了增加机器,我们还可以考虑“功能拆分”或者“数据分区”。2)Y轴:功能/业务拆分“功能拆分”比较复杂,一般包括几种模式:微服务拆分。根据特定的业务模型和领域模型拆分更细粒度的微服务。业务隔离和拆分。使用消息队列拆分和隔离消耗大量资源的在线业务(OLTP)和计算任务。核心和非核心隔离。对于一个微服务,SKA客户端可以和普通客户端隔离,SKA客户端使用独立的集群资源来提高稳定性。3)Z轴:沿客户边界划分服务和数据“数据划分”通常指的是数据库级别。需要引入数据库中间件,如sharding-jdbc、mycat等,并在数据层面配置相应的分片逻辑。正确的拆分对提高系统容量有很大帮助,拆分失败可能会造成热点集中,得不偿失。常用的分区逻辑包括按时间分区、按用户id取模分区等。7、微服务下线原则16:对于“废弃的服务”,要做好“下线”,包括服务下线、存储释放等,清理无效代码、环境,降低维护成本。同时释放资源,节约成本。8.总结架构师在进行微服务设计和微服务治理时,可以关注微服务生命周期的七个阶段。本文总结了16条常用的原则,希望能提供一些思路和启发。
