Skip to content

Latest commit

 

History

History
336 lines (186 loc) · 26.1 KB

2019-03-31.md

File metadata and controls

336 lines (186 loc) · 26.1 KB

企业 IT 架构转型之道:阿里巴巴中台战略思想与架构实战

这本书介绍了阿里巴巴电商系统架构的演变历史,并且对集团内一系列在工程上的实践进行了系统的总结。读完这本书,感觉不少知识点还是不太清楚,因为还没有过实战经验。但我相信,只要自己在以后的工作中多加实践,勤于思考和总结,一定会有更加深刻的认识。

以下是我对书中部分片段的手抄。

系统如何建设?

最大的浪费不是重复建设,而是不断重复建设。在早期往往一个新业务的上线除了数据可重复使用之外,服务却不能被重复使用。其实服务的重用会比数据重用带来更多好处。数据只是原始生产资源,服务则包含逻辑,是工厂的加工车间,如果加工过程也一样可以复制,将带来生产效率的大幅度提升。

系统的建设要从生产型模型升级到运营型模型从版本模型升级到迭代模型,运营模型最大的优势是所有的积累都被沉淀,而生产模型会因为 10% 的差异而重新建设 100% 的系统。

“烟囱式”系统建设模式

2008 年淘宝的技术团队同时支持着淘宝和天猫两大电商平台,而 1999 年成立的 B2B 电商平台 1688 一直拥有着自己的技术团队。三套电商体系的架构完全独立,各自应用独立开发和运维。可能是开发团队考虑到电商模式的不同,所以需要独立建设,或者新的业务团队认为在之前电商平台基础上改造成新模式,会有太多的技术和业务的历史包袱,从而促成了当时三座“烟囱”分别矗立支撑着当时阿里巴巴集团最为核心的电商业务。

1688-taobao-tmall

这种模式有三大弊端

  1. 重复功能建设和维护带来的重复投资。
  2. 打通“烟囱式”系统间交互的集成和协作成本高昂。
  3. 不利于业务的沉淀和持续发展。

很多企业通过 ESB 系统实现多个独立系统的打通,这时候要求各个系统进行服务的改造和封装,多数情况下,服务封装的工作跟运维人员自身 KPI 考核没多大关系。所以现实中会出现:

  1. 服务提供者团队不管是从 KPI 考核的角度,还是从认知上都会认为服务封装的任务已经完成,当他们收到新的服务需求时,心理是拒绝的,会出于多一事不如少一事的心态。
  2. 服务提供者团队拥有不错的做事态度,也愿意改造服务以满足新业务需求,但受限于之前服务设计的通用性和业务前瞻性的不足,需要对之前业务逻辑做较大的改造。更多团队选择放弃对新业务需求的支持。

服务重用

今天的阿里巴巴已经将集团 20 多个核心业务中公共的、通用的业务以服务的方式沉淀到了共享业务事业部,共享业务事业部在中台战略中扮演着至关重要的作用,整个集团的核心业务能力均建立在这样一套共享服务体系之上,使得我们在今天的业务支持中,真正发挥出了 SOA 架构的核心价值——服务重用

服务需要不断的业务滋养

服务最不需要“业务稳定”。一个服务如果一味追求功能的不变,一定程度上就是固步自封,这样的做法是在逼着其它系统去建同样的“轮子”,当越来越多的系统都采用自建“轮子”的方式满足自身系统对这部分业务的需求时,之前的这个服务就少有人问津,逐渐退出历史舞台。

服务需要不停的滋养,只有在滋养中才能从最初仅供单薄业务功能的服务逐渐成长为企业最为宝贵的 IT 资产,而服务所需的滋养正是新的业务不断进行服务的接入

赋予业务快速创新和试错能力

企业要想在互联网时代相比同行业的竞争对手们真正产生差异化的竞争力,业务试错是一个非常重要的能力,只有先人一步,唯快不破,才能帮助企业抢占商业先级的制高点。互联网时代的竞争只有第一,没有第二。

