饭饭TXT > 学习管理 > 《技术领导力:程序员如何才能带团队(出版书)》作者:周明耀【完结】 > 技术领导力:程序员如何才能带团队 (周明耀).txt

第5章

作者:周明耀 当前章节:15663 字 更新时间:2026-6-23 09:06

系统架构

软件技术学习到一定的程度后,会面对软件架构师这一门槛。一直以来,在软件行业内部,对于什么是架构有很多的争论,每个人都有自己的理解,甚至很多架构师一说架构,就开始谈论应用架构、硬件架构、数据架构等。而事实上,架构在软件发明前就早已存在了。由于众说纷纭,莫衷一是,于是大家产生了很多困惑。软件并不是虚无缥缈的东西,它和现实生活是紧密相关的。业务和架构都是处理人的问题,只有和人的问题联系在一起,才是真正的系统架构设计。

本章主要介绍和解决以下问题:

·什么是系统架构、软件架构师,他们的工作内容、责任、思路是什么。

·系统架构案例介绍、常用工具介绍。

·系统架构能力培养。

·架构过程常见问题分析。

·其他与系统架构相关知识分享。

5.1

系统架构工作

5.1.1 软件架构概念

1.什么是软件架构

谈到软件架构,很多人会认为软件架构就是一堆框架的组合,其实不对,软件架构本身是对于软件实体组织形式的阐述,使用框架的意义是快速完成软件架构设计,而不是取代软件架构设计,两者本质上是不一样的,它们的关系更像是设计图纸和所使用的原材料的关系。软件架构就是通过对软件生命周期的拆分,在符合业务架构的前提下,达到软件本身访问增长目的的方式。这个增长需要软件开发的增长,也需要软件运行的增长,进而支撑业务的增长。

软件架构离不开软件开发团队的组织架构,这个组织架构是软件开发生命周期和软件运行生命周期的执行者。离开了组织架构,任何软件架构设计都是纸上谈兵,因为架构的核心生命周期就是架构的执行。

2.工作分工

软件开发工作的分工是日积月累之后自然形成的,20世纪50年代软件开发工作刚兴起时,和现在相比,软件公司内部的分工是存在很大差异的。由于各种外部因素及其他约束,造成软件开发需要分工,自然而然就会分出不同的角色做不同阶段的事情,这就是需求决定最终概念。分工之后,有些人收集并汇总需求,有些人编写代码,有些人执行测试等。这样分工比较容易,招人也容易,切分出来的工作门槛也会比较低。分工清晰后,会给创业公司带来一定的麻烦,因为招聘岗位太多,造成薪资负担很重,希望能够招到牛人,什么都能一人干完。所以现在又开始流行全栈工程师,这类人能够胜任从产品到技术到测试所有工作,其实这是自然架构的一种倒退,必然会遇到问题。

3.什么是组织架构

前面提到了组织架构。软件架构若把软件看成虚拟的人,那软件架构实际上就是虚拟人的组织架构。架构拆分的原则,首先来源于业务自身的组织架构,软件架构要保持和业务组织架构的匹配关系。其实也只有软件架构和组织架构保持匹配,软件架构设计才能真正落地,软件架构师才能真正拥有工作的成就感、归属感。其次来源于软件开发团队自身的组织架构,没有组织架构的软件团队是不存在的,即便是现在流行的扁平化组织架构管理体系,组织架构依然是存在的,只是层级被压缩到较少程度而已。最后来源于用户的流量对软件本身的冲击,这其实是软件模拟人类行为的一种方式,一个人使用和成千上万人同时使用的业务场景都属于正常情况。如果软件开发团队的组织架构和业务的组织架构能一直保持高度一致,内部损耗就会达到最小,软件的架构会更简单,软件架构有效落地的可能性也会大幅度增加,软件模拟人的行为也会更加真实。

4.进化

很多人认为软件架构是进化或演化出来的。进化的含义是由一个物种变成另外一个物种,是本质的变化,比如物种由水生进化到了陆生等。

回到技术,架构追求的实际上是业务不断长大:通过对业务生命周期的拆分,突出并精简业务核心生命周期,弱化非核心生命周期,达到不同生命周期可以在空间和时间上并行,便于不同的人同时开展工作,提升业务人员单位时间内的产出。比如说我们设计的分布式存储系统,理论上通过增加机器就能无限提升存储能力和并发能力,也就节省了核心生命周期的开发时间,提升了开发人员的开发效率。

