2月5-7日QCon全球软件开发大会携手100+位大咖讲师落定北京,点击查看完整日程>> 了解详情
写点什么

架构设计实践五部曲(五):技术架构的战略和战术原则

  • 2019-09-28
  • 本文字数:4681 字

    阅读完需:约 15 分钟

架构设计实践五部曲(五):技术架构的战略和战术原则

技术架构,是将产品需求转变为技术实现的过程。技术架构解决的问题包括了如何进行纯技术层面的分层、开发框架选择、语言选择(这里以 JAVA 语言为主)、涉及到各自非功能性需求的技术点(安全、性能、大数据)。技术架构是确定组成应用系统实际运行的技术组件、技术组件之间的关系,以及部署到硬件的策略。


技术架构面临最大的挑战是“不确定性”。 在技术架构上,很多时候就会面临这种选择。是要选择业界最新的技术?还是选择团队最熟悉的技术?如果选择最新的技术,遇到新技术出了问题怎么解决?如果选择目前熟悉的技术,后续技术演进怎么办?这些都是架构师在做技术架构过程中需要考虑的。


业务在千变万化、技术在层出不穷,没有一套通用的技术架构模式来适用所有的系统。那么,我们如何保证在做技术架构时,能够实现一个稳定、出色的系统。面对这些“不确定性”时的架构设计问题,这里从战略和战术两个层面来提供一些设计原则。战略层提供的是技术架构的方法和思路,属于顶层设计;战术层提供的是技术架构的技术实践方式,更偏向详细设计。


1.战略层设计原则

战略层的设计原则就是:合适原则、简单原则、演化原则。


1.1 合适原则

技术人员有一种很强的技术情怀,就是在做设计的过程中,很希望挑战新的技术、在项目中采用最新的框架、或者自己重造一个比业界的还要牛的轮子。这样才能够显示出自己的优秀,以至于不让自己显的那么平庸。比如,在项目中重新造一个能够解决亿万级数据的新的 xx 流式计算技术,比 flink 还要牛一百倍;有或者在项目中使用最新的 xx 技术,能让系统承担亿级用户的访问。


那么现实是,如果在设计过程中一味追求新技术,往往失败的可能性很高。


  1. 没有那么多人,却想干那么多活


现实环境中我们一个业务团队可能就十几个人,项目工期短、上线要求快。在这种情况下,如果还要抽调几个人去研究、搭建、维护新的技术框架,对于项目势必会造成延期的影响。


  1. 没有那么多积累,却想一步登天


很多业界领先的方案,不是一帮优秀的开发加在一起,加班加点就能做出来的。而是经过几年时间的发展才逐步完善和初具规模。如果我们也想自己做一套类似的技术,不是说不可能。我们需要集合当下的技术实力、技术积累,做出适合自己团队情况的技术评估。


  1. 没有最新,只要最合适


所有新的技术刚出来都是打着比旧技术拥有更加出色的性能、提供更加优秀的扩展性。是不是使用新技术,就能解决一切问题了?新技术的出道,势必是解决某一场景下的问题,并不是一味万能良药。只有了解清楚每种技术的产生背景,适用场景,才能出一个对自己项目最优的选择。技术选型没有最新,只有最合适。


总结一下,合适原则就是适合优于业界领先。


1.2 简单原则

我们总是希望能将我们的软件设计的精美、宏大,这样才能彰显我们系统的复杂度和难度。我们是不是会遇到这样的场景,在做设计方案的时候,如果一个解决方案很简单,而且能很快的满足需求。在评审方案时,就会有人觉得这个方案是不是太简单了,没有什么技术含量,是不是需要再设计的复杂一点。


系统是不是一定要设计的复杂?在回答这个问题前,我们先看下软件领域的结构复杂性和逻辑复杂性。


  1. 结构复杂性


结构复杂的系统有两个特点:第一,组成的组件数量很多;第二,这些组件之间的关系很复杂。如下图:



图 1


结构上的复杂性存在的第一个问题是,组件越多,就越有可能其中某个组件出现故障,从而导致系统故障。假设组件的故障概率是 1%(有 1%的时间不可用),那么 2 个组件的系统可用性是 99%*99%=98%,5 个组件的系统可用性是 99%*99%*99%*99%*99%=95%,两者相差 3%。说明组件越多,系统稳定性就越差。


结构上的复杂性存在的第二个问题是,某个组件改动,会影响关联的组件。比如上图中 C 组件发生改动,会影响 A、B、D,而 A 有会影响 E。这样就会形成一连串的多比诺效应。


  1. 逻辑复杂性


意识到结构复杂性的问题后,只要减少组件就能让系统结构变简单?这样做还是行不通,原因在于除了结构的复杂性,还有逻辑的复杂性,如果一个组件的逻辑太复杂,通用会带来问题。


