互联网产品特点 > 单体架构不足 > 微服务

迁移微服务架构前的准备

架构改造过程中可以遵循的规则

互联网产品特点

创新成本低、需求变化快,用户群体庞大

单块架构维护、人员培养、缺陷修复、技术架构演进、系统扩展成本等无法适应

软件架构经典模式之三层架构

一层(页面、业务、数据库访问逻辑放一起) > 二层(数据访问层独立了) > 三层(表示 逻辑 数据)

解决代码间调用复杂、代码职责不清

各层间定义接口,接口实现分离,不同层易替换,降低层间依赖,后期维护成本,利于制定整个应用程序架构的标准

根据技能调配人员,提高生产效率

存储过程或触发器将业务逻辑放在db,大大增加后期维护复杂度和数据迁移成本

单体架构应用

三层架构帮助将应用在逻辑上分成了三层,但并不是物理上的分层,还没有考虑负载均衡以及水平扩展的情况

单体架构的挑战

传统企业代码在 100 万行比比皆是,庞大复杂的项目开发、测试、维护、运维极度复杂,弹性、扩展性、可维护性方面也困难重重

  • 团队接手困难

100 万行的噩梦项目,3 个月的时间通读一遍代码;每次修改代码心惊胆战,修改一个 Bug 极可能带来各种隐含的缺陷

  • 新人培养周期长

看文档,装环境

第一次配置完开发环境后,好几年都不愿意再升级或者重装系统,一招被蛇咬,十年怕井绳

  • 臃肿的部署

每次功能或者缺陷的变更,重新部署整个应用,影响大、风险高,部署频率低,两次发布之间有大量的功能或者缺陷需要进行变更,出错概率增高

  • 局限的弹性与扩展能力 ​
    单体应用作为一个强耦合的整体,无法根据业务功能伸缩,只能作为一个整体进行扩展

资源浪费,同时无法针对不同业务模块的特性进行有针对性的伸缩,比如计算密集型服务、IO 密集型服务

  • 技术选型成本高

团队对新技术的渴望是不言而喻的,士气会因为持续的关注在巨石应用的技术栈而降低

初始技术选型严重限制了将来采用不同语言或框架的能力

如果想尝试新的编程语言或者框架,没有完备的功能测试集,很难平滑的完成替换,而且系统规模越大,风险越高

单体式架构下的组织通常来说技术选型非常单一,团队技术能力相对单薄,团队的吸引力一般

对于服务等级、安全要求、业务监管等多个维度均需要针对不同的服务实现不同的治理,迁移到微服务架构成为必然

  • 可伸缩性差

迫切的需要扩展,垂直扩展可能是最容易的(钱不是问题),IOE,不用改变一行代码,整个世界都变好了

业务的增长,数据的增长,垂直扩展会变得越来越吃力,成本越来越高

水平扩展时,通常建集群,集群中不断的添加新节点,借助LB,将请求按某种算法,如轮转法、散列法或者最小连接法等合理的将请求分配到不同的节点上

但代码都运行服务器同一个进程中,导致水平扩展成本非常高

某部分功能是内存密集型,而另外一部分功能是 CPU 密集型的

某些节点保持状态,如用户登陆后的会话信息等,更增加了水平扩展的难度

基础设施整体花费非常高

迁移微服务架构前的准备

零号原则

对业务充分了解

因历史原因导致了解业务系统了的人屈指可数时,就试图转向微服务架构,即使采用最好的技术、工具、架构、团队,最后都会摔得很痛(无休止的拆分与变更)

充分了解业务的前提下,向微服务迁移,还需三个维度准备:

1、偿还技术债务

  • 自动化测试

团队管理大量服务,其复杂度和测试难度是几何级增加

帮助团队快速有效的验证应用

  • 持续集成与自动化部署

保障团队更快速、更容易的修改代码

缺少持续集成和自动化部署,向微服务架构转型过程会异常痛苦

2、新的架构设计原则

采用微服务架构,应用交付高度复杂化

架构设计原则需要从原来单体式架构下的关注功能、性能等维度向

  • MVP(最小可用产品)
  • 面向失败的设计(拥抱失败,而不是阻止失败)
  • 宽进严出(对请求宽进严出,对外的响应要严格规范化)
  • 宁花机器一分,不花人工一秒(自动与自助、复杂重复的事情交给平台工具去做,让程序员去做更有价值的事情)
  • 一切皆资源

等设计原则转变,形成架构渐进优化的设计风格

3、团队变革