如果有一个好的业务想法,需要投入 20 个人、 4 个月时间,结果还可能建设的系统达不到预期市场,那么这个业务试错的成本是高昂的,任何一个企业都很难支持这样的试错。如果企业打造了很好的业务中台,可以让 3 个人基于中台提供的核心服务在 2 周内建成系统并推向市场,看看市场的反馈来决定是否加大对这个新业务的投入,那么任何一家企业的领导都会乐意做这样的尝试。

美军在二战时,以军为单位作战;到了越战时,以营为单位作战;到了中东战争时,以 7/11 人的极小班排去作战。它是今天全世界范围内最灵活的军事组织,也是核心竞争力和打击能力最强的组织。美军之所以能够灵活作战,敢放这么小的团队到前面,是因为有非常强的导弹指挥系统,有非常强大的中后台能力,能支持这样的小团队快速做判断,并且引领整个进攻完成。

这与阿里巴巴如今的“大中台、小前端”战略完全一致,与华为公司提的头狼团队也有异曲同工之妙。

小的前端团队具有以下特征:

  1. 团队协同效率最高。
  2. 对战机(商机)的把握更加敏锐。
  3. 调整方向更加快捷。
  4. 一旦发现正确目标,全力投入扩大战果。

一旦前端的作战团队找到了正确的攻击目标,接下来一个远程呼唤,后端的中台炮火群会瞬间摧毁目标,这就是中台阵型发挥威力的最佳体现。如今的互联网公司都在着力打造自己的业务中台,通过中台资源的优势,吸引那些有能力基于这些中台进行更好业务创新的人才加入,形成了公司搭舞台、各路英豪在这个舞台上展现自己才能的格局,这应该是接下来一段时间顶尖公司与顶尖人才间建立合作的最佳方式。

淘宝平台“服务化”

2007 年,淘宝拥有超过 500 人的技术团队,整个淘宝网站是一个几百兆字节的 WAR 包,大小功能模块超过 200 个。当时淘宝业务计划处于每几个月就翻倍的高速发展期,这样的应用架构给淘宝技术团队带来了以下几个主要问题:

  1. 项目团队间协同成本高,业务响应慢

    代码合并时,各种 jar 包冲突、代码不一致,不同团队间需要进行各种确认和协调工作。

  2. 应用复杂度已超出人的认知负载

    越来越复杂的淘宝平台,各种业务错综复杂揉在一起,没有谁能完全清楚每一个功能和业务流程的细节,因为人的认知负载是有限的。这样造成了每一次淘宝平台整体打包发布时,蕴含着非常大的风险,小小的功能改动可能会给其它功能带来未知的风险,整个平台给人一种“牵一发而动全身”的感觉。

  3. 错误难以隔离

    一些非核心功能的设计不合理、代码质量差可能引起整个平台的业务受到全面影响,根本原因就是核心功能和非核心功能的代码都运行在同一个环境中,任何一个小的问题都可能造成应用实例的崩溃,从而影响到整个淘宝平台的正常运行。

  4. 数据库连接能力很难扩展

    所有业务功能在一个 WAR 包内,所有的数据也保存在同一数据库集群中,而数据库集群的数据库连接数量是有上限的,这就造成数据库连接数量的资源随着应用实例数量的增加而越来越捉襟见肘。

  5. 应用扩展成本高

    系统出现业务处理瓶颈时,可能只是某一个或几个功能模块负载较高造成的,但系统所有的功能都打包在一起,无法对单独的几个功能模块进行服务能力的扩展,只能将整个完整的应用进行扩容,带来了资源额外配置的消耗。

解决以上问题的根本就在于业务的拆分

淘宝从现有应用中选择了用户相关的功能点作为试点,剥离出了用户服务中心,主要出发点在于用户的业务逻辑相对独立和简单,而且服务功能的复用率最高。改造后,很多问题得到了解决:

  1. 降低了不同模块开发团队间的协同成本,业务响应更迅捷。
  2. 大大降低系统间的耦合度以及整体复杂度,各个开发团队可专注于各自的业务模块。
  3. 避免个别模块的错误给整体带来的影响。
  4. 业务拆分后解放了对单数据库集群连接数的能力依赖。
  5. 做到针对性的业务能力扩容,减少不必要的资源浪费。