我们试想一下,把淘宝的所有功能都在一个组件中实现,可以想象这个系统要有多庞大:几百人维护一个系统、代码分支几十个、需求变更应接不暇、不同分支的回归测试、修改一段代码可能影响整个系统的运行等等。这些场景相信大家都不希望看到的。


总结一下,简单原则就是大道至简。


1.3 演化原则

软件架构和建筑架构很多相同的地方,架构这个词也是从建筑领域借鉴过来的。比如,软件架构描述的是系统的结构、以及各模块之间的关系。而建筑结构描述的是一幢建筑的结构,以及建筑内部各部件如何有机的组成。


但是,软件架构和建筑架构有一个本质上的差异:那就是建筑一旦完成就不会再变,而软件却需要根据业务的发展不断的变化。对于建筑来说,永恒是主题;而对于软件来说,变化才是主题。


如果没有意识到“软件架构需要根据业务发展不断变化”这个本质,在做架构设计的时候很容易陷入一个误区:试图一步到位设计一个软件架构,期望不管业务如何变化,架构都稳如磐石。如果是按照这样的目标是设计,一开始上来就做出一套看似是终极的方案,投入庞大的资源做各种预测、分析。结果是投入巨大的资源、开发周期漫长,最终跌跌撞撞落地的系统,却发现已经无法很好的满足现有的业务。


所以技术架构设计需要一个过程:


首先,要满足当前的业务需求进行技术架构设计


其次,架构要不断地在实际应用过程中迭代,保留优秀的设计,修复有缺陷的设计,改正错误的设计,去掉无用的设计,使架构逐渐完善。


第三,当业务发生变化时,架构要扩展、重构、甚至重写;代码也许会重写,但有价值的经验、教训、逻辑、设计却可以在新架构中延续。


总结一下,演化原则就是演化优于一步到位。


2.战术层设计原则

战术层的设计原则分为 3 部分:高并发原则、高可用原则、业务设计原则。这些原则是对技术架构设计过程中提供详细的指导思路,帮助你做技术选型、技术拆分。


2.1 高并发原则

设计高并发的系统,需要考虑以下几个方面的设计:无状态、拆分、服务化、消息队列、数据异构、缓存。


  1. 无状态


  • 无状态应用,便于水平扩展。

  • 有状态配置可通过配置中心实现无状态


  1. 拆分


  • 系统维度:按照系统功能、业务拆分,比如购物车、结算、订单等。

  • 功能维度:对系统功能再做细粒度拆分。

  • 读写维度:根据读写比例特征拆分;读多,可考虑多级缓存;写多,可考虑分库分表。

  • AOP 维度:根据访问特征,按照 AOP 进行拆分.

  • 模块维度:对整体代码结构划分 web、service、dao。


  1. 服务化


  • 服务化演进:进程内服务 -单机远程服务 -集群手动注册服务 -自动注册和发现服务 -服务的分组、隔离、路由 -服务治理。

  • 考虑服务分组、隔离、限流、黑白名单、超时、重试机制、路由、故障补偿等。


  1. 消息队列


  • 目的:服务解耦(一对多消费)、异步处理、流量削峰缓冲等。

  • 大流量缓冲:牺牲强一致性,保障最终一致性。

  • 数据校对:解决异步消息机制下消息丢失问题。


  1. 数据异构


  • 数据异构:通过消息队列机制接受数据变更,原子化存储。

  • 数据闭环:屏蔽多重数据来源,将数据异构存储,形成闭环。


  1. 缓存


  • 用户层:DNS 缓存、浏览器 DNS 缓存、操作系统 DNS 缓存、本地 DNS 服务商缓存、DNS 服务器缓存、客户端缓存、浏览器缓存、APP 客户端缓存。

  • 代理层:CDN 缓存(一般基于 ATS、Varnish、Nginx、Squid 等构建,边缘节点 -二级节点 -中心节点 -源站)

  • 接入层:Nginx 的 Proxy_cache 代理缓存,或者 Nginx+Lua+Redis 做业务数据缓存。

  • 应用层:页面静态化、业务数据缓存(Redis/Memcache/本地文件等)、消息队列

  • 数据层:NoSQL(Redis、Memcache、SSDB 等)


2.2 高可用原则

  1. 降级


  • 降级开关集中化管理:将开关配置信息推送到各个应用。

  • 可降级的多级读服务:如服务调用降级为只读本地缓存。

  • 开关前置化:如 Nginx+Lua 配置降级策略,引流流量;可基于此做灰度策略。

  • 业务降级:高并发下,保证核心功能,次要功能可由同步改为异步策略或屏蔽功能。


  1. 限流


  • 目的:防止恶意请求攻击或超过系统峰值

  • 恶意请求流量只访问到 Cache

  • 穿透后端应用的流量 Nginx 的 limit 处理

  • 恶意 Ip 使用 Nginx Deny 策略或者 iptables 拒绝


  1. 可回滚


  • 发布版本失败时,可随时快速回退到上一个稳定版本。


