在内网上有太多的架构相关的文章了(比如大名鼎鼎的自顶向下),我之前也写过应用架构设计的经验。但是总有种雾里看花的感觉,好像有很多相关的知识,soa、分布式事务、DDD、复杂系统重构、领域建模、业务架构、等等等,这些复杂的名词和知识感觉学了一堆仍然不得其法。
所以我准备把我这些年在支付宝做架构,自己摸索成长的内容写下来,看能否帮助到大家。
我们经常说,要有架构师的能力,或者说需要成长为一个架构师。但是我们需要怎么成长?或者说什么才是“能力”?架构师的能力包含了什么内容?在我看来,能力的本质就是认知。所以,所谓架构师就是有着架构师的认知,和一些通用技术能力。
在我的认知里(哈哈,这句话也说明了这个标题的重要性),所谓能力,就是不同的认知能力。所谓成长,就是认知升级的一个过程。我想先用一个例子,来说明这个事情。我在面试中经常被问到一个问题,我也喜欢问别人:java当中如何处理多线程,如何处理并发。
高级工程师的回答:
使用Thread对象的方式来开启线程,传递Runnable,在多线程里面处理业务代码,这样就是并行处理了。此外在jdk1.5里面,增加了Executors类,可以方便的使用一些ThreadPool来处理多线程的线层复用部分。并发安全部分,如果多线程访问共享资源,那么就会有线程安全问题。我们可以使用sync关键字来同步代码。jdk1.5之后是Lock可以处理。这里可以扩展出很多的问题,比如Lock的实现原理,sync基于对象头,局部变量没有线程安全问题(线程栈)等等的扩展问题。
但是这样回答有问题吗?没有问题,不过没回答完。
我的回答:
不用多线程。这是我真实的回答,同时我99%以上的场景都拿到了正反馈。即:面试官非常认可我的回答。具体这个问题我怎么回答,我接来下讲,什么是架构师的认知就会说到。
这里,我想通过这个例子说明的就是:能力的不同,对于这个问题的认识就不同。反过来说也一样,对这个问题的认识的不同,也代表的能力的不同。而这,就是为什么我觉得成长,是认知的升级。所谓认:就是我们对事务的认识,理解,归因和定义。所谓知:就是我们要做的事情的方法,方案,选择和决策。
是什么
那么架构师,需要的认知是什么呢?我从阿里的job model里面抽离出来关键字:系统性&体系化思考,知其然知其所以然。仍然用上面的问题:java当中如何使用多线程?如何处理线程安全问题?
我的回答:不用多线程。
为什么?
我上面简单的说了一下。正常业务中是不会用线程池的。
这体现了哪些方面呢。
体系化
比如我在回答这个问题的时候,很随意的拆分成了几个维度来回答:坏处,技术难点,使用场景,最佳实践。这就是当我们回答一个问题的时候,自然而然的按照一定的模型思考,然后进行回答。无论这个模型是什么,他都是体系化的一种。
比如直接回答:1.为什么要用多线程?2.不用多线程有没有别的方案等等,这些都是思考的一个模型,按照这些维度进行拆分,这些维度进行汇总。就是体系化。
很有趣,读到这里又可以停下来了。我们可以回答:如何拿到架构师offer?
我们能否做到一个维度拆分?比如我这个文章,就是一个拆分的维度。而开始思考维度,就是架构师需要的一个认知,这也是体系化&系统化思考的表现。关键不在于结构是什么,关键在于需要有结构。
知其然知其所以然
为什么体现了这个呢,其实很简单,就是一个能力:多问一个why。这个能力是极其重要的,往往我们对于问题的定义高度,就决定了我们的架构高度。比如刚才的例子:如何处理线程安全问题?多问一个why:为什么要处理线程安全问题?可能这个时候就发现:是因为多线程并发访问共享资源问题。
那么我们的方案是不是就可以变成:不访问,主要是不写入共享资源,是不是就没有线程安全问题了?此外,也可以问:为什么要用多线程?可能回答是:要处理多任务并行能力,或者任务异步化能力降低请求耗时问题。那么是不是有别的技术方案可以解决?消息队列。可靠消息异步化能力。这点非常非常非常重要,重要到应该形成我们的本能。甚至不仅仅是技术方面。比如我这个文章,就可以问,为什么是两部分。为什么是架构师。等等。技术上,任何一个框架,都要问,这个框架解决了什么问题。
怎么做
可以从认知结构上和行为习惯上来说我们怎么做到成长。也可以直接给出答案,我们应该做什么具体的事情。我还是从这两个维度来描述这个问题。有没有发现,我说的内容都是总分结构?其实这是非常常用的一个方式。
认知结构
怎么做很简单,就是要多想一点,要知道用什么方法多想一点,多思考一点。而这个方法就是怎么做,思考出来的过程,就是认知结构,做到了这点,就会很快的成长。
我会简单的解释一些分析方法。
首先金字塔模型里面说的一个:
MECE原则总结来说就是两个维度:无重复,无遗漏我们描述一个问题或者事情,应该做到不重复。比如我们说什么是人类,可以说两个维度:生理性别男,生理性别女。这两个维度是不重复的(这里不讨论假定性别问题)。并且是不遗漏的。如果我们划分是:少年,青年,老年,这就不是一个很好的维度,因为年龄可能存在交叉。
5w2h这个维度思考
5w其实就可以划分成:
我讲解5w2h的这个过程,就是自然而然的对5w2h进行维度拆分的过程:分析维度,属性维度,关键方案,关键ROI。我不断的重复这个事情,就是想让大家理解,这些维度都是一个个的方法。我们要形成自己拆维度的习惯。
3why方法
很简单,对于任何问题,我们追问3个为什么。这样就能定义问题的本质,直面我们具体要解决什么问题。比如:
我们为什么要获得架构师offer?可能是我们想获得成长和一个好工资。(这里就明白我们本质需要,我们是看重工资还是真的成长空间?如果是成长,可能是找到几个良师益友,也不一定是换公司)
什么是更好的生活?可能是自我价值的体现。(这里可能就会更好的认识自己,所以认知的升级,也是不断加深自我认知的一个过程)
还有很多很多,比如swot,四象限等等。关键是帮助大家打开一个门。这个门就是:我们要多想想,并且我们是要按照一定的方法多想想。
具体的事情
这里我都会在后面详细的解释。对于我们技术人员来说。在日常工作和学习中,可以做下面几个事情。
1.抽象
我感觉这也是架构的基础,哪怕从架构的第一阶段:框架,开始,都是解决某一类的特定问题。比如ORM框架解决db和java代码之间的映射关系等问题。
在我们的实际业务代码中,我们尽量能对我们要实现的功能,多问一个why,也就是多抽象一点。比如一个活动参与次数的功能,我们抽象定义成一个通用的计次服务。这样可以多业务场景复用。比如我们处理业务报错之后的特殊逻辑,可以用AOP+异常处理流程。来做一个通用的框架,可以解决所有分支链路和主业务链路的解耦问题。
2.分层定义
按照清晰的维度,进行明显的层次划分。不同的层次有不同的特性和符合这一层次的关键职责。
在具体的工作中,有个习惯大家可以试试:我们总归有一层设计,是没有业务语义概念的。比如完整的一个insert操作。这个insert sql肯定没有业务语义,完全不理解这是一个什么场景需要insert。它只专注于实现insert功能。按照这种方法。我们就可以不断的抽象出不同的功能。在具体的架构方法里面我会介绍的详细一些。
3.思考业务问题,业务本质与业务价值
要思考我们为什么写代码,是实现某个功能,这个功能最终怎么产生的业务价值,那么对我们的功能就有什么要求?对我们代码的抽象,是架构,对业务本质的抽象,也是架构。业务价值最终决定着我们的架构价值。
从我们技术角度,业务就是我们要解决的”问题“。因为对于业务的定义,公司层面上就是要做”赚钱的事情“。而技术同学,代码怎么产生价值,就是代码怎么赚钱,所以描述业务能力,就是描述我们的定义问题能力。
业务=赚钱的问题
代码=怎么赚钱的问题
业务就等于,代码上要解决的问题。
必须说明,在公司内部晋升和外部面试,最大的不同就在于”业务“描述上。因为公司更考察业务洞察能力和业务本质定义的专业能力。而外部公司,往往不会直接做相关的业务,只会做相关内容,所以考察的往往是”通用的“,并且是”成熟的“特定内容解决方案。比如资金类业务,电商类业务,创新类业务,toC个人类业务这些业务场景中遇到的技术问题。要想说清楚技术方案,就必须介绍业务背景。而这就是体现技术专业度的地方。还有一部分是为了引出架构问题,描述我们的架构解决了什么业务问题,就需要对业务背景,业务本质,业务问题进行高度抽象的总结。这也是业务能力。
业务背景
是对我们系统的高度总结,在后续的面试准备里面我会好好的描述如何结构化的讲述我们的业务背景问题。
这里的业务背景是从我们系统要处理的核心功能角度出发来描述的。比如:一个电商公司,一定会分交易领域,汇金领域,商家领域,商品领域。每部分就是核心对要做的内容来描述。比如交易领域是围绕一笔电商交易单据的状态流转的串联。支付领域是面向用户支付资产转移等等。这些简单的解释一下核心职责。核心职责也一定会和架构核心定位相关。
业务问题
我一直觉得,架构最终目标还是解决问题的。否则没有”架构“这个概念的。如果只写一个hello word那不会有这些问题。所以要正确的认识和描述,我们的业务具体发生了什么变化,我们的业务边界是否发生了扩展,我们是否增加了一些业务场景。而这些变化,对我们的系统造成了什么问题,我们怎么进行解决的。就体现了我们的架构能力。
业务发展判断(前瞻性)
首先,前瞻性以及基于前瞻性判断的架构设计,一定是可考察的。可考察就意味着一定是有方法的。是有“套路的”。否则根本没办法做出一个面向未来的架构,只能凭运气或者架构演进&维持。另外,需要大家明白一个事情:业务sense,业务前瞻性,最终还是要为架构服务的(或许后面的战略思维是不一样的)。我从下到上分几个方面来说:
架构演进,扩展性
这是框架和架构设计部分。这么多年了spring的IOC本质发生变化了吗?没有。为什么?
因为是基于我们核心架构定位(DI,控制翻转等)出发来定义的。这样本质不变,主体结构就不变,发展就是横向以及纵向发展的。
横向:会有更多的平台产品,业务场景出现,但是关联关系不变。
纵向:会有更多的前后功能延伸出现,但是本质不变(比如spring做了很多的cloud)
网状:关系变化,所以我们建议把“独立”作为核心架构原子概念,这样关系就是另外的一个概念(半文链接理论)。
这样整体框架和核心架构定位上,是不会发生变化的。
业务演进
业务演进,一定还是符合互联网扩展形式的。如果我们不是做商业模式的扩展。那么一定是原有商业模式的商业效率扩展。比如,淘宝并没有更改交易的本质,营销也是类似于传统的吆喝。场地费其实就是地皮寻租的概念。
架构师往往没有到战略视角和洞察的阶段,我们需要的是在特定的业务领域下,判断未来的发展方式。所以就扩展就行,抽象定义好业务的本质,然后结合业务发展阶段进行扩展。比如我之前做的结算架构,就可以按照横向扩展演进的方式来进行。
为什么?
因为“结算”的概念和商业资金链路,很早就有了。支付宝也只是把这些内容搬到线上,然后搬到我们的收单支付配套上。所以围绕商家,供应链,供货商,资金分账,资金链路管理关系,就一定是未来的架构演进方向。因为现实社会中,别的企业用OA或者ERP这样的系统就在做这个事情。那么没道理支付宝内部的结算域会有根本的变化。
这里其实有个抽象,类比的一个方法,依赖我们的视野。比如我们做一个社区架构或者业务方向判断。
整个互联网社区,从最早的BBS-天涯-贴吧-校内-微博-知乎-抖音-小红书。等等。可以抽象定义出来不同的模式和不同的内容载体(视频,文字,图片)。然后传播从以前的单点-广播-网状-核心KOL。但是想想,和最早以前人们下班了之后,搬起来小板凳村口唠嗑。没什么本质的区别。业务演进部分,最终就是回归到:架构延续这个命题上的。
基于上面我的解释,其实就有很好的一个方法来做:架构定位(隐喻)或者说明灯这个方法。因为业务本质是不会发生变化的,所以我们围绕架构定位设定的核心领域模型,就不会发生根本的变化。除非我们的领域发生变化了
这里主要讲在设计部分体现的能力,如果一个架构师在面试过程中最重要的地方,我觉得就是技术性。而这个技术性,就是我们用技术方案来解决架构问题的一种描述。
架构能力,展开说我可以说几十篇文章。所以我直接给一个设计方法论。相信通过我上面对于认知的描述,大家也理解什么叫方法论。
下面是我之前做的一个架构方案的目录。我觉得目录就很好的体现了方法这个词,因为无论什么架构方案。都可以按照一定的目录结构来写。
方法论
我这里说的方法论,就是我们做一个系统的架构方案需要经过的一些步骤,我们具体的产出物。无论是什么架构,都可以按照一定的结构和维度进行分析和拆分,这种通用的方法,就是方法论部分。
方法论+业务能力,就是某个领域,某个功能架构能力的体现。
我这里介绍我的常用方法:架构定位(隐喻),业务架构,应用架构。
我所做的所有架构工作,基本都是上面的三个事情。每一部分都有具体的产出,结合不同的业务场景我们都要运用不同的方法。但是就像我在认知里面说的一样,架构的工作也应该是分维度和步骤的。
下面我详细的介绍每一部分。
架构定位
架构定位是核心架构职责,架构上下边界的高度抽象定义。用一种大家都觉得”理应如此“的方式来提出。和业务概念高度相似。不同的是架构定位还包括功能部分。比如:
交易系统:围绕一笔商品交易的单据,进行不同状态的流转和业务参与者关系的流程组装与驱动。
支付系统:基于用户有价资产偿付。
商品系统:围绕商业活动中,对于物的属性定义与管控。
账务核心:围绕资产管理与资产流转驱动。
等等,我举的例子不一定对,但是大家都会觉得有一点道理,有一点抽象,描述了是什么和做什么。如果感觉对,又不对,那么我们的架构定位可能就设定对了。
此外,我还想介绍一下我的一个理论:架构隐喻
我把这种方法叫做明灯。明灯不是方向,不是目标,不是我们的实施路径。但是就像黑暗之中的莹莹灯火,指明了我们的方向,照亮了我们的目标,牵引着我们的道路。这种”牵引“就是明灯所带来的核心结果,他解决了我们的架构分层问题,平台产品问题,架构延续问题。而xp:极限编程,这本书里面的:架构隐喻。我感觉就是明灯的一种具象化。用一种具象的概念让大家理解我们架构的”感觉“。比如:我们都知道什么是电商里面的交易。那么架构隐喻就可以是:一手交钱,一手交货。
架构定位的作用是巨大的。它指引着我们进行架构方案的设计,也帮助我们做架构协同,架构宣讲,架构延续等等内容。同时在一些具象化的内容也直接帮助着我们,比如核心平台产品是不可能超过架构定位的。在很多非常复杂的架构方案里面,对架构定位可能就讨论一个多月。同时,如果没有进行这一步,架构方案在进行到某个程度的时候也一定会失败。比如有的域进行架构升级,上来就分析业务场景,从来没说要升级什么。然后直到最新方案。才隐约提出一个架构定位。而从这个时候开始,架构升级才艰难的进行了下去,但是围绕分层,又出现了很多问题,比如分了7层,仍然在业务推演上有问题。
业务架构
这里的业务架构,主要是描述我们怎么设计业务功能的。因为只有划分好了功能,我们才能达到代码复用。才能隔离风险,提高研发效能,解决复杂业务场景落地等等等的问题。
业务架构,就是描述系统的业务功能与职责。举例来说,业务架构就是描述我们具有哪些职责和功能,我们怎么和上下游分割划分(L0)。比如交易系统划分业务架构:
对上:提供下单,支付,确认收货,评论 等业务阶段暴露
核心:交易单据,状态流程,业务组件串联
对下业务功能:创建交易,支付交易,库存扣减,安全校验等等
标准的方法中我采用的是三层架构。注意这个可是和Controller,Service,Dao完全不同的概念。这三层是指:业务场景定义,平台产品定义,平台服务能力定义。
写到这里,我发现一个问题,我主要围绕一个非常复杂的背景:平台架构,在描述我的方法。也有可能有的同学没有处理过这样复杂的问题,或者没有这部分的经验。首先,方法一定是相通的,能理解复杂的系统,没道理做不好trade off,没道理做不好简单系统的业务划分。此外,这是不是说明,我们做更多的事情,也更好的帮助我们自己成长。所以这并不是PUA的一种。
业务场景是描述整个业务身份,我们的系统要处理哪些”业务“。然后这些业务是按照什么维度进行划分的。业务场景定义最难的地方在于”垂直拆分“的问题。即:为什么业务A和业务B是两个业务。为什么不是一个业务。什么时候新增业务场景,如果一个业务A和业务B只有100行左右的代码不同,怎么办。等等这些问题。
平台产品是描述”非业务相关,业务通用“的。某个特定的平台型功能聚合。提供标准的扩展和标准的解决方案。比如”担保交易“这是一个非常典型的平台产品,淘宝,天猫都是基于这个交易链路来做的。
平台产品最难解决的是”横向拆分“问题。比如某个功能是不是平台产品功能,还是只属于某几个业务的功能。
平台服务能力是描述完全隔离的,独立提供功能的代码。注意一定是隔离的,并且独立的。这是平台服务的基本特性。比如一个资金转移服务,安全校验服务等等。平台服务能力最难解决的也是垂直问题。就是什么是独立服务,什么是服务配套。
这里可以展开说很多内容,比如按照接口集成维度划分场景,然后我们围绕领域模型定义产品流程,这样可以跨接口场景复用。然后我们的流程是基于领域模型DDD的。
下游核心服务,就是我们的DB(这也是洋葱圈架构标准定义)。所以我们把DB的操作定义成原子服务。这是一个非常简单场景。但是如果我们是这样思考和设计的。那么我相信这就是一个架构师的能力标准。
业务架构还包括一些核心内容,比如:核心领域模型,核心业务流程等内容。这些都是在具体实践中。我们进行一些关键设计。
应用架构
应用架构,就是解决我们业务架构然后代码落地的问题。就是如何用代码实现我们的业务架构中的业务功能,如何组织我们的代码,如何按照模块进行划分。
比如我理解的典型洋葱圈架构,就是一种应用架构方法论。因为这里涉及到了DB。DB是具体技术的概念。在业务架构中是不会出现具体技术的。比如”支付“是业务功能。这个功能甚至都不会是java来实现的。下游可能是一个系统。这里就是区分。
应用架构是包含关键技术架构的。因为应用架构关注与“实现”层面的事情。
我的架构经验比较复杂,这里不详细展开了。主要是两个框架:DSL框架和扩展引擎框架。我这里就介绍一种方案:基于不同业务场景扩展参数组合+workflow复用的架构。
这是一种非常简单的代码组织方式,大部分系统都是用这种架构方式的。核心就是基于功能action。然后业务中用到五个功能,就把五个action串联起来就行了。
架构延续
在业务发展判断(前瞻性)里面,我描述了我们的业务能力,业务sense怎么提升。但是,我想说明的是,作为架构师,我们的业务能力,最终还是为架构服务的。当然了,继续往下个阶段,就不一定了,因为解决问题的手段不仅仅是“架构”这一个手段了。
基于我们对业务发展的判断,我们框架部分的灵活扩展设计。是否就能保证我们的架构核心延续下去呢?其实我觉得还不够。
因为架构延续,不仅仅是能完成业务功能。同时还需要保证我们的核心领域模型,架构分层,核心架构概念,技术风险,研发效能。这些部分能够持续不断的演进,不说变好,至少没有那么快的变坏。相信这个问题都有感觉,因为一个5年左右的系统,代码经常被称之为“屎山”。我们经常戏称我们的工作就是屎上雕花。那么怎么能够做到架构延续呢?
我从一个比较感性的角度来说明这个问题:架构隐喻
这是我在XP极限编程里面学习到的一个概念,里面很多内容我并不能赞同。但是这个核心方法我还是保留了下来,然后结合我的工作进一步的解释和落地。
另外,我是一个绝对的“英雄主义史观“。在我看来,所有的制度,流程,业务设计,架构设计。最终都取决于人这个因素。我们没办法很好的限制人,我们只能按照”感性“的维度,去引导大家。架构隐喻,就是一种具象化的,感性化的。让相关同学都能理解和明白相关架构定位和发展方向的”感觉“。依托这种感觉,我会不断的进行我们的架构迭代。朝着我们的目标方向发展。好的架构一定是延续的。
下面我还会讲一些具体的方法和拆分的维度,但是这个是属于顶层概念。一定是基于”架构隐喻“才能让大家保证执行不出差的。否则无论是什么方法,只要提出了,都还需要解答另外一个问题:如何保证别人落地的过程中和你想的不出现gap?
在具体的架构延续方法上,还会分几个部分(上面也说了)。
本文系作者在时代Java发表,未经许可,不得转载。
如有侵权,请联系nowjava@qq.com删除。