写点什么

系统架构系列(五):技术架构之高可扩展系统设计与实现

  • 2019-06-27
  • 本文字数:3441 字

    阅读完需:约 11 分钟

系统架构系列(五):技术架构之高可扩展系统设计与实现

可扩展性是衡量架构设计的一个因素,也经常被开发者提到。但是,一个系统要设计出比较好的可扩展性是有一定难度的,而且可扩展性体现在不同层次上,有大的可扩展性,也有小的可扩展性,本文从可扩展的本质出发,通过平时常用的框架来印证,最后通过实际案例说明如何设计高可扩展性系统。


一、可扩展的本质是什么?

可扩展的意思是在面对变化时,用最少的代价去实现,平时我们听得最多的是面向抽象(接口)编程,如果只是把这里的抽象理解成接口,那么就有些狭隘了,抽象是通式通法,而接口只是其中一个,所以在谈可扩展实现之前一定要讲清楚可扩展的本质是什么,连本质都不知道,怎么提出系统性解决方案。

1.1 扩展的本质

扩展的本质就是占位符,明确告诉你这里被占了,具体谁占了不清楚。那么问题来了:占位符到底是什么?它是怎么表达的?又要如何实现的?如果可以把这三个问题理清楚,就可以想到很多可扩展性方案,而不再是单一的面向接口编程。


  • 占位符到底是什么:占位符仅仅是一个标识,标志这里会有变化,一句话可以概括:凡是可以表达变化的就是占位符,然而具体的变化实现又没有给出,真正体现了做什么和怎么做的分离

  • 占位符怎么表达:要回答这个标识是用什么来表达,变量、接口、配置项…这些都可以表达占位符,变量能被赋值同一类型的数据;接口可以有不同的实现;配置项也可以被赋予不同的值…所以,实现可扩展的思路一下就打开了。

  • 如何实现:再往深层次思考,实现一个接口,如何在执行时动态找到实现类?如果把这个问题想清楚,在实际中实现可扩展又会有一套系统性解决方案。整个过程就两点:识别和执行,识别的意思就是要找到对应目标,接下来就是执行。


综上,到这里可能已经有自己应对可扩展的方法,上面已经给了从不同角度看可扩展性的示例,接下来就是系统化提出应对可扩展的方法。


结论一:扩展的本质就是占位符,凡是可以表达变化的就是占位符

1.2 应对可扩展的方法

先给出应对可扩展的方法:规范、识别、注册、使用,这 4 点都是从上面可推导出来的,下面一一进行详细说明。


  • 规范:规范是从占位符推导出来的,既然是标志有变化,一定要遵循一定的规范表达,否则别人是不知道的,如接口,就是很直接地表达这里是有变化的,具体的实现还不知道;变量天然地表达这里是变化的数据。

  • 识别:有了规范定义之后,接下来就是识别,之前为什么可扩展一直对我们来讲很虚,那是因为规范和识别都是系统帮我们做的,我们只是知道而没有真正实践。规范是定义,识别是找出有哪些实现了规范。

  • 注册:识别出来之后,就要把信息存储起来,可以存储在本地,也可以存储在远程,如果存储在远程就是一个注册的过程,这里的注册就是存储的意思。简单理解就是识别出来之后要集中管理。

  • 使用:使用就很简单,找到具体实现并执行逻辑处理。


上面四个单词看起来简单,除了使用是终极目标外,其它三个都是抽象的表达,比如规范如何定义、怎么识别、如何注册?通过上面的表述可以看到具体要怎么实践,这里再总结下:


  • 规范如何去定义:凡是可以表达变化的就能用它来定义,常见的有配置项、变量、接口、注解等;

  • 怎么去识别:这个要具体去看如何定义规范,如配置项的变化有一个监听变化;注解是要扫描类来识别 annotation;

  • 如何去注册:如果系统的交互只是一个,那么存储在本地就行,如果系统的交互是多个,那么要注册到一个注册中心上去。


结论二:应对可扩展的方法:规范、识别、注册、使用

1.3 扩展的经典案例

此处使用一个经典案例来说明可扩展性,并从其原理上印证上述方法。


在 Java 中,SPI 对于大部分人来讲并不陌生,最典型的加载数据库驱动就是通过 SPI 来实现的。如果你看了 SPI 的原理,再去看上面写的,会感觉两个思路很相似。


SPI 有它的规范,要到指定目录下加载对应文件;找到文件后进行解析、识别并加载;最后就是使用。整个流程能印证上面所提到的:规范、识别、注册、使用。所以,方法的提出有一个点就是从具体案例中进行抽象,提炼共性的东西,再去推演其它案例看能不能也满足。

二、可扩展性系统实践之路

此处以优惠券业务平台为例讲解可扩展性系统设计与实现,在上一篇文章中已经讲了优惠券系统是一个平台型的业务系统,要做到业务与业务的隔离、业务与平台的隔离。