业务相当于基因,而架构呈树状延展则相当于细胞的分裂。就好比每一个人,都是从一个细胞逐渐分裂出来的。一个细胞最终分裂成什么,起决定作用的不是分裂本身,而是它的基因。基因决定了细胞最终会分裂生长成什么样的一个生命。比如一棵树从种子长成小树苗,再长成参天大树,这不叫进化,这叫生长。长成什么树是由树的基因决定的,不是架构。因为不管怎么拆分,业务的目标,也就是基因没有任何变化。如果一个企业的业务由制造商变成电商,这个时候业务就发生进化了。因为基因变了,业务已经完全不一样了,整棵架构树的含义就变了。该企业的软件架构就需要重新设计,而不能在原有的架构上修改,也就不存在架构的进化。

严格来说,只有业务才会进化,架构是支撑业务长大的。业务的核心生命周期相当于架构树的主干,主干没有变化,则说明没有变成一棵不同品种的树,因此只有架构的拆分不能叫作进化。随着架构拆分得越来越细,“树”长得越来越大,并行度越来越高,业务也就长得越来越大。

5.1.2 软件架构师岗位

1.为什么需要架构师?

我们需要有人能够回答这些问题:

·我们这个系统的边界是什么?

·我们系统由哪几部分组成?

·各模块之间怎么通信?

·选择什么样的基础技术?

·为什么要这样选择?

·技术方案未来会遭遇哪些坑?

·我们的备选方案有哪些?

·从技术角度这个应用将来如何持续扩展功能?

这一系列的问题归咎为规划,因为做所有事情都需要规划,对于研发流程而言,规划阶段就是我们的总体设计阶段。一个复杂的软件系统更需要规划,如果没有规划可能连一行代码都很难写出来(当然会有人持反对意见,因为他们用一堆框架搭起一个系统,虽然没有设计环节,但是貌似还能正常运行。但是别高兴得太早,当你遇到业务急速扩充,系统出现各种异常情况时,你会被拖垮)。这个问题从一个程序员的角度去思考,其实也是一样的,你在写一个上万行的代码时难道是想到哪里就写到哪里吗?

2.职责

架构师要解决的问题都是人的问题。更进一步,架构师要解决的问题基本都是别人的问题。别人的问题解决了,架构师自己的问题才能解决。任何找上架构师的问题,基本都不是真正的问题。为什么呢?因为如果是真正的问题,提问题的人肯定能够自己解决,不需要找架构师。因此,架构师都要有觉悟,理解并发现问题永远比解决问题更加重要,遇到问题首先进行分析,不要急于解决问题。

3.谁是架构师?

很多公司设了软件架构师的职位,主要职责是做出架构设计,他们具备一定的影响力,但并不具备调动组织架构的权利。这样的职位往往不能发挥架构师的作用,有时候还会起反作用。软件架构师必须是一个组织的领导人,有权利调整这个组织的架构,才能够更好地发挥架构师的作用,才能够把软件开发生命周期、软件运行生命周期和业务生命周期的拆分落实执行。软件开发团队的组织领导人其实都是架构师,只是没有这个头衔而已,真正的架构师不一定需要具备架构师的头衔。

一个开发团队的领导,如果不能在架构方面给出意见,那就不能在整个设计环节给出自己的观点或者对团队进行指导,也就可能会在整个软件开发流程中脱节,进而丢失自己的技术领导力,也就做不成技术管理者。一名优秀的技术管理者,技术在前,管理在后,并不是说两者有太大的轻重差异,而是你需要花费70%的时间在技术上,只能花30%的时间在管理上,但是你需要用这30%的时间做完100%的管理工作。技术、管理,一样都不能差,架构能力也是一样。因此,一个好的领导就是一个很好的架构师。我相信,在架构师的领导下,这个组织一定是健康向上的。

当然,也可以有另一种方式来允许架构师角色独立存在。架构师可以由专门的个人或者团队组成,他们承担新技术、框架的调研工作,负责对用户提出的需求进行评估,采用新的技术做出产品原型、输出技术调研报告,供产品部门在技术选型和技术架构选型时参考,这也可以体现架构师的水平和贡献。

5.1.3 软件架构师的责任

一个软件往往因为某个业务需求而产生,后续不断更新、修改,逐渐变异、长大,当该软件不再被需要(因为业务的消失)或有更好的软件来替代时就会被废弃,完成使命而消亡。软件的整个生命周期也会发生切分,从而形成两个子生命周期,即软件开发生命周期和软件运行生命周期。

作为软件架构师,必须时刻把对软件生命周期和业务生命周期的识别放在第一位。软件生命周期的核心在于软件运行生命周期,以及围绕软件运行生命周期的拆分和组织,业务生命周期的核心在于围绕业务核心生命周期的拆分和组织。

对于软件生命周期,必须要深入思考软件开发生命周期和软件运行生命周期。在这个基础上,要根据业务的情况合理地进行软件开发生命周期的架构拆分和软件运行生命周期的架构拆分。软件开发的拆分和软件运行的拆分的目标都是支持业务流量的增长。