《Exploring the Duality Between Product and Organizational Architectures》书中给了一个很有意思的观点,组织的耦合度与系统的模块化成正比

组织耦合度越高,所开发的产品耦合度越高

组织耦合度越低,所开发的产品耦合度也越低

微服务架构本质上在强调松耦合的架构,因此在微服务架构迁移前,我们有必要对组织进行微调(不要变革,对组织影响很大),确保独立的、小的团队交付一个微服务,同时小团队是微服务的 Owner(除了负责开发外,同时负责测试和运维)

这会极大提供团队的责任感,加速微服务的自治和交付能力

架构改造过程中可以遵循的规则

基于业务进行拆分、采用自动化文化、去中心化、服务独立部署、服务完全自治、隔离失败、渐进式拆分、避免大规模改造原有代码等原则

实践经验

1、先分离数据库、后分离服务

数据模型能否彻底分开,决定了微服务的边界功能是否彻底划清

太多直接从服务分离而造成多次重构和返工的案例

2、“绞杀者模式”

无法修改的遗留系统,推荐采用绞杀者模式:

在遗留系统外面增加新的功能做成微服务方式,而不是直接修改原有系统,逐步的实现对老系统替换

3、统一日志规范

规范整个系统而非微服务的日志体系,标准日志格式便于后续日志聚合检索,整体视角分析、监控、查看系统

4、选择成熟框架

同时做两件不可控的事情(微服务改造、新技术的冲击)注定项目成功概率较低,千万避免自己重复发明轮子,尽量选择市面上成熟的开源技术框架进行支撑

Spring Boot、Spring Cloud、Netflix、WildFly Swarm、Docker、Kubernetes 等框架

还有很多细节规范,比如前后端分离原则、全局唯一流水号原则实现全链路交易跟踪、如何进行服务的文档化管理及服务测试 Mock 等

  • 数据库方面调整

这个话题非常有意义,微服务改造,第一件事情就需要针对数据库模型进行拆分,数据模型边界划清后,服务顺利成章容易划清界限

强烈推荐的原则是一个微服务对应一个库。随着微服务规模壮大,可以针对性的做读写分离;单表数据庞大,分表解决

实现实现最终一致性 三种模式

微服务架构下,完整交易跨越多个系统运行,事务一致性是一个极具挑战的话题

依据 CAP 理论,在微服务架构下应选择可用性,然后保证数据的最终一致性

https://ddatsh.com/post/microservice-consistency/

微服务架构下数据一致性保证(一)http://dwz.cn/3TVFHs

微服务架构下数据一致性保证(二): http://dwz.cn/3TVHBW

微服务架构下数据一致性保证(三):http://dwz.cn/3TVJaB

中间件的使用

MySQL、Redis 等中间件适合作为微服务独立出现

大块头 Oracle、DB2 或者诸如 Queue 的产品,不适合作为独立微服务出现,可以采用集成的方式工作

微服务架构需要和新的中间件平台提供融合,IaaS 平台、PaaS 平台等

微服务框架内部,有大量新的中间件的产品,比如 etcd、motan、resteasy、ELK 等

对于中间件的使用,保持一个原则:业务逻辑放在服务中,尽量保持中间件的简单

改造过程中如何规避风险以保证平滑过度

1、重视运营平台建设

实施微服务改造前,建议先行搭建好运营支撑平台,平台至少提供微服务的编译、集成、打包、部署、配置等工作

如果有能力建议采用 PaaS 平台,解决微服务从开发到运行的全生命周期管理,同时提供异构环境管理、容器资源隔离与互通、服务伸缩漂移、服务升级与回退、服务熔断与降级、服务注册与发现

平台帮助开发人员解决更多的技术问题,开发人员专注在业务功能的拆分上

2、从试点入手,逐步推进

业务应用分级,先外围应用试点;经验丰富后,核心应用迁移和大规模改造

三个关键点:

针对业务系统,重新梳理概念模型 + 数据模型,切分出松耦合、高内聚的微服务,保障项目组在做正确的事情

制定微服务开发规范(包括技术架构,Spring Boot+Motan+etcd+RESTEasy+Elasticsearch+Docker+Kubernetes 技术架构选型),保障项目组按照统一的开发规范(技术架构)正确做事

微服务拆分之后,最大的挑战来自于运维、监控、故障处理,如果团队没有微服务运行的经验,故障之后无法快速定位、快速回复,会受到更大的业务压力,因此后期的微服务运营平台或者管理平台对团队异常重要,需要配套设计及时跟上,支撑微服务的运行管理