2.1 识别变化

经过整体分析之后,已经确定大业务流程:建券、发券、用券、退券,以及对应的子流程,接下来就是要分析出哪些内容会变化。



比较明显的变化就是领券、用券门槛的变化,因为不同业务线有不同的限制条件,有的要限制不同人群,有的要限制领取次数…已经认别了变化接下来就是要处理这些变化。


结论三:找扩展点就是找系统经常变化的地方

2.2 处理变化的常见手段

2.2.1 野蛮处理


一个最简单的处理,就是在代码中写 if else,它的特点是简单直接上线,不足的点长期下去,系统会变得很难维护、可扩展性较差。


   if(productId = ProductEnum.A){       // 具体的处理   }else if(productId = ProductEnum.B){      // 具体的处理   }else if(productId = ProductEnum.C){      // 具体的处理   }else{      ......   }
复制代码


这种代码放到现在,很多系统还是这么做的,而且是在业务发展初期最喜欢用这种野蛮处理方式,搞上去就能直接上线,快速支持业务。


2.2.2 面向接口设计


对上面野蛮方式的一个常见处理就是面向接口设计,抽象出一个限制条件检查的接口,不同的业务线有对应的实现,通过配置指定业务线下所有的实现,将这些实现放到一个映射中,在程序执行过程中,通过业务线就可以执行所有的接口实现类并依次执行。


     List<Rule> ruleList = RuleFacotry.getByProductId(prodcutId);
复制代码


这种方法比第一种明显要好,体现了一定的可扩展性,新加一个规则限制,重新实现接口就行,然后在配置项中加上这个新的实现,代码的改动量也还好。它有一个明显的问题就是每次新加一个实现就要发布上线,有没有办法不发布上线就能满足目的呢?有,就是下面提到的一类可扩展性设计的方法。

2.3 一类可扩展性设计的方法

再来明确一下目标:系统具备可扩展性和不发布系统就能实现新增功能。


还是使用上面说的方法:规范、认别、注册、使用,下面结合这个具体的案例来说明。


  • 规范:这里是用接口来作为规范描述限制条件,包含入参和出参,这里有一个开放平台,实现了一个接口后就可以提交代码。

  • 识别:在建优惠券时,会加载业务线有哪些业务规则实现,在领取、使用时可以进行配置选择,此时只是插入一个变量标识使用某个限制条件(如限人群,这个实现的逻辑可能会变化,通过变量名来标识变化)。

  • 注册:系统在执行的过程中,发现有限制条件的变量名,拿这个变量名从开放平台中拉取具体的实现存储在本地(有一个缓存时间,具体的过期时间依业务考虑,我们取的是 30 分钟)。

  • 执行:拿到具体的实现后,依次执行。


再整理下流程步骤,让大家更进一步掌握该设计方法:


  • 在开放平台提交限制条件接口的实现代码,有限制人群的实现、限制领取券次数…

  • 在开放平台提交之后,会入库存储,数据库里会存储一个业务线对应的多个限制实现。

  • 创建优惠券时,会加载业务下的限制规则,通过配置选择具体要使用到的限制规则(相同业务线下的不同优惠券可以有不同的规则限制),配置选择后,会在规范字段中存储规则实现的 id(规则实现可能会变化,会有多次提交),所以这里存储的是 id,在执行的时候可以拿到这个 id。

  • 在领券、用券时,会检查规则限制有哪些,通过 id 列表从远程开放平台拉取具体实现,把 java 代码拉下来之后就可以编译,并存储到本地或者集群缓存中。

  • 最后就是执行具体的实现逻辑。



结合这张图看就会清晰很多,整体的业务平台架构比较清晰,分为开放平台、配置平台、业务平台和数据平台,一个新业务方接进来很简单,简单配置下就可以使用。

三、小结

本篇文章主要讲可扩展性系统的设计与实现,从可扩展的本质讲起,可扩展的本质就是占位符,凡是可表达变化的都可以称之为占位符,常见的有变量、接口、配置项、注解等,然后提出应对可扩展性的方法:规范、识别、注册、使用四个步骤,虽然只有 8 个字,但它包含了一套系统的处理方案,不再是单一的面向接口编程,最后结合具体的案例进行说明如何设计可扩展性系统。


作者介绍:


高福来,先后在 Oracle、阿里工作,目前在滴滴小桔车服加油团队负责营销基础(优惠券、奖励金),在分布式中间件和系统架构方面积累了一定的经验,擅长用通俗易懂的语言描述复杂问题。


相关文章:


《系统架构系列(一):如何用公式定义该概念?》


《系统架构系列 (二):应对这一概念的方法》


《系统架构系列 (三):业务架构实战上篇》


《系统架构系列(四):业务架构实战下篇》


2019-06-27 08:3516751

评论 10 条评论

发布
用户头像
这个系列讲的不错
2019-09-13 13:40
回复
用户头像
看着有点难理解,希望可以详细讲解, 业务平台和业务方应用在运行态的关系 , 是否可以理解为业务平台只保存定义和配置,在运行时还是由业务方应用拉取到本地来编译运行
2019-06-27 23:45
回复
业务平台里有固定的业务流程,由于每个业务线相同功能也有不同的实现,就提供一个扩展点出来,可以是业务平台来实现,也可以是业务方自己实现,把这个实现上传至开放平台上,业务平台在配置的时候会记录规则id,业务方应用调用业务平台时,业务平台会根据记录的规则id去开放平台拉取对应扩展点的实现代码编译运行
2019-06-28 09:35
回复
同感;系列中1、2、3文笔流畅,思路清晰,4,5当中”平台“字眼有些多,平台之间的关系阐述的有些拗口,难理解;
仍然为作者的分享点赞
2019-06-28 16:32
回复
感谢您的反馈,为您的持续关注点赞
2019-06-28 16:40
回复
用户头像
深入浅出的讲解了系统架构:
系统架构=解决待定的问题+连接+要素。
实践这个的方法:系统性思考 分解 抽象 模式
非常感兴趣,希望有机会线下交流
2019-06-27 16:48
回复
期待 可以先加个微信哈(gaofla)
2019-06-27 18:28
回复
我也想加大佬微信
2020-12-10 09:08
回复
没有更多了
发现更多内容

众妙之门玄之又玄,游戏系统中的伪随机(Pseudo-Randomization)和真随机(True-Randomization)算法实现Python3

刘悦的技术博客

算法 游戏 Python3 算法实践 随机数

悟空的私藏「架构』书籍推荐

悟空聊架构

4月日更 悟空聊架构

Go 学习笔记——Switch(我不是游戏机)

为自己带盐

Go 学习笔记 4月月更

APP应该关注哪些数据指标?

InfoQ IT百科

企业级知识管理(KM)建设方法及过程

小炮

知识管理

报名开启|QKE 容器引擎托管版暨容器生态发布会!

青云技术社区

Rust异步框架的性能评估

非凸科技

tokio Zenoh 异步框架 async_std smol

全网征集!说说你跟宜搭之间的故事吧

一只大光圈

阿里 低代码 数字化 钉钉宜搭 宜搭

2022年,网传苹果即将发布的新机型iPhone 14 Pro和iPhone 14 Pro Max将会是全新屏幕造型,不再是刘海屏,你对新屏幕造型的iPhone 14期待吗?

InfoQ IT百科

设计千万级学生管理系统的考试试卷存储方案

哈喽

「架构实战营」

秒云助力中电科32所发布“基于拟态应用集成框架的SaaS云管理平台解决方案”

MIAOYUN

内生安全 拟态应用集成框架 网络空间内生安全大会

企业级知识管理(KM)建设方法及过程

小炮

知识管理

面向全球市场,PlatoFarm今日登录HUOBI等全球四大平台

小哈区块

手机运行内存应该怎么选?

InfoQ IT百科

社区运营书籍推荐

坚果

4月月更

这个API Hub厉害了,收录了钉钉企业微信等开放Api,还能直接调试 !

Liam

前端 Postman API OpenAPI 开放api

CrashSight 常规功能&特色功能介绍

WeTest

面向全球市场,PlatoFarm今日登录HUOBI等全球四大平台

西柚子

你知道你的手机上有多少传感器吗?

InfoQ IT百科

如何彻底删除电脑上的文件?

InfoQ IT百科

rm格式的文件怎么打开?

InfoQ IT百科

开源大数据OLAP引擎最佳实践

五分钟学大数据

数仓 4月月更

敏捷实践 | 提高小组可预测性的敏捷指标

LigaAI

敏捷开发 敏捷度量

如何通过云效Codeup完成代码合并 | 云效

阿里云云效

云计算 阿里云 代码管理 Codeup 代码合并

对线郭老师职业发展,记下自己的心得体会

北洋

面试 职业规划 程序猿 4月月更

坚持做正确的事情

FunTester

科创人·派拉软件CEO谭翔:零信任本质是数字安全,To B也要深研用户心智

科创人

2022年,5G芯片会有哪些值得期待的发展趋势?

InfoQ IT百科

电脑上怎么快速切换显示不同的软件界面

InfoQ IT百科

为什么智能手机传感器市场一直是索尼占主导

InfoQ IT百科

优麒麟 22.04 LTS 版本正式发布 | UKUI 3.1开启全新体验!

优麒麟

Linux 开源 操作系统 优麒麟 22.04

系统架构系列(五):技术架构之高可扩展系统设计与实现_文化 & 方法_高福来_InfoQ精选文章