在代码层面,要对业务代码和访问代码做好架构拆分,要确保业务代码符合业务的生命周期,使得业务生命周期活动的结果积累在生命周期的主体上,也就是要具有内聚性,避免散落到访问代码中。这样软件的拆分就不会有太大的问题。

架构在软件发明前就已经存在很久了,我们应该多向大自然、艺术界、建筑界学习架构的概念,因为软件并不是虚无缥缈的事物,它和我们的现实生活是紧密相关的,它来源于生活,最终又通过软件服务回到生活。企业软件架构的设计不仅要注重某一个系统功能,更需要给企业一个可进化的、可持续发展的、不断创新的平台。

团队达到一定规模之后,技术管理者(也可能有独立架构师存在)的大部公时间就需要花费在思考上面了,当然也可以继续编程,但是编程的目的是验证架构是否合理,所以不要受是否需要编程这一思维的束缚。如果设计得不好,那么团队就会走很多弯路,如果想要设计得很好,你必须自己或者带领团队做很多的测试、预研工作。作为架构师,你需要多多思考,很多时候因为很忙、事情很多,导致真正思考时间太少了。

5.1.4 软件架构思路

1.前提条件

软件架构师需要学会拆分生命周期,并且应该指导形成组织架构来落实架构的执行,需要平衡别人的利益,甚至去调整别人的利益。对于软件架构师而言,是无法直接去调整业务利益的,只能够在某种程度上去影响。毕竟软件架构师是为业务服务的,而不是主导业务的业务架构师。

2.应对增长

架构的目的就是为了增长,而要达到增长,就必须让很多人合作为完成同一件事情,并且使他们做的事情合并起来达到1+1>2的效果,最少也要达到1+1=2的效果。

架构师应该把需要增长的业务了解清楚,挖掘出核心生命周期,并确定核心生命周期的主体。换句话说架构师要发现问题的主体,并确定核心问题。在确定业务核心生命周期以及核心生命周期的主体之后,架构师还需要对业务核心生命周期进行分析,剥离出非核心生命周期,并根据当前人员的状况,合理地分配非核心生命周期的权责。这样不同的人就可以并行且互不影响地做不同的事情,最后根据核心生命周期,把他们的工作成果组合起来,达到1+1>2的效果。

架构师工作的反馈应该由问题的解决效果,也就是增长的效果来决定。如果以很少的资源达到了很大的业务增长,那肯定是一位好的架构师,公司所节省下来的资源应该回馈给架构师,从而形成正向反馈。从这一点来看,架构师要对总体增长的效果负责。

5.1.5 软件架构落地

只要问题明确,寻找技术并组合来实现架构的拆分并不是难事。如果架构师能够深入理解技术背后的驱动力,了解技术是如何实现的,则能够做出更合适的判断和选择,这就是所谓的“接地气”。所以架构师在做好架构拆分后,会形成不同的生命周期。针对不同的生命周期,要选择不同的技术来进行支撑,再把不同的生命周期分工交给不同类型的软件工程师去实现。这就是架构师和技术人员的分工配合,架构师负责拆分生命周期,技术人员负责实现生命周期。

组织架构是树状的,上层节点要求下层执行,所以执行才是架构的核心。同时权力也要下放,只有权力下放了,下层节点才能够更好地执行。只有架构师拥有组织架构的权利,才能确保架构拆分的落地。架构师思考技术时更多地需要考虑技术对生命周期拆分的支撑,以及不同技术实现拆分落地的成本和收益。以最少的成本达到更高的增长,这是每个架构师追求的目标,所以架构既不是技术的对立面,也不是技术的同一面,两者是相辅相成的关系。

很多软件架构设计都有相通性。我们来看看HBase的RegionServer设计方式。在HBase内部,所有的用户数据以及元数据的请求经过Region的定位后,最终会落在RegionServer上,并由RegionServer实现数据的读写操作。RegionServer是HBase集群运行在每个工作节点上的服务。它是整个HBase系统的关键所在,一方面它维护了Region的状态,提供了对于Region的管理和服务;另一方面,它与Master交互,上传Region的负载信息,参与Master的分布式协调管理。HBase系统架构如下页图所示。

HRegionServer与HMaster以及Client之间采用RPC协议进行通信。HRegion-Server向HMaster定期汇报节点的负载状况,包括RS内存使用状态、在线状态的Region等信息,在该过程中HRegionServer扮演了RPC客户端的角色,而HMaster扮演了RPC服务器端的角色。HRegionServer内置的RpcServer实现了数据更新、读取、删除的操作,以及Region涉及的Flush、Compaction、Open、Close、Load文件等功能性操作。

