当前位置:文档之家› 微服务架构介绍

微服务架构介绍

微服务架构介绍微服务是个说的挺长时间的概念,也是比较成熟的技术体系。

像Spring Cloud,甚至提供了微服务所需要的全套框架,包括注册中心(Eureka)、配置中心(Config)、断路器(Hytrix)、API 网关(Zuul) 等组件。

微服务体系庞杂,每个组件都能独自成章。

微服务与更早就起来的SOA 是什么关系? 个人觉得如果从概念上来说,微服务和SOA 都是一回事,强调把整个系统,按照多个服务的方式去组合及通信,而不是揉合在一起,但它们的内涵有很大的区别。

SOA 诞生在早期企业级的应用,其业务复杂、技术体系多样,SOA 强调的是各个服务之间,尤其是异构系统、遗留系统之间,建立起一套统一的协议和通信(SOAP),以及寻址服务(UDDI),它的侧重点在集成和兼容;与SOA 同期的另一种概念ESB(企业总线),强调通过一根总线服务,把所有服务串联起来,由ESB 总线来屏蔽各种不同业务系统自身业务/ 语言/ 协议的特殊性,各服务以一种统一的方式,与总线相连,从而降低接入成本。

这两种概念,我感觉在国内没有太发展起来。

一是国内的软件起步相对较晚,系统的整体复杂度——多厂商、多语言/ 技术栈、历史遗留系统的问题,还不算突出。

而对于公司内部的产品系,又没有必要使用SOA、UDDI 来做复杂的集成。

随着互联网的兴起和用户量的迅速爆发,企业自身的产品的微服务化的需求,快速发展起来,而与此同时SOA 这种以XML 为基础的SOAP 协议、以寻址为主要作用的UDDI,不能使用互联网产品的发展——SOAP 的XML 协议内容太多,造成性能明显下降;HTTP 协议的效率不如RPC;UDDI 只有寻址,缺少服务治理等功能。

在此种大背景下,以服务切分+ 服务注册+ 服务治理+ 限流降级+RPC+ 监控等为主要内涵的微服务,就快速发展起来的。

国内的阿里巴巴走在前列,以Dubbo 为代表在国内互联网企业中得到广泛应用;后来Spring 官方发布Spring Cloud,揉合了一系列自研或其他企业捐赠的开源项目,发布微服务领域的Spring Cloud 产品。

各自都有各自的优势和劣势,而随着这些年来,微服务的继续下沉(sidecar 和service mesh) 到基础设施层,给微服务的治理带来了新的方向。

微服务的关键特性服务粒度服务的粒度,切分到多大算合适? 太粗的话,这服务就涵盖过多的业务逻辑,从而难维护、易出错;太细了,就会搞出很多的工程,造成很大的工程维护和通信成本。

主流说法是依据康威定律——团队的交流机制应该和组织机构相匹配。

应用到软件领域来看,如果某个应用,需要多个组织之间一起交流和修改,那么它的交流机制就大于组织机构了,出现了不匹配的情况,那么这个应用很可能就太粗而需要拆分。

这里有个不太好懂的地方——既然系统架构和团队组织机构想匹配,那我们是先定系统架构呢,还是先定团队组织机构呢? 这有点类似先有鸡还是先有蛋。

我觉得可以这么来理解:无论是团队怎么定、还是架构怎么定,这都是跟着业务的发展而发展的,可以说都是业务的衍生发展而来。

所以系统架构设计,首要做的还是业务理解和切分——业务切分决定了服务切分、业务切分也决定了团队组织。

业务切分有两种简单办法:1.参照业内同类公司的划分:比如电商,业内比较成熟的:支付、库存、订单、搜索、用户等;2.将自身业务的主要信息流画出来,先找出其中的名词或动名词,它就可能是个服务eg:在我们的线上贷款业务中,典型的user case 是这样:1.用户导入几项金融资料数据2.系统根据信息清洗出部分衍生变量3.系统跑欺诈规则4.系统计算授信,给出额度5.用户试算得到月费率和利息6.系统人工信审7.系统放款8.到还款日时用户还款或者我们系统主动扣款将其中的名词整理出来,整理流程大概就是如下图:这些都是候选服务。

根据其复杂度和相关性,做适当的拆解和合并,形成了如下几个子系统及服务。

治理范围从服务的角度来看,对外公开的是契约——即我们系统提供哪些特性,而内部算法/ 数据都应该隐藏起来,而在不同服务间“是共享数据库还是独享数据库”上,实践中的冲突和困惑,体现地比较明显。

我们假想个流程,ServiceA 的李雷需要更新User 表的某个字段,如果大家数据库表都共享的,李雷只要写个SQL 就解决了。

但一旦把User 表服务化后,归到UserCenter 这个服务自治之后,问题就麻烦了:1.李雷要去找UserCenter 团队——假设是韩梅梅接了这个需求,好在是个女生,男女搭配干活不累——讲清楚他的需求或提供需求文档;2.韩梅梅理解了需求,设计接口、提供文档、评审并准备开发;3.韩梅梅可能手里有其他事,所以这个需求大概要等几天才能开发;4.终于韩梅梅开发完了,她要自测、部署;上游李雷开始联调,如果有问题,需要双方再沟通解决;5.联调完毕上线,韩梅梅的UserCenter 先上,李雷的业务系统再接着上;从这可以看到,一旦一个人、一个系统做的事,变成了 2 个人、两个系统来做,那要多出多少麻烦了。

所以我完全理解,在公司早期,所以业务系统共享一套数据库表,是多么地务实。

我们功夫贷在创业之初也是这么做的,在创业2 年后,它的弊端开始密集体现,而服务化改造过程中,我们也是付出了相当大的代价。

