04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]

04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]本章,我就针对最近十几年电商平台的架构变化过程,来具体说明下,为了支持业务的快速发展,架构是如何一步步演进的。从2003年淘宝上线开始,国内电商平台经历了高速的发展,在这个过程中,系统遇到了很多的挑战,比如说:如何针对当前的业务现状,选择合适的架构呢?如何在业务发展过程中,升级改造架构,并保证系统的平滑过渡呢?接下来,我会结合自己的工作实践,和你一起探讨架构的演变历程,你可以从中了解到各种架构的优劣点和适用性,然后在实际工作中选择合适的架构。这里,我总结了国内电商平台架构发展的大致过程,你可以结合图片

大家好,又见面了,我是你们的朋友全栈君。

本章,我就针对最近十几年电商平台的架构变化过程,来具体说明下,为了支持业务的快速发展,架构是如何一步步演进的。

从2003年淘宝上线开始,国内电商平台经历了高速的发展,在这个过程中,系统遇到了很多的挑战,比如说:

  • 如何针对当前的业务现状,选择合适的架构呢?
  • 如何在业务发展过程中,升级改造架构,并保证系统的平滑过渡呢?

接下来,我会结合自己的工作实践,和你一起探讨架构的演变历程,你可以从中了解到各种架构的优劣点和适用性,然后在实际工作中选择合适的架构。

这里,我总结了国内电商平台架构发展的大致过程,你可以结合图片参考下。

04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]

我们可以看到,从最初的单体架构到最新的中台架构,架构的可扩展性越来越强,这些都是系统不断适应业务复杂化的结果。下面,我就结合电商业务的变化,按照顺序和你介绍下各个架构。

单体架构

在单体架构中,只有一个应用,所有代码跑在一个进程,所有的表放在一个DB里。第一代电商平台都是单体架构,比如说淘宝,在最初的3年,它的系统就是一个巨大的单体应用。

单体应用内部一般采用分层结构,从上到下,一般分为表示层、业务层、数据访问层、DB层。表示层负责用户体验,业务层负责业务逻辑,数据访问层负责DB的数据存取。

04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]

我们可以看到,各个层的职责,正好对应业务处理的不同阶段,所以,单体架构在水平方向上,通过层次化的划分,降低了业务的深度复杂性(所谓的业务深度,指的是业务流程从开始到结束的长度)。

不过在垂直方向上,单体应用缺乏清晰的边界,上下层模块之间是多对多的网状依赖关系,比如业务层的某个模块(上图中BO1),可能调用数据访问层的所有模块(DAO1~3), 同样的道理,数据访问层的某个模块,也可能被业务层的所有业务模块给调用。

所以,单体架构中的模块只是在逻辑上独立,并没有在物理上严格分开,导致系统在落地时,模块的职责和边界划分比较随意,相应地,模块之间的依赖关系也比较模糊。所以,在单体架构中,模块结构是否合理,很大程度上依赖于开发者的个人水平。

在电商发展的初期,业务并不复杂,比如前台的首页、搜索页、详情页、结算页等,页面的功能都比较简单,可以放在一个应用里处理,这样,使用单体架构就可以快速落地系统。但当业务开始变得复杂时,每个页面都发展为一个独立的业务体系,比如说首页,它原先展示相对固定的内容,现在发展为一个动态的千人千面系统。

这样一来,业务的复杂度急剧上升,模块的数量也大幅度增加了,我们就很难在单体架构里,通过构建一个清晰的模块体系来支持系统的扩展。而且,所有代码放在一个代码库里管理,如果多团队并行开发的话,很容易发生代码冲突,这样也难以满足系统的快速扩展。

举个例子,07年的时候,eBay网站总体上也是一个单体应用,它的核心工程有数百万行代码,由于代码合并和编译非常复杂,他们甚至有专门的团队负责代码合并,有专门的团队负责编译脚本开发,另外还有一套复杂的火车模型,来协调不同团队之间的并行开发和上线。

所以,当业务系统的体量变大时,单体架构的弊端就充分暴露出来了,我们就需要对系统进行有效的拆分,比如把首页、搜索页、详情页、结算页拆成一个个独立的应用,分别进行管理。于是,分布式架构就应运而生了。