Region是HBase数据存储和管理的基本单位。HBase使用RowKey将表水平切割成多个HRegion,从HMaster的角度,每个HRegion都记录了它的StartKey和EndKey(第一个HRegion的StartKey为空,最后一个HRegion的EndKey为空),由于RowKey是排序的,因而Client可以通过HMaster快速定位每个RowKey在哪个HRegion中。HRegion由HMaster分配到相应的HRegionServer中,然后由HRegionServer负责HRegion的启动和管理,和Client的通信,负责数据的读(使用HDFS)。每个HRegionServer可以同时管理1000个左右的HRegion。

再来看看软件系统架构方面的分区设计。以任务调度为例,假设我们有一个中心调度服务,那么当数据量不断增多时,这个中心调度服务一定会遇到性能瓶颈,因为所有的请求都会最终指向它。为了解决这个性能瓶颈,我们可以将任务调度拆分为多个服务,多个服务都可以处理任务调度工作。那么问题来了,每个任务调度服务处理的源数据是否需要完全一致?根据华为公司发布的专利发明显示,他们对于每一个任务调度服务由数据来源区分操作,即按照任务调度数量对源数据进行划分,比如3个任务调度服务,源数据按照行号对3取余的方式进行划分,如果运行了一段时间之后,任务调度服务出现了数量上的增减,那么这个取余划分需要重新进行,要按照那个时候的任务调度数量重新划分区间。

上面举的两个示例的实现原理是完全一致的,架构设计也是类似的,只是最终解决的业务问题有所不同。

5.1.6 有用的工具

在软件开发流程的各阶段中,IT架构师都必须不断地评估自己的设计,以确保它能够满足需求。如果需求发生了更改,这在现实世界中是非常普遍的,最终产品的计划和时间安排都必须随之进行相应的更新。使用一些优秀的软件工具,可以使这项工作变得更加容易。让我们来看看在这个周期的各个阶段可以使用的一些工具。

1.IBM Rational RequisitePro

需求分析是系统设计过程中的一个重要部分,系统中所有的利益相关者都通过这项工作来确定客户及软件应用程序自身的要求和需求,这是一个漫长的过程,并且会影响最终产品,所以IT架构师必须确保不遗漏任何一个方面。需求分析和管理工具必须具备完成所有这些任务所需的功能。

IBM Rational RequisitePro解决方案是针对项目组(想要改进项目目标的交流、增强协作开发、减少项目风险,以及在部署之前提高应用程序质量的项目组)的需求和用例进行管理的工具。

Rational RequisitePro提供的功能包括:

·高级Microsoft Word集成。Word是IT架构师用来为系统收集需求的最常用工具。RequisitePro并没有阻止用户使用Word,相反,它能够很好地与Word集成在一起。用户在Word中处理并保存收集到的数据,而在后台,RequisitePro将数据保存到了中央数据库中。

·可靠的数据库基础结构,并支持大量的行业标准、企业数据库,如IBM DB2、Oracle和Microsoft SQL Server。

·创建并比较项目基准的能力。

·详细的更改影响分析,并提供了审核跟踪和电子邮件通知。

·深入的可跟踪性和覆盖率分析。

·可靠的、灵活的、内置的报告系统。

·为分布式团队提供Web访问的模块。

·用户定义需求类型的能力。

·大量可配置的项目和文档模板。

2.ArgoUML

系统设计和体系结构设计工具可以在很大程度上帮助IT架构师完成可靠的和高质量的软件。ArgoUML是一种用于系统设计和架构设计的、优秀的开放源代码工具。它提供了一些有趣的特性,这些特性使得它成为市场中最流行的UML工具之一。

ArgoUML具有以下特征:

·基于开放标准(XMI、SVG和PGML)。

·完全用Java语言编写,所以它是平台独立的。

·开放源代码,这使得它易于扩展,甚至可以根据具体需求对它进行自定义。

·基于UML1.4。

3.Notability

Notability是App Store编辑推荐的应用,作用就是可以手写笔记并且支持很多工具,比如可以插入图片、音频、便签等。

笔记APP使用频率还是比较高的,用Notabiling配合Apple Pencil手写字体很精确,几乎没有延时,很接近在纸上写字的感觉,不过不支持识别压力和倾斜。

4.Mindmanager

MindManager的官方网站是http://www.mindjet.com。MindManager是一个创造、管理和交流思想的通用标准,其可视化的绘图软件有着直观、友好的用户界面和丰富的功能,这将帮助用户有序地组织思维、资源和项目进程。

MindManager也是一个易于使用的项目管理软件,能很好地提高项目组的工作效率和小组成员之间的协作性。它作为一个组织资源和管理项目的工具,可从脑图的核心分支派生出各种关联的想法和信息。