随着用户量和数据量的上升,这种共享数据库表的最明显的弊端就是慢查询越来越多——因为谁都可以操作任何一张表、而开发过程中或者是对业务理解不够、或者是SQL 能力不足,很容易写出慢SQL 来,其结果就是导致DB 的CPU 飙升到100%、或者是IOPS 被打满,从而全APP 被拖慢甚至无法提供服务。

这种危害是相当巨大的。

所以,从运行时的慢SQL 带来的巨大杀伤力来说,数据库应该是隐藏在服务内部,该服务由熟悉该业务的固定团队维护、也会做很多优化。

虽然开发阶段慢了,但是运行时稳定了、系统的可用性得到了保障。

只是这件事,不应该在创业初期就做,那样会比较严重地放缓系统迭代速度、更应该在系统规模相对较大的时候来改造。

当然,我们说改造是要付出代价的。

不仅之前的一个库中的表,要分成不同的库,各服务的程序要做不小的改造,其中最困难的是,同一张表的字段,可能会属于各个不同的应用。

看下面这个User 表。

开始的时候,User 表只包含了完全业务无关的属性,但随着系统的发展,一些和业务相关的字段(上图红色部分) 逐渐地被加进来——这也不完全是决策时犯的错误,而是本身这属性是否和业务有关,也不是很容易界定。

所以逐渐会发现,很多系统都会依赖这张表,从而交织难以拆分。

各个服务可能都需要有这张表,而各自维护自己所关心的那部分字段及功能。

在我们的实践中,服务化的过程以及数据迁移,大约是这样的步骤(以“用户中心”应用为例):1.创建新应用UserCenter,梳理清楚其的业务边界和所涉及的数据表;2.收集和分析其他系统对这些数据表的需求,并在UserCenter 中开发接口,以备上游系统调用;3.逐渐改造上游系统,使其由原先的读取数据库,修改为调用UserCenter 接口。

由于有多个上游系统和功能需要改在,因此这个阶段会比较长,上游系统在这个时间周期内,也会“访问接口服务”和“直接访问数据库”这两种形态并存;4.检查并确认上游系统都改造完毕上线,此时理论上应该没有上游系统直接读取UserCenter 的表了,都通过接口了,此时准备迁移UserCenter 的表数据;5.建立New UserCenter DB,并通过DB 同步机制,实时地将UserCenter 的表数据由老库同步到新库。

在新库同步完成之前,UserCenter 的应用仍然使用的是老库里的表;6.新库同步完毕,UserCenter 应用切换到新库,此时所有的新数据都会进新库,而老库理论上是不用了;7.断开新老库的同步链,同时rename 老库的表(先不删,同时在rename 前一定要断开同步链,否则新库也会被同步rename 掉了)。

如果此时万一有某个系统的功能,在之前的系统改造/ 测试中遗漏了没被发现,仍然是直接读取的数据库表,那么这时候就会报错(因为表名被rename 掉了,找不到了)。

此时就是个恢复窗口,赶紧把表rename 回来,减少损失,然后再继续处理。

这也是前面千万不能直接把老表删除的原因;8.运行几天没问题之后,再把老库的表删除,整个服务化过程结束;服务组合在微服务之后,各个系统只对某一块业务负责,那么就有可能需要对服务做一些聚合。

下面是常见的两种模式:这是聚合服务的模式,由web 应用去负责聚合后端服务或做个性化处理,这是它的好处——可以根据自身的业务做任何组合和处理,而它的坏处也很明显——对于不需要特殊处理的,也得过它一道。

这是后台服务自包含的模式。

某个后台应用,依赖于其他服务,于是就将其他服务的相关调用都处理完了,或者这么理解——后台服务也有多个层次:库存服务、支付服务、发票服务是最底层的,交易服务是更上层一些的共享服务,从而达到封装细粒度服务的目的,与此同时,它的个性化也就丧失了。

假如有个交易,是不需要发票服务的,那么这种模式就不是太灵活。

从我个人的经验来看,我是倾向于聚合服务这种模式。

每个前端应用,还都是应该有个自己的后台服务,去完成很多小的功能(比如更新APP 版本、展示首页广告、记录埋点等APP 特有feature)、以及聚合。

而对于不需要App-Server 处理、直接使用后台服务的,应该能够通过gateway 直接调用,而不需要App-Server 来做代理转发。

容错容错的目的就是在出现问题的时候,仍然能够正常提供服务,其具体表现形式有这么几种:∙当调用下游服务 B 出错的时候,可以在安全的情况下考虑重试;∙当调用下游服务 B 出错的时候,可以调用替代服务B';∙当调用下游服务 B 出错的时候,是否可以返回某个默认值、或者返回最近一次的值?∙当调用下游服务 B 超时的时候,如果超时请求达到一定数量,则需要熔断,以保证自身其他服务能正常提供服务,而不会被拖垮;∙当调用下游服务 B 出错的时候,能否以异步+ 定时任务补偿的方式代替?上面这些特性,有些是通过RPC 框架来实现(重试)、有些是应用控制(调用替代服务、异步+ 定时补偿)、有些可以通过Hytrix 这样的断路保护框架来实现。

容错也比较简单,但为了容错确实也需要增加不少开发工作量,它就像买保险,有的人看重风险、愿意付出一些代价来买一份适合的保险;有的人比较乐观,不相信灾难会降临到自己身上,所以这就看一个公司对自己的要求了。

从我个人的观点来看,公司到达千万用户级以上,就需要比较严肃地考虑这个了,因为一次全局事故,带来的损失就会是不小。

限流限流主要有两种算法:令牌桶算法和漏桶算法。

相关主题