“中心化”与“去中心化”服务框架对比

SOA 的主要特性:

  • 面向服务的分布式计算
  • 服务间松散耦合
  • 支持服务的组装
  • 服务注册和自动发现
  • 以服务契约方式定义服务交互方式

目前,互联网有两套架构,一套是以 ESB(企业服务总线),以中心化方式实现 SOA;一套是“去中心化”架构。

ESB 模式的“中心化”服务架构

系统间交互时,通过在 ESB 上进行一次调整,避免了因为服务提供者接口的变化而导致需要调用此服务的服务调用者都进行修改的现象,实现了对服务接口变化带来影响的隔离。ESB 架构降低了系统间的耦合,更方便、高效地实现了对新系统的集成,同时也在服务负载均衡、服务管控等方面提供了相对“点对点”模式更专业的能力。

在 ESB 这样一个中心服务总线上,提供了诸如对各种技术接口的适配接入、数据格式转换、数据裁剪、服务请求路由等功能。核心目的是让企业客户能基于这些 SOA 的产品实现系统间的互联互通,同时提高开发集成效率,更快地实现 SOA 项目的落地。

“去中心化”分布式服务架构解决的问题

“去中心化”服务架构除了对于 SOA 特性的实现和满足外,相比“中心化”服务架构最重要的不同就是服务提供者和服务调用者之间在进行服务交互时无需通过任何服务路由中介,避免因为“中心点”带来平台能力难扩展问题,以及潜在的“雪崩”影响。

“中心化”服务框架为什么不适合互联网场景

  1. 服务调用方式的不同带来业务的响应和扩展成本

    传统 ESB,每一次服务的调用者要向服务提供者进行服务交互请求时都必须通过中心的 ESB 来进行路由。

    consumer-ESB-provider

    经过服务总线路由过的服务交互,共出现 4 次网络会话创建和数据传输,而“去中心化”服务架构中服务的交互,一次服务的调用只有两次网络会话创建和数据传输,开销少了一半。

    consumer-provider

    从逻辑上看,所有服务调用都通过服务总线,服务总线的访问和计算压力都非常大,虽然也可通过集群部署的方式进行压力的分担,但一般企业服务总线包含的功能非常多,使得企业服务总线一般对服务器的要求都比较高,每次扩容升级,都需要不少投入。

  2. “雪崩”效应束缚了“中心化”服务框架的扩展能力

    基于企业服务总线构建的服务体系,会成为企业服务调度的核心枢纽。如果在 ESB 集群有 10 台实例,服务访问的峰值,每个企业服务总线负载达 80%,而此时某个应用对某服务产生了不规范的服务调用,或者出现其它异常故障,导致 10 台企业服务总线的实例有 1 台出现了问题,此时压力落在剩下的 9 台 ESB 服务器上,每台服务器负载水位超过 88%,集群可能在瞬间被访问洪流冲垮,这就是典型的雪崩效应。

    一旦遇上雪崩,故障恢复的时间和成本非常高昂。一台一台重启服务器已经不能进行故障的恢复,因为一旦服务启动起来,前端的访问洪流会立即再次压垮启动后的服务器。唯一正确的方式则是首先切断前端应用对企业服务总线的服务请求,让这 10 台服务器全部启动后,再开放服务请求,这样才能恢复系统的运行。但这样没定位问题所在,而着急恢复系统,这样的系统运行其实处于一个“脆弱”的状态,之前造成服务实例宕机的问题可能让“雪崩”事故再次上演。

阿里巴巴分布式服务框架 HSF

HSF 组件

