架构设计流程:识别复杂度

如何识别复杂度?
复杂度问题列出来,然后根据业务、技术、团队等综合情况进行排序,优先解决当前面临的最主要的复杂度问题。

  • 1、构建复杂度的来源清单——高性能、可用性、扩展性、安全、低成本、规模等。
  • 2、结合需求、技术、团队、资源等对上述复杂度逐一分析是否需要?是否关键?
    • 高性能”主要从软件系统未来的TPS、响应时间、服务器资源利用率等客观指标,也可以从用户的主观感受方面去考虑。
    • 可用性”主要从服务不中断等质量属性,符合行业政策、国家法规等方面去考虑。
    • 扩展性”则主要从功能需求的未来变更幅度等方面去考虑。
  • 3、按照上述的分析结论,得到复杂度按照优先级的排序清单,越是排在前面的复杂度,就越关键,就越优先解决。

架构设计流程:设计备选方案

为什么需要备选方案?
知识局限,评估未全面

做架构设计时两种查关键错误方案

  • 1、设计最优秀的方案
  • 2、只做一个方案

备选方案需要注意

  • 1、不要耗费了大量的时间和精力(备选方案不要过于详细)
  • 2、备选方案的差异要比较明显
  • 3、备选方案的数量以 3 ~ 5 个为最佳
  • 4、备选方案的技术不要只局限于已经熟悉的技术

事实上方案的创新绝大部分情况下也都是基于已有的成熟技术,例如:

  • NoSQL:Key-Value 的存储只是把数据库的索引独立出来做成了一个缓存系统。
  • Docker 虚拟化,基础是 LXC(Linux Containers)。
  • LevelDB 的文件存储结构是 Skip List。

架构设计流程:评估和选择备选方案

如何评估和选择备选方案?
可列出我们需要关注的质量属性点,然后分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案。

常见的方案质量属性点有:性能、可用性、硬件成本、项目投入、复杂度、安全性、可扩展性等。在评估这些质量属性时,需要遵循架构设计原则 1“合适原则”和原则 2“简单原则”,避免贪大求全,基本上某个质量属性能够满足一定时期内业务发展就可以了。

假如我们做一个购物网站,现在的 TPS 是 1000,如果我们预期 1 年内能够发展到 TPS 2000(业务一年翻倍已经是很好的情况了),在评估方案的性能时,只要能超过 2000 的都是合适的方案,而不是说淘宝的网站 TPS 是每秒 10 万,我们的购物网站就要按照淘宝的标准也实现 TPS 10 万。

架构设计流程:详细方案设计

何为详细方案设计?

简单来说,详细方案设计就是将方案涉及的关键技术细节给确定下来。,

  • 假如我们确定使用 Elasticsearch 来做全文搜索,那么就需要确定 Elasticsearch 的索引是按照业务划分,还是一个大索引就可以了;副本数量是 2 个、3 个还是 4 个,集群节点数量是 3 个还是 6 个等。

  • 假如我们确定使用 MySQL 分库分表,那么就需要确定哪些表要分库分表,按照什么维度来分库分表,分库分表后联合查询怎么处理等。

  • 假如我们确定引入 Nginx 来做负载均衡,那么 Nginx 的主备怎么做,Nginx 的负载均衡策略用哪个(权重分配?轮询?ip_hash?)等。

可以看到,详细设计方案里面其实也有一些技术点和备选方案类似。例如,Nginx 的负载均衡策略,备选有轮询、权重分配、ip_hash、fair、url_hash 五个,具体选哪个呢?看起来和备选方案阶段面临的问题类似,但实际上这里的技术方案选择是很轻量级的,我们无须像备选方案阶段那样操作,而只需要简单根据这些技术的适用场景选择就可以了。

例如,Nginx 的负载均衡策略,简单按照下面的规则选择就可以了。

  • 轮询(默认)
    每个请求按时间顺序逐一分配到不同的后端服务器,后端服务器分配的请求数基本一致,如果后端服务器“down 掉”,能自动剔除。

  • 加权轮询
    根据权重来进行轮询,权重高的服务器分配的请求更多,主要适应于后端服务器性能不均的情况,如新老服务器混用。

  • ip_hash
    每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,主要用于解决 session 的问题,如购物车类的应用。

  • fair
    按后端服务器的响应时间来分配请求,响应时间短的优先分配,能够最大化地平衡各后端服务器的压力,可以适用于后端服务器性能不均衡的情况,也可以防止某台后端服务器性能不足的情况下还继续接收同样多的请求从而造成雪崩效应。

  • url_hash
    按访问 URL 的 hash 结果来分配请求,每个 URL 定向到同一个后端服务器,适用于后端服务器能够将 URL 的响应结果缓存的情况。

这几个策略的适用场景区别还是比较明显的,根据我们的业务需要,挑选一个合适的即可。例如,比如一个电商架构,由于和 session 比较强相关,因此如果用 Nginx 来做集群负载均衡,那么选择 ip_hash 策略是比较合适的。

此外

  • 架构师不但要进行备选方案设计和选型,还需要对备选方案的关键细节有较深入的理解。例如,架构师选择了 Elasticsearch 作为全文搜索解决方案,前提必须是架构师自己对 Elasticsearch 的设计原理有深入的理解,比如索引、副本、集群等技术点;而不能道听途说 Elasticsearch 很牛,所以选择它,更不能成为把“细节我们不讨论”这句话挂在嘴边的“PPT 架构师”。

  • 通过分步骤、分阶段、分系统等方式,尽量降低方案复杂度,方案本身的复杂度越高,某个细节推翻整个方案的可能性就越高,适当降低复杂性,可以减少这种风险。

  • 如果方案本身就很复杂,那就采取设计团队的方式来进行设计,博采众长,汇集大家的智慧和经验,防止只有 1~2 个架构师可能出现的思维盲点或者经验盲区。