2.3 业务设计原则

  • 防重设计

  • 幂等设计

  • 流程定义

  • 状态与状态机

  • 后台系统操作可反馈

  • 后台系统审批化

  • 文档注释

  • 备份


3.技术架构图

技术架构图是将系统的技术方案、技术选型通过视图的方式进行展现。技术架构图分为两类:一类,功能需求技术架构图(逻辑架构图),是描绘如何通过技术组件来实现系统产品功能的图。另一来,非功能需求技术架构图(物理架构图),是描绘如何通过物理部署的来实现系统运行的图。


3.1 逻辑架构图

功能需求技术架构图以产品架构图和应用架构图为基础。实现每个功能点需要使用什么技术、技术实现逻辑如何,就提现在技术架构图上。功能需要技术架构图绘制可以按照“整体 -局部 -整体”的思路实现。


  • 整体


首先可以按照应用架构图的应用分布得到应用分布框架。如下:



图 2


  • 局部


在整体框架的基础上,对每一个局部的子系统进行详细的技术实现的表达。子系统的技术架构图中需要展示每个子系统使用的技术组件,比如(缓存技术、消息中间件、流程引擎、流式计算框架等等)。同时,这些技术组件是如何实现业务功能,需要清晰的展示技术实现逻辑。


下图是对风控系统中的实时引擎、离线引擎、准实时引擎三个子系统的进行的技术架构。在实时引擎中,主要使用 RuleEngine(规则引擎)作为技术特点,这里就重点列出 RuleEngine。准实时引擎使用 Blink 作为流计算的技术框架,并概要的展示了计算逻辑。



图 3


  • 整体


在完成每个子系统的技术实现后,最终进行一次整合,绘制一张总体的系统技术架构图。各子系统之间通过服务接口、数据库、缓存或消息中间等技术实现数据交互,以此将打通各个子系统,实现最终整个产品从数据、技术的串联。



图 4


3.2 物理架构图

物理架构偏重于网络设计、集群设计、中间件设计、数据存储设计等基础软硬件的设计架构。非功能需求的技术架构图重点在于展示企业系统在物理上是如何部署。物理架构规定了组成系统的物理元素、物理元素之间的关系以及他们的部署策略。物理架构反映出软件系统动态运行时的组织情况。从物理架构图中,我们能够全局的得知整个系统是如何从流量访问、数据流转、数据存储到技术组件的运转。



图 5


4.总结

我们从架构的本质开始,分别对业务架构、产品架构、数据架构、应用架构、技术架构的设计提供了一些思路和原则。这些思路和原则在进行架构设计和画架构图的过程中提供一些指导帮助。最后我们再来思考一个问题,好的软件架构是规划还是演化出来?


架构规划对架构的影响是很重大的。首先,好的架构是设计出来的。好的架构,系统的性能和质量都将很高。架构设计的质量直接影响架构后续向好的方向演化的难易程度。架构设计如同城市规划一样,缺少规划将难于演化。



图 6


演化是一个过程,这个过程或长或短,所以演化需要考虑系统的生命周期。如果演化的过程非常漫长,超出了软件的生命周期,即使架构越来越优化,对于产品或者项目的帮助也将有限,所以时间这个约束条件是非常苛刻的。


在现有规划的基础上进行演化,我们无法得到普适的架构,但可以得到确定领域的通用架构,可以在特定领域通过演化使架构逐步优化,帮助业务快速的发展。


作者简介


胡斌,菜鸟网络技术专家,目前负责菜鸟风控系统的建设。曾在淘宝技术部先后负责卖家平台、商家运营等领域。在大规模分布式应用、大数据、架构领域有多年的开发和管理经验。


延展阅读

架构设计实践五部曲(一):架构与架构图


架构设计实践五部曲(二):业务架构与产品架构设计实践


架构设计实践五部曲(三):从领域模型提取数据架构


架构设计实践五部曲(四):单体式与分布式的应用架构


2019-09-28 08:0016567

评论 8 条评论

发布
用户头像
有几个问题想请教下,您在文章里面把架构分为了以下几个
1. 业务架构
2. 产品架构
3. 应用架构
4. 数据架构
5. 逻辑架构(功能需求技术架构)
6. 物理架构(非功能需求技术架构)

网上的李运华老师又把后端架构分为了
1. 业务架构 -- 按业务划分
2. 系统/后端架构 -- 按模块划分
3. 应用架构 -- 按应用划分
4. 部署架构 -- 按组件划分

我看两则的主要区别是 产品架构和数据架构在李运华版本中没有列出,同时其逻辑架构是否就等同”系统/后端架构“呢。