分布式架构

分布式架构,简单来说就是系统由多个独立的应用组成,它们互相协作,成为一个整体。

分布式架构包括了多个应用,每个应用分别负责不同的业务线,当一个应用需要另一个应用的功能时,会通过API接口进行调用。在分布式架构中,API接口属于应用的一部分,它和表示层共享底层的业务逻辑,你可以认为,API相当于应用在实现本身业务的基础上,开了个小窗口,给外部使用。

关于分布式的具体架构,你可以参考下图:

04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]

你可以看到,分布式架构在单体应用的基础上,进一步对系统按照业务线,进行了业务广度上的切分(所谓业务广度,指的是不同业务线的数量),这样就把一个大系统的业务复杂度,分割成多个小业务的复杂度,从而降低了整体的复杂度。通过拆分后,各个应用之间的耦合度低,就可以很好地支持多团队的并行开发。

但分布式架构也有局限性,作为应用的开发者,除了要满足自身业务的需求之外,同时还需要考虑外部业务的需求,这两部分经常会打架。比如,由于自身业务的需求,引起底层的业务逻辑修改,这时会同时影响API接口功能,导致其他业务受影响;同样的道理,外部业务需求过来,需要API接口做调整,即使不影响底层业务逻辑,也会导致整个应用重新部署,影响自身业务的稳定性。

另外,在分布式架构下,每个应用都是从头到尾,自搭一套完整的体系,导致业务之间重复造轮子,造成资源浪费。举个例子,在2008年,淘宝还没有开始服务化改造之前,不同业务线的用户、商品、订单逻辑非常类似,导致了整个系统有超过1/3的核心代码重复。

所以,你可以发现,分布式架构适用于业务相关性低、耦合少的业务系统。举个例子,企业内部的管理系统,分别服务于不同的职能部门,比如财务系统和HR系统,就比较适合按照分布式架构去落地。

但在电商场景下,业务都是围绕交易展开的,各个页面(应用)都需要和商品、用户、订单、库存打交道,对于这样业务相互依赖、应用之间需要紧密协作的场景,在系统架构方面,是否有更好的手段,可以更高效地集成这些应用呢?

答案是有的,SOA架构就可以有效地解决这个问题。 接下来,我们就具体了解下。

SOA架构

SOA架构(Service Oriented Architecture)是一种面向服务的架构,它的发展经历了两个阶段:传统的SOA架构,它解决的是企业内部大量异构系统集成的问题;新的SOA架构,它解决的是系统重复建设的问题。下面我就来和你详细介绍一下。

从2000年开始,很多传统企业进入了信息化建设高潮,先后采购了很多系统,比如ERP、OA、CRM等等。这些系统都是由不同的供应商提供的,落地后,就形成了很多的信息孤岛。随着业务的发展,企业需要打通这些不同的系统,那么问题来了,这些系统使用不同的技术,事先也没有提供开放接口给外部使用,那我们如何才能有效地集成这些系统呢?

解决的办法是,每个系统首先把外部需要的能力,封装为一个个粗粒度的接口,打包成一个独立的服务;然后,外部系统通过这个服务访问系统内部,解决不同系统相互集成的问题。经过这样的改造,系统最后就变成了一个面向服务的SOA架构。

这就是一个传统的SOA架构,如下图所示:

04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]

你可以看到,在SOA架构中,每个服务都对应一个现有的系统,所有这些服务都部署在一个中心化的平台上,我们称之为企业服务总线ESB(Enterprise Service Bus),ESB负责管理所有调用过程的技术复杂性,包括服务的注册和路由、各种通信协议的支持等等。

比如说,09年的时候,eBay就基于Axis 2,开发了自己的SOA框架,让各个系统通过提供标准的服务,来满足外部调用需求。 比如后台搜索系统,本身是C++开发的,但是它通过提供Java服务,封装常见的搜索功能,就方便了其他系统(大多是Java)和搜索系统进行集成。

以上讲的是传统SOA架构,它主要用于解决遗留系统的集成问题。而新的SOA架构,它利用服务共享的思想,解决系统的重复开发问题。

