【分布式技术专题】「架构实践于案例分析」总结和盘点目前常用分布式技术特别及问题分析
分布式架构
互联⽹架构演进
单体应⽤架构
定义
⼀个归档包(例如 war 格式)包含所有功能的应⽤程序,我们通常称为单体应⽤。⽽架构单体应⽤的⽅法论,就是单体应⽤架构。
架构示意图
优缺点分析
初期:
架构简单,统一化管理真个服务和生态体系
开发、测试、部署都很⽅便
随着项⽬的发展,项⽬越来越臃肿,问题出现了:
复杂性⾼
只有逻辑性的模块化,物理不隔离,随着代码的增⻓也越来越混乱、复杂。⼀个百万⾏级别的单体应⽤为例,整个项⽬包含的模块⾮常多,模块的边界模糊,依赖关系不清晰,代码质量参差不⻬,混乱地堆砌在⼀起……整个项⽬⾮常复杂。每次修改代码都⼼惊胆战,甚⾄添加⼀个简单的功能,或者修改⼀个 BUG 都会带来隐含的缺陷。
技术债务
时间推移、需求变更和⼈员更迭,会逐渐形成应⽤程序的技术债务,并且越积越多。“不坏不修(Not broken,don’t fix)”,这在软件开发中⾮常常⻅,在单体应⽤中这种思想更甚。已使⽤的系统设计或代码难以被修改,因为应⽤程序中的其他模块可能会以意料之外的⽅式使⽤它。
部署频率低
随着代码的增多,构建和部署的时间也会增加。⽽在单体应⽤中,每次功能的变更或缺陷的修复都会导致我们要重新部署整个应⽤。全量部署的⽅式耗时⻓、影响范围⼤、⻛险⾼,这使得单体应⽤项⽬上线部署的频率较低。⽽部署频率低⼜导致两次发布之间会有⼤量的功能变更和缺陷修复,出错概率⽐较⾼。
可靠性较差,影响范围大
极端场景下,某个 BUG,例如死循环、OOM 等,可能会导致整个应⽤的崩溃。
扩展能⼒受限
单体应⽤只能作为⼀个整体进⾏扩展,⽆法根据业务模块的需要进⾏伸缩。
模块是计算密集型的,它需要强劲的 CPU;
模块则是 IO 密集型的,需要更⼤的内存。
由于这些模块部署在⼀起,我们不得不在硬件的选择上做出妥协。
阻碍技术创新
单体应⽤往往使⽤统⼀的技术平台或⽅案解决所有的问题,团队中的每个成员都必须使⽤相同的开发语⾔和框架,要想引⼊新框架或新技术平台会⾮常困难。例如,⼀个使⽤Struts 2 构建的、有 100 万⾏代码的单体应⽤,如果想要换⽤Spring MVC,毫⽆疑问切换的成本是⾮常⾼的。
微服务架构
诞⽣背景
互联⽹的迅速发展 => 敏捷
快速验证、快速试错 => 持续交付
更频繁的部署频率 => 要⾃动化,DevOps
单体架构⽆法满⾜要求
微服务是什么
微服务架构⻛格是⼀种将⼀个单⼀应⽤程序开发为⼀组⼩型服务的⽅法,每个服务运⾏在⾃⼰的进程中,服务间通信采⽤轻量级通信机制(通常⽤HTTP 资源 API)。这些服务围绕业务能⼒构建并且可通过全⾃动部署机制独⽴部署。这些服务共⽤⼀个最⼩型的集中式的管理,服务可⽤不同的语⾔开发,使⽤不同的数据存储技术。
TPS 分布式架构
Martin Fowler《微服务》博客原⽂:http://www.martinfowler.com/articles/microservices.html,译⽂:http://blog.cuicc.com/blog/2015/07/22/microservices/
微服务优缺点
优点:
单个服务更易于开发、维护
单个微服务启动较快
局部修改容易部署
技术栈不受限
按需伸缩
缺点:
运维要求⾼
分布式固有的复杂性
⽹络延迟、容错、分布式事务...
重复劳动
微服务 vs SOA
微服务设计原则
单⼀职责原则 SOLID
服务⾃治原则
轻量级通信机制
合理的微服务粒度
⾃动化机制:⾃动化测试、部署、运维,⼀切。
调⽤关系设计原则
尽量缩短链路
避免循环依赖
微服务架构通览
服务发现原理+负载均衡原理剖析
最初的模式
单体应用集中式部署
多个应用集中式部署(集群式)
多应用分布式部署(分布式)
多应用分布式部署+TDDL 分布式代理数据
微服务拆分⽅方案
领域驱动设计(DDD)
领域模型:为了准确定义需要解决的问题⽽构造的抽象模型。
领域语⾔ - 定义领域模型时,⼀定要基于某个特定场景,建⽴⼀个⽆歧义的交流语⾔。例如 UML
界限上下⽂ - 限定某个特定边界的上下⽂。对于相同的模型⽽⾔,在不同的场景强调的场景是不太⼀样的。例如:对于订单⽽⾔,从⽤户的视⻆分析,⽤户关⼼的是订单的价格、快递到的时间;从库存的⻆度分析,库存更关注订单的库存的告警等等。
⾯向对象
by name:对象模型
by verb:对象⾏为。
微服务拆分最佳实践
初期使⽤⾯向对象/DDD 建模后拆分即可,不要过分纠结微服务粒度,也不宜拆分得过细(防⽌出现很多不合理的拆分粒度),满⾜当前要求即可。当随着业务的发展,业务场景需要我们进⼀步细化拆分的粒度再去细化拆分或改造。
项⽬改造成微服务
改造前须知
改造不是⼀蹴⽽就的,往往很⻓⼀段时间内,新⽼架构是共存的
改造原则
初期只做必要的微服务治理
缩⼩改造范围,⼩范围试⽔
降低对已有系统的侵⼊性
尽量减少对现有系统的改动,降低⻛险,保证可⾏性
初期挑选相对独⽴、耦合性较⼩的上层应⽤进⾏改造,积累经验
经验丰富后,再进⾏⼤规模的改造
新⽼架构共存
只能⼀点⼀点改造,并逐步将遗留项⽬迁移⾄微服务架构。
老应用依赖新应用
调用模式
新应用依赖老应用
⽼服务暴露基于 HTTP 的 API,新⽼服务之间通过 Spring Cloud Sidecar 进⾏通信,Sidecar 原理解析。
代码改造方式
绞杀者模式
对于遗留系统 Legacy
不改动⽼系统 Legacy,⽽是另起微服务 Modern,实现对 Legacy 的改造
外层创建⼀个⻔⾯,做接⼝的转发,对于已经改造完的 API,转发到 Modern,对于未改造的 API,
依然转发到 Legacy
使⽤⽹关配置转发规则
随着迁移的不断深⼊,最终绞杀掉 Legacy
修缮者模式
识别出应⽤要拆的部分(Flawed Supplier)
为(Flawed Supplier)抽象接⼝层(Abstraction Layer),从⽽隔离(Flawed Supplier)内部发
⽣的变化
“客户端”通过接⼝层(Abstraction Layer)调⽤(Flawed Supplier)
为要拆的部分(Flawed Supplier)编写新的实现(New Supplier)
“客户端”通过接⼝层调⽤新的实现(New Supplier)
删除 Flawed Supplier
数据库层⾯的改造
废弃掉掉触发器、存储过程
⼲掉跨模块的 join,使⽤API 调⽤的⽅式实现原有功能
将 API 按照模块拆出去
将相关的表拆到对应的微服务种
业务改造期间,通过双写⽅式
切少量流量到新库,进⾏测试与验证
流量全切到新库
逐步退化⽼库,直⾄废弃
迁移失败预案
版权声明: 本文为 InfoQ 作者【洛神灬殇】的原创文章。
原文链接:【http://xie.infoq.cn/article/7cd236e45b6a8d42ba5d2c3fa】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论