正确安装好MindManager之后,打开软件,会发现MindManager使用的是和Office2007同样的Ribbon风格的界面。除了界面上相像之外,MindManager和Office的互操作性非常好,使用方法极其贴近Office。下图所示是MindManager的界面。

5.Enterprise Architect

Enterprise Architect(简称EA)和Rose是软件开发过程中常用来进行UML建模的工具。EA使用的比较广泛,能够绘制用例图、类图、数据库模型、时序图、协作图、状态图等常用图形。

以一个user表为例,下图框中的各项均是要完善的。设置Alias(别名)后,我们看到的就是中文。Database的选择涉及后面新建字段后的数据类型以及和数据库的交互。填写Notes后,数据库中也会出现注释。Author标识设计对象。

设计外键关联如下图所示。

5.2

系统架构能力培养

5.2.1 提升驱动力

一个技术团队必须有自己的技术定位,也可以说是有技术愿景,只有这样才能留住对技术很有热情的工程师。明确了技术定位后,我们就需要制定团队技术能力的提升计划,特别是在系统架构能力的提升方面。而提升这些能力,又都需要有实际推动力。一般来说,推动力可能来自以下三个方面:

·客户实际需求:例如客户需要你设计一个能够支撑1万路并发的系统,而通过测试发现现在的设计只能支持1000路,那当然需要技术上改进,可能是局部改进,也可能是重构。王坚博士在多个场合都曾经讲过,“双11是过去几年阿里技术发展的强大驱动力。”这就说明了业务需求是技术推动力。技术真正发挥价值的地方,一定是对用户产生影响的时候。如果做不到这点,一旦遇到人力紧张的情况,这样的技术改造就会被放弃。

·测试数据:例如进行性能测试时发现一个数据很可疑,为什么操作数据库花了这么多时间?接着就是讨论可能是编码问题,可能是设计的算法问题,也可能是业务逻辑设计造成的。业务发展到一定阶段都会遇到“飞机在全速飞行的前提下换引擎”的问题,是在现有框架下对两个业务分别改造,还是推翻现有模式建立一个技术共享的新模式?这不仅是对架构能力的挑战,更是对团队的协同作战能力的考验。

·外部公司技术资料:例如参加顶尖科技公司主办的技术大会、顶尖科技媒体主办的技术交流会,或者阅读技术大牛公司或者个人出版的图书、IEEE论文等,这些都能给技术管理者一些灵感,帮助他们创造更好的技术产品。多了解外部的技术发展状态,对于明确或纠正团队的技术发展方向很有利。

技术团队需要不断地前进,这些推动力实际上也是人的自我愿景设置,只有不断给自己设置愿景的人,才会不断地尝试提高自己的技术能力、设计能力。

5.2.2 步步为营

“不应该一开始就承担大项目。应该先从小的、无关紧要的项目入手,并且不要去希望该项目能够做大。否则,你就会做出过度的设计,并且通常会把项目的重要性看得比它实际的要高。或者更糟的是,你会被预想的不切实际的项目规模吓得望而却步。因此,要从小规模的项目做起,把细节考虑周全,不要盲目憧憬过大的愿景或虚幻的设计。如果项目不能解决一些相当紧急的需求,那么它十有八九是被过度设计了”。这是林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds)的观点。他是著名的电脑程序员、黑客,Linux内核的发明人及该计划的合作者。

我们以一个架构的实际变化为例来进行说明。一个电商网站的发展过程反映了网站十几年的发展历程,当然也可以理解为一步步构建起一个网站系统架构的过程。虽然我们希望网站一开始就能有一个最好的架构,但事物是在发展中不断前进的,网站架构也会随着业务的扩大、用户的需求不断完善,在这个过程中设计能力也是一步步在提升的。其实几年前我还不知道真正的设计,因为之前的工作经历分工太明确,每个人只管着自己手头的工作,大型系统的架构设计工作多由别人把控,我们这些人只是做些实现的工作,现在看来就是小工。直到加入了现在的公司,遇到了一位合适的领导,我的系统架构思维瞬间被打开,能力也伴随着思维的不断拓展而快速上升。

回到技术,系统架构也是这样一步步完善的,以刚才所说的构建一个网站为例,刚开始时可能只是在托管服务器上部署自己的程序(很有可能是单机程序),因为流量不高,能够支撑就够了。随着站点运营力度的不断提升,这个时候由于网站具备了一定的特色,吸引了部分人访问,系统的压力越来越高,响应速度越来越慢,而这个时候比较明显的是数据库和应用互相影响,应用出问题了,数据库也很容易出现问题,而数据库出问题的时候,应用也容易出问题。于是进入了第一个阶段,将应用和数据库从物理上分离,变成两台机器,这个时候技术上没有什么新的要求,但确实起效果了,系统又恢复到以前的响应速度,并且可以支撑住更高的流量。