我个人的理解是这样的:
1. 首先肯定是产品人员出来”业务架构图“, 然后根据业务架构图规划出产品范围得到”产品架构图“(该图可能包含了以后要做但当下不做的内容), 以上两个图都是产品人员负责出,很多时候甚至没有业务架构图。

2. 根据产品架构图,架构师开始思考如何将某些功能进行拆分或组合,以及对共性的能力下沉,然偶得到功能架构图。 -- 其实这个过程就是在进行技术实现层面的模块拆分,以及为了支撑产品功能需求加入的某些功能点等。

3. 根据功能架构图中各模块的耦合关系进行应用的拆分,得到应用架构图,同时设计出数据架构。

4. 然后根据功能性和非功能性需求设计出技术架构。

5. 最后设计出物理架构。

其中,第2点是不是不需要,直接使用产品架构来衍生出应用架构即可呢??? 同时,我上面的理解是否有问题?? 恳请指教~~











展开
2022-08-17 14:45 · 重庆
回复
用户头像
很好的系列
2022-08-17 14:20 · 重庆
回复
用户头像
刚开始接触架构,就看到了这个系列文章;图文并茂,感觉醍醐灌顶;对架构有了整体的认识,非常感谢大佬;
2022-08-12 15:41 · 北京
回复
用户头像
应用架构图的重点是体现应用之间的逻辑关系和通信关系,体现产品的内部关系和外部关系。内部关系是产品内各应用的调用关系;外部关系展现的是产品与外部系统间的调用关系。将应用的内外关系呈现在应用架构中,产品在整个业务中的定位和影响将变得清晰。
2020-03-19 13:36
回复
用户头像
这个系列文章非常棒,最近在研究架构,发现很少有成体系的论述,都相当杂乱,像4+1模型感觉还是太古板了,不太适合互联网项目,个人简介而已。
2019-10-22 16:34
回复
用户头像
这个图还是脱敏了···看过你写的六扇门啊
实时拦截的话,必须依赖缓存吗,挂了怎么办
2019-10-10 15:58
回复
用户头像
不错的系列文章,逻辑合理,结构清晰,值得学习!
2019-09-29 12:56
回复
用户头像
受益匪浅,等待实践反馈
2019-09-29 11:36
回复
没有更多了
发现更多内容

云原生,开发者的黄金时代

阿里巴巴中间件

云计算 阿里云 云原生 中间件

面试字节跳动java岗被算法吊打,60天苦修这些笔记,侥幸收获offer

Java~~~

Java 架构 面试 算法 红黑树

0代码之缘

明道云

Nebula Operator 云上实践

NebulaGraph

阿里云 云原生 k8s 图数据库 分布式图数据库

RunC TOCTOU逃逸CVE-2021-30465分析

腾讯安全云鼎实验室

容器 漏洞分析

模块五设计微博评论高性能高可用计算架构

kitten

阿里 Java 二面必问:8张图带你解决所有TCP可靠传输问题

编程 面试 TCP 网络 计算机

crudapi增删改查接口零代码产品成功案例之金茶王投票系统

crudapi

Vue API crud crudapi 投票

校招失败,在小公司熬了2年后我终于进了字节跳动,竭尽全力(Java岗)

今晚早点睡

Java 编程 字节跳动 面试 计算机

我们可能是被工具耽误的一代

非著名程序员

深度思考 认知提升 成长笔记 8月日更

区块链钱包系统开发,imtoken去中心化钱搭建

干货|后互联网时代,运维工程师的必备性能优化指北

阿里巴巴中间件

阿里云 云原生 中间件

【我和达梦的故事】 有奖征文活动开始啦,万元奖品池+现金奖励等你拿!

墨天轮

数据库 征文大赛 国产数据库 达梦

终于学完国内算法第一人10年经验总结的数据结构与算法详解文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

linux 工具之pstack/gstack

webrtc developer

Vue进阶(四十二):var、let、const 三者区别

No Silver Bullet

Vue var const let 8月日更

面面俱到!腾讯大牛把源码分析、基础案例、实战案例、面试、系统架构,全部总结到这份Java多线程与高并发里面了

Java 编程 程序员 面试 多线程

不会被开除吧?一顿饭换来“字节”面试题库Java岗,刷完直接入职大厂

Java架构师迁哥

架构实战营1期模块5作业——高性能计算架构

tt

架构实战营

音视频demo| 不一样的AR Call

anyRTC开发者

uni-app 音视频 移动开发 uni-app demo

谷歌架构师分享gRPC与云原生应用开发Go和Java为例文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

终于拿到了深入Java虚拟机:JVMG1GC的算法与实现文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

架构实战营模块 5 作业指导

华仔

#架构实战营

linux 工具之perf

webrtc developer

架构设计实践五部曲(五):技术架构的战略和战术原则_架构_胡斌_InfoQ精选文章