HSF 服务框架包含以下主要组件:

  1. 服务提供者

    真正提供服务功能实现的应用实例,一般以集群部署以保障服务提供的高可用。以 WAR 包形式存在,运行在阿里巴巴优化定制后的 Tomcat 容器。

  2. 服务调用者

    作为服务的消费者,大多数也是以 WAR 包运行,集团内也有一部分基于 C/C++、PHP、Node.js 等语言开发的服务调用者。

  3. 地址服务器

    为服务提供者和调用者提供部署环境中所有的配置服务器Diamond 服务器的服务器列表信息,由 Nginx 提供该服务能力。服务提供者和调用者通过统一域名,比如 xx.tbsite.net 的方式访问地址服务器,通过 DNS 轮询,实现地址服务器访问的高可用性。

  4. 配置服务器

    主要记录环境内所有服务发布(服务提供者 IP+Port)和服务订阅(服务调用者 IP+Port)信息,并将服务相关信息推送到服务节点上。信息保存在内存中。

    配置服务器与所有的服务提供者和调用者均是长连接,采用心跳 ♥ 的方式监控各服务节点运行状况,一旦服务提供者节点出现故障,自动推送更新后的服务提供者列表(删除了出问题的服务提供者节点信息)给相关的服务调用者端。

    生产环境中,会配置多台配置服务器用于服务发布、订阅、推送的负载均衡,在多台配置服务器间会进行实时的数据同步,保证服务节点和订阅信息尽快同步到各服务节点上。配置服务器就是指挥官的角色。

  5. Diamond 服务器

    通用的统一配置管理服务器,类似 Zookeeper,给应用提供统一的配置设置和推送服务。主要承担了服务路由权重、服务 QPS 阈值等配置规则的保存,所有的信息均是持久化保存到了后端 MySQL 服务器中,并自动将规则推送到相关的服务节点(实际实现上是服务节点会定时从 Diamond 服务器上同步相关配置信息)生产环境中,会有多台 Diamond 服务器提供负载均衡的服务。

HSF 工作原理

HSF-process

  1. 服务节点从地址服务器获取配置服务器列表

    服务启动时,服务节点(服务提供者+调用者)以域名的方式从地址服务器获取到配置服务器和 Diamond 服务器的 IP 列表信息。如步骤 ①② 所示。

  2. 服务的注册发布

    服务提供者通过上个步骤获取到配置服务器列表后,向配置服务器发送当前应用包含的服务提供者信息,即:注册到配置服务器。如步骤 ③ 所示。

  3. 服务的订阅

    服务调用者同样获取到配置服务器列表,向配置服务器发送服务消费者相关信息到配置服务器进行服务的订阅。此使配置服务器在内存中搜索,一旦获取到对应的服务注册信息,就将提供者的 IP+Port 返回给服务调用者所在节点,用于在服务真正交互时使用。如步骤 ④⑤ 所示。

  4. 服务规则的推送(If need)

    如果没有服务安全管控、流量控制的需求,对于 Diamond 服务器的使用并不是必需的。如果有需求,可通过 Diamond 服务器提供的规则配置界面,对指定服务的服务提供者和调用者设置相关的规则,一旦保存,则 5s 内推送至所设置服务相关的服务节点上。如步骤 ⑥ 所示。

  5. 服务交互

    进行业务请求处理时,服务调用者从已经保存在该应用节点上的服务提供者服务器列表中选择(阿里使用随机模式)其中一台进行服务请求的发送,直接调用服务提供者。如步骤 ⑦ 所示。

阿里巴巴的分布式服务框架核心是以服务化方式构建整个应用体系的同时,保证高并发的情况下,服务具备高效交互、高可用性和扩展能力。

HSF 如何提供以上能力

  1. HSF 框架采用 Netty+Hession 数据序列化协议实现服务交互

    采用网络通信框架 Netty 加上 Hession 数据序列化协议,主要考虑点是在大并发量时,服务交互性能达到最佳。RPC 协议采用多路复用的 TCP 长连接方式,多个请求同时调用时会共用同一个长连接,避免了反复建立连接的开销。

    Hession 在数据量较小时性能表现出众,优点是精简、高效、可跨语言使用,与最稳定的 Java 序列化相比并不会逊色多少。Hession 是在性能和稳定性同时考虑下最优的序列化协议。

  2. HSF 框架的容错机制

    服务提供者多实例部署,某一台服务器发生故障时,服务调用者端会获取到服务调用失败的反馈,会立即从剩下的服务提供者列表中选择另外一个服务器再次进行服务请求。

    HSF-HA

  3. HSF 框架的线性扩展支持

    若服务面对较大服务调用压力,只需要通过增加该服务的服务提供者实例,基于 HSF 框架的运行机制,新增加的服务器提供者实例一旦应用启动完成,几秒内可以开始进行服务请求的处理,从而为其它服务器实例分担压力。