随着访问的人越来越多,响应速度又开始变慢了,查找原因,发现是访问数据库的操作太多,导致数据连接竞争激烈,所以响应变慢,于是进入了第二个阶段。数据库连接又不能开太多,否则数据库机器压力会很高,因此考虑采用缓存机制来减少数据库连接资源的竞争和对数据库读取的压力。这个时候也许首先会选择采用squid等类似的机制来将系统中相对静态的页面(例如一两天才会有更新的页面)进行缓存(当然,也可以采用将页面静态化的方案),这样程序上可以不做修改,就能够很好地减少对WebServer的压力以及减少数据库连接资源的竞争。

增加了squid实现缓存后,系统整体速度确实是提升了,WebServer的压力也开始下降了,但是随着访问量的增加,系统又开始变慢了,于是进入第三个阶段。在尝到了squid之类的动态缓存带来的好处后,我们开始想能不能将现在那些动态页面里相对静态的部分也缓存起来呢?因此考虑采用类似ESI之类的页面片段缓存策略,于是开始采用ESI来做动态页面中相对静态的片段部分的缓存。

采用ESI之类的技术再次提高了系统的缓存效果后,系统的压力确实进一步降低了,但同样,随着访问量的增加,系统又开始变慢,于是进入第四个阶段。经过调查,可能会发现系统中存在一些重复获取数据信息的地方,就像获取用户信息等,这个时候开始考虑是不是可以将这些数据信息也缓存起来,于是将这些数据缓存到本地内存,改变完毕后,完全符合预期,系统的响应速度又恢复了,数据库的压力也再度降低了不少。

好景不长,随着系统访问量的再度增加,Webserver机器的压力在高峰期会陡增,这个时候开始考虑增加一台Webserver,进入第五个阶段,这也是为了同时解决可用性的问题,避免单台的Webserver宕机没法使用的情况。在做了这些考虑后,决定增加一台Webserver,但同时会碰到一些问题:

1)如何将访问分配到这两台机器上?这个时候通常会考虑的方案是Apache自带的负载均衡方案,或LVS这类的软件负载均衡方案。

2)如何保持状态信息的同步,例如用户session等?这个时候会考虑的方案有写入数据库、写入存储、cookie或同步session信息等机制。

3)如何保持数据缓存信息的同步,例如之前缓存的用户数据等?这个时候通常会考虑的机制有缓存同步或分布式缓存。

4)如何让上传文件这些类似的功能继续正常?这个时候通常会考虑的机制是使用共享文件系统或存储等。

在解决了这些问题后,终于把Webserver增加到两台,系统终于又恢复到了以往的速度。

享受了一段时间的系统访问快速响应的幸福后,系统又开始变慢了,这次又是什么状况呢?经过调查,发现数据库写入、更新的这些操作的部分数据库连接的资源竞争非常激烈,导致了系统变慢。这下怎么办呢?进入第六个阶段,此时可选的方案有数据库集群和分库策略,但集群方面有些数据库支持的并不是很好,因此分库是采用比较普遍的策略,分库也就意味着要对原有程序进行修改。修改实现分库后,目标达到了,系统速度甚至比以前还快了。

随着系统的不断运行,数据量开始大幅度增长,这个时候发现分库后查询仍然会有些慢,于是按照分库的思想开始做分表的工作,进入第七个阶段。于是萌生出能否增加一个通用的框架来实现分库分表的数据访问的想法,此时不可避免地会需要对程序进行一些修改,也许在这个时候就会发现自己要关心分库分表的规则等,这个演变的过程相对而言需要花费较长的时间。当然,也有可能这个通用的框架会等到分表做完后才开始做。同时,在这个阶段可能会发现之前的缓存同步方案出现问题,因为数据量太大,导致现在不太可能将缓存存在本地再进行同步,故需要采用分布式缓存方案。于是,又是一通考察和折磨,终于将大量的数据缓存转移到分布式缓存上了。

在做完分库分表这些工作后,数据库上的压力已经降到一个比较低的点,又开始过着每天看着访问量暴增的幸福生活了。突然有一天,系统的访问又开始有变慢的趋势了,这个时候首先查看数据库,压力一切正常,之后查看Webserver,发现Apache阻塞了很多的请求,而应用服务器处理每个请求也是比较快的,看来是请求数太高需要排队等待,导致响应速度变慢,于是进入第八个阶段。添加一些Webserver服务器,在添加Webserver服务器的过程中,有可能会出现几种挑战:

1)Apache的软负载或LVS软负载等无法承担巨大的Web访问量(请求连接数、网络流量等)的调度,这个时候如果经费允许的话,会采取的方案是购买硬件负载平衡设备,例如F5、Netsclar、Athelon之类的。如果预算不允许,采取的方案是将应用在逻辑上做一定的分类,然后分散到不同的软负载集群中。

2)原有的一些状态信息同步、文件共享等方案可能会出现瓶颈,需要进行改进,也许这个时候需要根据情况编写符合网站业务需求的分布式文件系统等。

在做完这些工作后,开始进入一个看似完美的无限伸缩的时代,当网站流量增加时,应对的解决方案就是不断地添加Webserver。

突然有一天,这个完美的时代也结束了,数据库的噩梦又一次出现在眼前。由于添加的Webserver太多,导致数据库连接的资源还是不够用,而这个时候又已经分库分表了,开始分析数据库的压力状况,可能会发现数据库的读写比很高,这个时候通常会想到采用数据读写分离的方案。当然,这个方案要实现并不容易,另外,可能会发现一些数据存储在数据库上有些浪费,或者说过于占用数据库资源,于是进入第九个阶段。在这个阶段可能会形成的架构演变是实现数据读写分离,同时编写一些更为廉价的存储方案,例如BigTable。

经过上面这个漫长而痛苦的过程,终于是再度迎来了完美的时代,不断地增加Webserver就可以支撑越来越高的访问量了。对于大型网站而言,人气的重要毋庸置疑,随着人气的越来越高,各种各样的功能需求也开始呈爆发性的增长。这个时候突然发现,原来部署在Webserver上的那个web应用已经非常庞大了,当多个团队都开始对其进行改动时,会相当不方便,复用性也相当差,基本是每个团队都做了或多或少重复的事情,而且部署和维护也相当麻烦。因为庞大的应用包在多台机器上,复制、启动都需要耗费不少的时间,出问题的时候也不是很好查。另外一个更糟糕的状况是很有可能某个应用上的一个Bug就会导致全站都不可用。还有其他的例如调优方案不准确(因为机器上部署的应用什么都要做,根本就无法进行针对性的调优)等因素,所以进入第十个阶段。这个阶段我们根据分析结构,开始痛下决心,将系统根据职责进行拆分,于是一个大型的分布式应用就诞生了。通常,这个过程需要耗费相当长的时间,因为会碰到很多的挑战:

1)拆成分布式后需要提供一个高性能、稳定的通信框架,并且需要支持多种不同的通信和远程调用方式。

2)将一个庞大的应用拆分需要耗费很长的时间,需要进行业务的整理和系统依赖关系的控制等。

3)如何运维(依赖管理、运行状况管理、错误追踪、调优、监控和报警等)好这个庞大的分布式应用。

经过这一步,系统的架构基本会进入相对稳定的阶段,同时也能开始采用大量的廉价机器来支撑巨大的访问量和数据量,可以结合这套架构以及这么多次演变过程吸取的经验来采用其他各种各样的方法来支撑起越来越高的访问量。

5.2.3 学习能力

如果你想进步、想要有所成绩,就需要持续学习、终身学习。

个人层面需要不断地输入,学习新的知识,保持对行业、领域内新技术的更新。看论文可以被认为是架构修炼的一种方式,因为很多论文写得比较严谨,也比较系统化,了解一个系统实现的细节对于架构方面的成长很有好处。

有一天我的一位同事找到我:“周工,我看到你出的书了,能不能告诉我怎么提高自己的技术能力?”。我对他说:“你每天7点起床,23点睡觉,中间所有空闲时间都拿来学习、思考、总结技术问题,你就可以提高了。”这不是开玩笑,任何人想要提升自己的专业能力,有效、高效、有针对性地付出时间是最直接、最有效的办法。

架构师是一个充满挑战的职业,知识面的宽窄往往决定着一个架构师的架构能力,你需要阅读大量的技术书籍,但是不要仅限于软件相关的书籍。要经常上技术论坛,一方面可以结交朋友,一方面可以拓展自己的知识面。公司的大小往往决定了所做的项目规模,一般的大项目不太可能直接总包给小公司去做,但这并不妨碍小公司可以分包到大项目的一部分。在做小项目的同时也可以积累丰富的经验。宽广的知识面对于一名出色的架构师来说是必不可少的。也许很多人对架构的理解还停留在设计模式、重构、SOA等软件层面,然而这仅是非常基本的东西,架构师的脑子里不光需要知道让软件如何高效地运行,还需要知道如何去结合网络、存储,甚至一些文件系统的特性,比如GFS、NFS、XFS、NTFS等。而且架构师还需要知道一些编程语言的特性,如C、C++、Java、PHP、Python、Lisp、JS等。现在是一个混合编程的时代,只了解一种语言,即使再精通也会使你在架构系统的时候受到很大的局限。架构师需要对数据库技术有深刻的认识,因为现今是一个信息时代,大量的信息都是需要存储并检索的,数据库设计得不好,将会严重影响系统的性能,而这一点往往会被我们的设计人员忽略,他们只知道遵守那些范式而不会去结合数据的特性来设计数据库。