举个淘宝的例子,淘宝的系统基本是自建的,系统相互打通的问题不大。但经过一段时间的自然生长,系统重复建设的问题很突出,前面也提到,有超过1/3的核心代码重复。针对这种情况,我们就可以通过服务化手段,把通用的逻辑和数据从各个业务系统里抽取出来,封装成独立的服务,提供给所有业务进行共享。

基于这个思路,淘宝花了2~3年时间,先后落地了用户、商品、订单、库存、店铺、营销等服务,搭建了共享服务体系。通过共享,淘宝不仅提升了开发效率和质量,也加强了系统的扩展能力。

新的SOA架构如下图所示:

04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]

所以我们可以看到,相对于分布式架构,SOA架构给系统的扩展带来了一系列的好处:

  • 首先,它通过服务化思想,提供更好的业务封装性,并通过标准技术,能更友好地对外输出业务能力;
  • 其次,SOA服务不依附于某个具体应用,它可以独立地部署和扩展,这样避免了直接影响现有的系统;
  • 最后,服务通过封装通用的业务逻辑,可以供所有应用共享,解决了重复造轮子的问题。

不过,虽然SOA服务化的思想很好,但在系统实现上比较重,落地比较困难。那有没有更轻量级的架构,使得系统各个部分更容易构建和相互协作呢?

这时候,微服务架构便悄悄地登场了。

微服务架构

关于微服务,大家都不陌生,但究竟什么是微服务,每个人的理解可能都不一样。接下来,我就基于自己的服务化实践,和你分享我的看法。

微服务概念的提出,一开始是用来和单体架构做区分的。我们知道,单体架构和分布式架构,实际上都是围绕一个大的业务线来构建应用,当业务变得复杂时,就无法做到模块边界和依赖关系的清晰划分,模块局部的调整往往会导致系统整体的调整,使得系统很难扩展。

而微服务围绕更小的业务单元构建独立的应用。

比如说,一个飞机航班预订系统,我们可以把它划分为预订航班、时间表查询、计算票价、分配座位等几个小应用(微服务)来落地。那么经过划分后,每个小应用都比较简单,只关注于一个业务功能即可。

这里要注意的是,每个微服务,都是负责端到端的业务,包括前端的UI展现部分和后端业务逻辑。微服务的团队成员可能包括产品、开发、测试、运维等人员,由这个小团队负责应用的整个生命周期管理。

因此,从一定程度上说,微服务叫做微应用,或者说微产品,更合适一点,你也可以认为微服务架构是拆分得更细的分布式架构。

另外,微服务强调围绕业务,进行清晰的业务和数据边界划分,并通过良好定义的接口输出业务能力,这和SOA架构里的服务有点类似。但两者不同的地方在于,微服务是去中心化的,不需要SOA架构中ESB的集中管理方式。

一方面,微服务强调所谓的哑管道,即客户端可以通过HTTP等简单的技术手段,访问微服务,避免重的通信协议和数据编码支持。另一方面,微服务强调智能终端,所有的业务逻辑包含在微服务内部,不需要额外的中间层提供业务规则处理。

这样子,微服务提供方可以自由地选择语言和工具,来落地微服务,服务的部署和维护上也更灵活,从这个意义上来说,你也可以认为微服务是轻量级的SOA服务。

所以说,微服务兼有应用和服务的特征,你可以把微服务理解为:

微服务=小应用+小服务。

以上就是微服务架构设计的初衷,但在实践中,我们更多地把微服务当做一个小服务,而不是一个端到端的小应用,那么为什么会这样呢?这里有几个原因。

首先,我们很难把一个大系统,按照端到端业务的方式,拆分为一个个应用;而拆分为服务是比较灵活的,我们可以把系统核心的业务逻辑和数据封装成服务,其它部分还是以应用的方式落地。另一方面,微服务要求团队人员跨多个职能,构建独立的小团队,来负责服务完整的生命周期,这就需要把现有的职能团队打散后重组,这种人员组织的调整实际上也很难落地。

我们可以看到,微服务强调围绕端到端的小业务功能,通过组建跨职能的团队,来进行落地,这只是一种理想化的做法。所以,在实践中,我们往往弱化微服务的小应用定位,然后扩大化微服务小服务的定位,我们不再强调端到端的业务封装,而是可以有各种类型的微服务。