关于微服务

Martin Fowler 对于微服务架构的描述:

  • 分布式服务组成的系统
  • 按照业务而不是技术来划分组织
  • 做有生命的产品而不是项目
  • 智能化服务断电与傻瓜式服务编排
  • 自动化运维
  • 系统容错
  • 服务快速演化

服务中心的划分原则

  1. 高内聚、低耦合原则

    高内聚是说一个服务中心内的业务应该是相关性很高、依赖性很高的;而低耦合是说服务中心之间的业务隔离性应该比较大,追求尽可能的低耦合。

  2. 数据完整性原则

    数据模型要统一。强调大数据的思维,不光只是业务逻辑的关键数据,还要考虑业务的相关性数据;不光是实时在线数据,还要考虑到离线计算的数据。

  3. 业务可运营性原则

    服务中心是应该是承载业务逻辑、沉淀业务数据、产生业务价值的业务单元。

  4. 渐进性的建设原则

    推荐服务化从简单开始,只有真实的业务需求才会锤炼出稳定可靠的共享服务

阿里巴巴分布式数据层平台发展和演变

Cobar

2006 年阿里巴巴 B2B 团队开源了 Cobar 这一关系型数据的分布式处理系统,很大程度上解决了最初使用 Oracle 数据库因为存储数据变得越来越大的扩展性问题,并且为开发人员提供了一个使用相对简单的用户体验。但是 Cobar 在某些业务场景下显得力不从心:

  • 不支持跨库情况下的连接、分页、排序、子查询操作
  • SET 语句执行会被忽略
  • 不支持 SAVEPOINT 操作
  • ...

TDDL

2008 年阿里巴巴内部基于淘宝业务发展的需要,在 Cobar 基础上重新研发了分布式数据层框架 TDDL,Taobao Distributed Data Layer,针对分库分表场景,提供了对各种业务场景的支持,开发人员体验更加友好。总的来说,TDDL 提供了以下优点:

  • 数据库主备和动态切换
  • 带权重的读写分离
  • 单线程读重试
  • 集中式数据源信息管理和动态变更
  • 支持 MySQL 和 Oracle 数据库
  • 基于 JDBC 规范,很容易扩展支持实现 JDBC 规范的数据源
  • 无 Server,以 client-jar 形式存在,应用直连数据库
  • ...

DRDS

随着阿里巴巴集团业务的多元化,TDDL 这种无 Server 模式对于故障的定位运行环境的要求(必须是阿里巴巴内部服务环境),支持新业务有了不少困难,因此 2014 年阿里巴巴研发出新一代分布式数据库产品 DRDS Distributed Relational Database Service,该产品相比 TDDL 在业务场景的支持、故障的定位、运维管控等方面有了一个全面提升。

数据库分库分表

原则 1:数据尽可能平均拆分

分库分表场景下,最重要的一个原则就是被拆分的数据尽可能的平均拆分到后端数据库中,如果拆分得不均匀,还会产生数据访问热点。

电商平台,一个维度是通过订单 ID 为分库分表键,一个是通过买家用户 ID 的维度进行哈希取模。

  • 通过订单 ID 取模的方式,原则上很好满足了数据尽可能平均拆分的原则。
  • 通过买家 ID 哈希取模的方式,可能因为某些买家订单数量较多而出现数据不平均的现象。

从数据尽可能平均拆分的角度来看,按照订单 ID 取模的方式看起来更能保证订单数据进行平均拆分。

原则 2:尽量减少事务边界

事务边界是指单个 SQL 语句在后端数据库上同时执行的数量。

如果有这么个场景,显示买家 test1 过去三个月的订单列表信息,此时由于是按照订单 ID 取模的方式,将订单数据分布到不同的数据库上,分布式数据层会将 SQL 推送到后端所有数据库中执行,然后返回结果在分布式数据层进行聚合后再返回给前端应用。这样会出现全表扫描,导致整体性能降低、系统越难以扩展。

