2.4 技术设计
集成设计之下的那一层,可以分为三个领域:技术设计、用户界面设计与数据库设计。本节讨论技术设计。
技术设计有两大目标:
1.设计出可以满足非功能型需求的解决方案。
2.设计出可以尽量简化功能编程的解决方案。
非功能型的需求,是指那种与业务工作并没有直接支持关系的需求。它们包括:
- 所应满足的吞吐量及响应时间。
- 可用性方面的目标。
- 灾难恢复方面的要求。
- 安全设计。你需要知道应用程序的安全漏洞、修复这些漏洞的办法,以及系统监控与系统管理工作的执行方式与执行地点。
- 系统操作和系统管理的易用性。
- 能够有效处理新硬件及新软件的发布。
- 成本方面的目标。
大家在思考非功能型的需求时,一般都只会关注前两项,也就是性能及可用性方面的目标。这两项需求对设计所造成的影响,确实是最大的,然而其他几项需求,也不应该忽略。
笔者撰写本书的时候(也就是2015年),很多人在鼓吹DevOps[7]。它的主要动力源于业界想要缩短编程完工与产品发行之间的时间。为了达到这一目标,我们需要打破开发(dev)与运维(ops)之间的阻隔(例如,使用同一套版本管理工具来进行开发与运维),并且需要缩减或消除发布软件时所需的工序。微服务的推崇者会嘲笑SOA,而DevOps的推崇者则会轻视ITSM(IT Service Management,IT服务管理)。在很多IT部门之中,安装新版软件所需的流程,固然是很有问题的,但是这种流程依然有必要存在。如果你想知道糟糕的软件更新方式所引发的后果,那么可以看看2012年NatWest Bank(National Westminster Bank Plc,国家Westminster银行)所遇到的状况[8],那次事件正是由于软件升级不当所引发的。业务活动之中的流程随时都在演变,但麻烦的是,这些流程经常朝着更加复杂、更加昂贵和更加缓慢的方向演变。同时,遵照这些流程来工作的员工,由于已经熟悉了现有的流程,因此不希望这些流程再发生变化。DevOps流派的出现,使得业界能够反思自己在流程方面的一些做法,但是你在改善流程的时候,应该遵照一套法则来持续地进行改善,否则,这些流程又会逐渐地走向僵化。
复杂的大型应用程序,其变更控制(change control)流程之所以会如此冗长和烦琐,一个原因就在于这种流程必须逐段地进行演变。技术设计至少可以给我们提供一个起始点,使我们能够由此出发,以一种全新的方式来解决问题。技术设计所要处理的问题有:
- 开发与运维所使用的版本控制工具。
- 与汇报错误、切换到备份机制等工作有关的操作流程。
- 是否需要在应用程序中放入一些监控代码,以协助我们检测故障并监控性能。
如果不考虑系统的测试环境,那就没有办法制定版本控制流程及安装流程。因此,技术设计者也需要考虑到系统应该怎样进行测试。
在这些运作方面和系统测试方面的问题之中,有很多都和技术设计的第二项目标有关,那就是要为程序员的开发工作提供帮助。然而更宽泛地来说,在技术设计能为程序员所提供各种帮助之中,最为重要的一种方式,是通过设计并实现一套有效的框架,来促进程序员的工作,如图2-1所示。为此,我们首先要选择硬件及软件技术,此外还有其他一些方面要做。技术设计应该给功能代码的实现方式提供指导,应该提供一些如安全验证及用户组确认等常见的服务,如果用到了中间件,那么还应该把中间件的用法告诉程序员。此外,如果在调用某项服务的时候,需要用某个应用程序来检测网络超时,那么技术设计者就应该指出检测的方式。
对于某些IT应用程序来说,技术设计是相当简单的,但对于多层的业务应用程序等项目来说,由于还要涉及与灾难恢复有关的备份服务器及暗室操作,因此技术设计会比较复杂。有的时候,同一套技术设计或许可以涵盖多个应用程序及服务,尤其是在使用外部云或内部云的时候。
有的时候,我们需要从技术设计跳回情境设计,如果在做完技术设计之后,发现自己无法承担这个项目的开销,那就更应该如此。此时不必直接把项目取消,而是应该稍稍收缩一下自己当初的想法,同时可能还需要修改早前的情境设计。这种反馈是相当关键的,值得花些时间把这两种设计做好。
笔者坚信,要想判断某个技术设计方案是否可行,唯一的办法就是开始构建它。无论用什么框架,都应该尽快判断出该框架是否能够胜任当前的工作,而不要等到把应用程序的很多功能都放到设计方案里面之后才发现框架不行。检测框架是否合乎目标的办法,是把它置于负载之下运行。
笔者建议大家按照图2-7所演示的顺序,来为较为复杂且要求较高的应用程序编写代码。
首先构建试验原型(experimental prototype),以探索新的技术或想法。如果这项技术已经理解得很充分了,那么可以跳过该阶段。下一阶段是构建框架并测试环境。然后,用某些stub组件来填充框架,并测试该框架在负载之下的表现。此时还可以执行其他一些测试,例如,切换到备份服务器或判断应用程序的易用性。如果用户觉得这个解决方案还不错,那可以等到真正的组件做好之后,用它们来替换早前那些stub组件。
这套流程几乎不会造成浪费,因为对系统进行性能评测(benchmark)的那台计算机,本身就可以当作系统测试机来用。因此,向评测所用的那台计算机注入大量消息的那个驱动器(driver),同样可以充当系统测试的驱动器。
https://yqfile.alicdn.com/307ae0e60e270683b107be63da462093eeceacc9.png">
当然,对于一个简单的应用程序来说,这套流程有些过于庞大了。各种应用程序的技术设计,其规模与复杂程度也各有不同。