比如说,封装底层基础业务的是共享微服务,封装流程的是聚合微服务,封装具体业务场景的服务端是应用微服务,封装基础中间件(如Redis缓存、消息推送)的是系统微服务。当然,这些服务在具体落地时,我们还是采取去中心化的机制,使用轻量级的通讯框架,最后把它们打造成一个个技术上轻量级的、功能职责上细分的微服务。

所以,基于这样的思路,微服务就很容易构建,同时,也像水电煤一样,容易被我们使用。然后,我们在这个基础上组装微服务,像搭积木一样搭建系统,这样的系统更具弹性,更容易扩展。

值得注意的是,我们需要对服务依赖关系进行有效的管理,打造一个有序的微服务体系。否则的话,东一个服务,西一个服务,这样会让系统变得碎片化,难以维护和扩展。

所以我这里也放了一张图,来帮助你理解,一个有序的层次化微服务体系大致是什么样子的。

04 _ 可扩展架构案例(一):电商平台架构是如何演变的?[通俗易懂]

总结

电商平台架构的发展过程,从单体架构到分布式架构,再到SOA架构和微服务架构,每种架构都针对前一种架构的缺点做了改进,架构的扩展性也变得越来越好,可以满足更高的业务复杂性要求。

但值得注意的是,每种架构都有两面性,既有优点,又有缺点,在实际系统中,这些架构也都是并存的。架构没有最好,只有最合适的。我们做架构设计时,一定要根据当前业务的特点,选择合适的架构。

最后,给你留个思考题:现在人人都在落地微服务,你在这方面有什么经验和教训吗?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149198.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月16日 下午5:36
下一篇 2022年6月16日 下午5:46


相关推荐

  • linux系统安装Memcache

    linux系统安装Memcache

    2022年2月8日
    51
  • Java实例变量和类变量

    Java实例变量和类变量Java 程序的变量大体可分为成员变量和局部变量 其中局部变量可分为如下 3 类 形参 在方法签名中定义的局部变量 由方法调用者负责为其赋值 随方法的结束而消亡 方法内的局部变量 在方法内定义的局部变量 必须在方法内对其进行显示初始化 这种类型的局部变量从初始化完成后开始生效 随方法的结束而消亡 代码块的局部变量 在代码块内定义的局部变量 必须在代码块内对其进行显式初始化 这种类型的局部变量从初始化

    2026年3月26日
    2
  • linux内存不足导致tomcat宕机

    linux内存不足导致tomcat宕机情况,正常运行的服务器,突然tomcat不能访问了因为服务器的内存是2g的,所以就怀疑是内存不够了,所导致开始排查ps-ef|greptomcat[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TTLyQ5EC-1585835537446)(E:\Workspaces\Markdown\linux\记一次内存不够的情况.assets\image-…

    2022年7月23日
    11
  • 手把手教程:0.02/张接入GPT Image 1.5 API!GrsAi国内直连完整指南,速度超快

    手把手教程:0.02/张接入GPT Image 1.5 API!GrsAi国内直连完整指南,速度超快

    2026年3月16日
    4
  • css画三角形「建议收藏」

    css画三角形「建议收藏」实现原理将div的高和宽设置为0,然后设置四个border不同的颜色。效果如下:div#triangle{width:0;height:0;border-top:50pxsolidblue;border-right:50pxsolidred;border-bottom:50pxsolidgreen;bord…

    2022年6月30日
    33
  • CIDR的IP地址的表示与划分方法

    CIDR的IP地址的表示与划分方法早期的 ip 地址划分 最初设计互联网络时 为了便于寻址以及层次化构造网络 每个 IP 地址包括两个标识码 ID 即网络 ID 和主机 ID 同一个物理网络上的所有主机都使用同一个网络 ID 网络上的一个主机 包括网络上工作站 服务器和路由器等 有一个主机 ID 与其对应 IP 地址是一个 32 位的二进制字符 为了方便人类的记忆 所以 通常人们会将二进制的 IP 地址表示成十进制的格式 没每八位分割一下 即分成四段

    2026年3月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号