原则 3:异构索引表尽量降低全表扫描频率

采用异步机制将原表内的每一次创建或更新,都换另一个维度保存一份完整的数据表或索引表,就是“拿空间换时间”。

order-index-table

在应用创建一条按照订单 ID 为分库分表键的订单数据时,也会再保存一份按照买家 ID 为分库分表键的订单索引数据。结果就是同一买家的所有订单索引表都保存在同一数据库中。查询时,根据订单索引表中的订单 ID,直接到订单表去获取。

query-order-index-table

原则 4:将多条件频繁查询引入搜索引擎平台

采用数据异构索引的方式在实战中基本能解决和避免 90% 以上的跨 join 或全表扫描的情况,是在分布式数据场景下,提升数据服务性能和处理吞吐能力的最有效的技术手段

但商品搜索调用非常频繁,如果采用 SQL 语句在商品数据库进行全表扫描的操作,则必然对数据库整体性能和数据库连接资源带来巨大压力。建议采用专业的搜索引擎平台来执行搜索。

原则 5:简单就是美

如果在“尽量减少事务边界”与“数据尽可能平均拆分”两个原则间发生了冲突,优先考虑“数据尽可能拆分”,因为事务边界的问题相对来说更好解决,无论是做全表扫描或做异构索引复制都可以解决。而写入或单机容量如果出现不均衡,处理难度会比较大。

如果每一个存在跨 join 或全表扫描的场景都采用数据异构的方式,整个数据库会出现大量数据冗余,数据一致性的保障也会带来挑战。

以 82 法则,在实际中,我们仅针对那些在 80% 情况下访问的那 20% 的场景进行如数据异构索引这样的处理,达到这类场景的性能最优化,而对其它 80% 偶尔出现跨库 join、全表扫描的场景,采用最为简单直接的方式往往是最有效的方式。

CAP 理论

一个分布式系统最多只能同时满足一致性 Consistency、可用性 Availability 和分区容错性 Partition tolerance 这三项中的两项。

  • “一致性”指更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致。
  • “可用性”指用户在访问数据时可以得到及时的响应。超过一定响应时间的服务是没有价值的或者价值量低的。
  • “分区容错性”指分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。

除了整个网络的故障外,其它的故障(集)都不能导致整个系统无法正确响应。

如何解决数据一致性问题

一个简易的方案是建立类似操作系统中的锁机制,要求确保所有数据节点的数据均同步之后,才能进行数据的访问操作。但这样会有可用性问题,不同数据节点间的数据同步需要时间,采用大量的锁机制会给数据层带来严重的性能瓶颈,从而可能导致平台在业务繁忙时的服务瘫痪或糟糕的用户体验。

另一个做法就是商品的库存数据只保存一份,不做复制,这样就不会存在数据一致性的问题。而因为网站的数据量太大,一个节点容纳不小,需要分割存储在不同节点,这就是典型的数据分库分表,这样就能解决可用性问题。但这样也会有个明显的问题,假如某一时刻数据节点间的网络阻塞或者切断了,会导致网站可能获取不到完整的数据。这就是分区容忍性问题

CAP 并不意味着所有的系统设计都必须抛弃三个要素中的一个。CAP 三者可以在一定程度上衡量,并不是非黑即白,例如可用性从 0% 到 100% 有不同等级。

BASE 理论

BASE 理论是对 CAP 理论的延申,核心思想是即使无法做到强一致性,但应用可以采用适合的方式达到最终一致性。

BASE 是指基本可用 Basically Available、柔性状态 Soft State、最终一致性 Eventual Consistency

  • “基本可用”是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。比如电商大促时,部分用户可能会被引导到降级页面。这就是损失部分可用性的体现。
  • “柔性状态”是指允许系统存在中间状态,而该中间状态不会影响到系统整体可用性。允许不同节点间副本同步的延迟就是柔性状态的体现。
  • “最终一致性”是指系统中所有的数据副本经过一定时间后,最终能够达到一致的状态。