从一个程序员到架构师是一个很大的变化,架构师需要从大的方面考虑,而不只是考虑这个模块该用哪种设计模式去开发。总的来说,想要成为架构师,需要有耐心,不断学习,拓宽自己的视野,不要局限于自己眼前的项目,多关注开源技术,多关注热门技术社区的新动向。

5.2.4 创新思维

批判性思维是创新过程中最显著的特征,不求一鸣惊人,但求独善其身是程序员队伍中一种比较具有代表性的思想。但我们真正能做到独善其身吗?试想如果现有代码的可维护性很差,任何人都很难在有限的时间内写出高质量代码,最终很可能“随波逐流”。有时我们也会一不小心走到另一个极端,如果留意,我们总能在公司的茶水间里听到员工关于公司缺乏产品创新的批评。批评是有益的,但我们更需要批评过后的冷静思考和实际行动。创新无疑需要批判性思维,但前提是我们能将“批判”与“批判性思维”区别开,批判的目的只是为了达到对某个事物的否定,而批判性思维则是通过否定来寻找更好的做事方法。单纯批判是消极的,而批判性思维是积极的。

对于软件研发团队,定义问题的能力直接影响其需求分析的质量,进而最终决定了产品的质量。一般认为软件工程师参与到需求分析与产品设计的机会并不是很多,他们是接收来自用户或者产品经理的需求规格,并且努力把功能列表转变为可以运行的程序。不幸的是,现实中软件生产过程要复杂得多。在开始阶段,写下来的需求只是冰山一角,未写下来的需求才是沉浸在水下的巨大冰块;即使写下来的、被用户所确认的需求也不能确保实现后一定能够让用户满意。

没有精神层面的支持,创新是无从谈起的,因为创新实在是一项艰巨的工作,概念的建立不是一蹴而就的,需要反复地推敲、对比、自我否定。问题的定义更是自我意识游走在理想与现实之间,尝试各种问题边界的可能,不断地进行权衡。人生贵在坚持批判性思维,而不是简单的批评与抱怨。所有这些行动都是很困难的,因为它们会产生巨大的认知摩擦。由此可见,对于一个致力于创新的程序员,能够建立并保持一个积极的人生态度才是最值得庆幸的事情。

我们可以将创新模型简单地归纳为以下4个核心要素:

·创新需要挑战现状,即批判性思维。

·批判性思维需要准确的问题定义。

·问题的定义有赖于概念系统的建立。

·在初始阶段,概念模型的正确与否是次要的,更为重要的是要有一个概念模型,然后这个概念模型可以随着认识的深入而不断演化。谁在幕后推动认识的发展?答案还是批判性思维。批判性思维有助于我们修正原有概念的不足或创建全新的概念,在思维的各个阶段都需要乐观的人生态度的支持。

通常我们的开发人员具有的也是模块化设计逻辑,程序完成后会打包并部署成一个个具体的应用。每个应用的格式依赖于相应的应用语言和框架。例如,Java应用通常会被打包为WAR格式,部署在Tomcat或者Jetty上,而另外一些Java应用会被打包成自包含的JAR格式。同样,Rails和Node.js会被打包成层级目录。这种应用开发风格很常见,也很易于调试,只需要简单运行此应用,用些工具链接UI就可以完成端到端测试。将打包好的应用复制到服务器端,通过在负载均衡器后端运行多个拷贝就可以轻松实现应用扩展。在早期,这类应用运行得都很好。但一个简单的应用会随着时间推移逐渐变大,几年后,这个小而简单的应用会变成了一个巨大的“怪物”。一旦你的应用变成一个庞大而又复杂的“怪物”,那开发团队肯定很痛苦。敏捷开发和部署举步维艰,其中最主要的问题就是这个应用太复杂,以至于任何单个开发者都不可能搞懂它。因此,修正Bug和正确地添加新功能将变得非常困难,并且很耗时。

目录
设置
设置
阅读主题
字体风格
雅黑 宋体 楷书 卡通
字体大小
适中 偏大 超大
保存设置
恢复默认
手机
手机阅读
扫码获取链接,使用浏览器打开
书架同步,随时随地,手机阅读
首 页 < 上一章 章节列表 下一章 > 尾 页