教你如何hold住架构设计
“人们本可以控制自己的命运,如果我们失去了控制,那错的不在命运,而在于我们自己” ――莎士比亚
一名优秀的架构师, 应该主动地掌控服务的演进 ,运行的每个逻辑都经过仔细设计,系统每个模块的运行结果都在预料之内,并时刻准备好应对内部外部各式各样的异常和变化。想要成为优秀的架构师,需要掌握“一切尽在控制”的理念。
这里的一切都包含哪些:
- 核心业务进程的cpu占用是多少?
- Qps能够达到多少?
- 超时比例是多少?
- 使用带宽是多少?
- 系统瓶颈在什么地方?
- cache命中率范围是多少?
- .......
在设计阶段,架构师就必须对这些问题的答案了然于胸。
下面从几个维度来下详细分析一下“一切”包含的内容:
从功能到架构
从功能设计开始,明确需求优先级和问题边界,确定主要功能模块与核心业务流程,满足业务功能需求。然后设计满足各项工程及运营需求的系统架构,这些需求通常包括:处理能力(QPS、Timeout、容量等)、伸缩性、容错性、扩展性、安全性等等很多非功能性需求。
这里的每一项都有很大的挑战,任何一项的失控都可能导致严重的后果。在互联网服务里面,对性能不可控的结果是灾难性的;不良的伸缩性会导致服务的运营异常艰难;容错性的失控就像服务的黑洞,黑天鹅事件的产生。
从测试性能到掌控性能
任何系统的性能是设计出来的,不是尝试出来的。我们在设计、实现一个系统时,在动手之前就应该大概知道系统的性能容量是多少,而不是等压测。Google资深架构师Jeff. Dean这样描述过:
Important skill: ability to estimate performance of a system design without actually having to build it!
这一点需要架构师对整个系统各个层面有深刻而精确的认识。对于系统内部或系统所依赖的每个组件、模块或外部系统,要知其所以然。对于整个系统的认识,不仅是定性而且要定量,应该知道某个函数的操作步骤,性能大概是什么情况,磁盘的随机读写性能,内存顺序读性能,网络通信带宽等每个环节。
在架构设计阶段,通过软件和硬件的详细参数,在系统设计时就已经可以确定如何实现,需要什么样的硬件支撑,大概能够服务多少用户等。不需要实现,架构师就可以模拟出运行时的场景,比如:负载均衡需要8台机器,每台机器cpu占用大约50%,内存使用约80%,包量40K/s,流量300Mbps等等。
从正常到异常
在异常情况下,是很容易出现失控的地方,比如雪崩问题,1230购票系统,当用户刷新没有票的时候会不停的刷新,导致后台的服务突然增加,当负载超过正常的系统性能容量时,雪崩效应产生了,整个系统的可用性就崩溃了。
当系统在“非正常状况下”运行时,架构师应当让整个系统还是在控制下运行,而不是随机的、无序的。比如我们可以有目的的优先保证忠实用户的使用情况,做到逐步有损服务。
容错的设计是必备的,对于一个服务系统来说,绝大部分的异常都应是常态。在做系统设计时,首先要能考虑到所有的非正常情况,进而分析后确定架构方案应该cover的范围和程度。
具体如何实现容灾我们这里不做详细分析,简单的比如:机房容灾、用户优先级、有损服务等。
从单机到集群
海量互联网服务系统是分布式系统技术的一类典型应用。
在集群环境下,很多资源访问都变成远程访问,丢包、延时等问题造成访问不可靠因素大大增加,同步访问也更多地替换为异步处理,数据需要分割到多台的机器分布式存储和访问,这些都增加了系统的复杂性,要求架构师不能只以传统的软件设计模式思考,更多地要考虑box之间的交互与关系。
从系统到服务
提供的是服务而不是软件或系统,这一点是每个架构师应该牢记于心的。决定系统优劣的永远是它能最终提供给用户什么质量的服务。
优质的服务包括两个方面:
有效的功能,良好的体验;
很高可用性、高性能等。
这两个方面都是优质服务的组成部分,犹如一个人的左右手,他们是不应该产生PK的。当系统出现问题时,我们第一时间应该保证服务的正常运行,比如回滚系统等,而不是纠结于具体的问题和错误。
那么如何才能真正做到“可控”呢?这里谈几点核心要素:
尽量简单
之前的文章里面也提到过,系统尽量简单,简单是对系统控制能力的保证。一个系统越是复杂意味着越难以控制。Keep It Simple and Stupid,是无数系统设计哲学中都反复提到的一条经典原则。
对于那些难以避免的复杂性,通过一些方法也可以降低系统复杂度。复杂的系统可以通过分层、分模块的方式将其分解成关系清晰、松耦合的子系统,使得每个子系统的相对简单可控,这样整体的复杂性就大大降低了。还有复杂性隔离,将复杂的逻辑隔离在一个尽可能小的范围内,提供简单的接口以与外部解耦,从而防止复杂性扩散等等。
精确地把控
架构师对系统的控制能力很大程度上依赖于其对系统从上层到底层的深刻认识,并且这种认识不是定性的、模糊的,而是定量的、精确的。前面也有提到过。
完备地设计
可控的另一个重要因素,在于架构师考虑问题的完备性和严谨性。在设计一个问题解决方案时,如何保证能应对问题的各种情况,任何的疏漏都有可能导致最后服务的失控。前面提到的雪崩问题就是典型的设计完备性上的缺陷。
具体的方法可以查阅相关文章。
合理地tradeoff
鱼与熊掌不可兼得,tradeoff是架构师在做系统设计时最常做一部分工作,同时也是比较有难度的那一部分。合理的tradeoff有事半功倍之效,可大幅提高系统性能,而盲目的tradeoff将会事得其反。
这里有两个关键点,一是需要对系统的透彻地理解,能够抽象出问题模型,认清系统设计的几个主要可变因素及其对整体性能的影响;二是正确认识需求及其优先级,根据真正的需求来确定各可变因素的平衡点。
前面提到的有损服务的设计理念,其核心也是tradeoff,关键是保证tradeoff天平两边都是在控制的范围内,一边是代价、成本、性能,一边是一致性、体验,决不能是片面的“损”,或者盲目的“损”。
简单的写了一些,希望能一起交流和沟通。