<audio id="audio" title="49 | 深入浅出网站高性能架构设计" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/12/65/120458a1f86167fce5f1194d5efef865.mp3"></audio>

你好，我是茹炳晟。今天我和你分享的主题是：深入浅出网站高性能架构设计。

在上一篇文章中，我从全局的角度和你分享了测试人员学习架构知识的重要性、应该学到什么程度，以及怎么学的问题，希望你可以借此明白网站架构的why、what、how。

接下来，我将站在测试人员的视角，通过这个专栏的最后四篇文章，和你分享网站的高性能架构、高可用架构、伸缩性架构以及扩展性架构。希望借此机会，可以让你对网站的架构设计做到心中有数，在设计测试用例时可以做到有的放矢。

今天我们就先从网站高性能架构的设计开始吧。

性能是网站的重要指标，如果一个网站的访问速度很慢，就会直接导致大量用户的流失。所以说，性能是设计网站架构时要考虑的关键因素。也因此，网站的性能问题成了网站架构升级、优化的导火索。

目前，为了优化网站性能，业界出现了很多相关的架构改进方案和技术手段。而包括了这些升级、优化网站性能的方案、技术手段在内的高性能架构设计，是个很大的话题，单单依靠几篇文章是很难讲清楚的。所以，我从中精选了一些对测试工程师比较关键的概念和技术，和你展开今天的分享。

如果你想了解更细节的技术实现的话，可以参考我在上一篇文章中推荐的学习资料，也可以直接在留言区给我留言。

从全局来看，网站的高性能架构设计包括两大部分内容：一是前端性能，二是后端服务器相关的性能优化和架构设计。

## 前端的高性能架构

关于什么是前端性能，以及如何设计针对前端性能的测试，你可以直接参考第31篇文章[《工欲善其事必先利其器：前端性能测试工具原理与行业常用工具简介》](https://time.geekbang.org/column/article/17935)中的相关内容。

相对来说，**前端高性能架构比较直观易懂，其本质就是通过各种技术手段去优化用户实际感受到的前端页面展现时间。**

目前，业内的标准实践是来自于雅虎前端性能团队提出的35条原则，我已经在第29篇文章[《聊聊性能测试的基本方法与应用领域》](https://time.geekbang.org/column/article/14832)中，为你解读了其中几个比较典型的规则，你可以再回顾下。同时，你还可以访问[雅虎网站](https://developer.yahoo.com/performance/rules.html?guccounter=1)查看经典的35条规则，以及对各规则的详细解读。

前端的高性能架构相对于后端来讲比较容易实现，因为前端性能优化的方法是相对标准的。而且，目前的前端性能测试工具，比如我在前面文章中曾经介绍过的WebPageTest和YSlow之类的工具等，都能系统性地分析前端的性能问题，并给出对应的解决方案建议。

可以说，我们只要在项目开发过程中，把前端性能优化纳入了测试范围，那么一般来讲都能获得比较理想的性能优化结果。

## 后端服务器的高性能架构

后端服务器的高性能架构，业内采用的最主要的技术手段是缓存。同时，集群也可以从计算能力的角度，提升后端的处理性能。

### 缓存

可以说，在计算机的世界中，凡是想要提高性能的场合都会使用到缓存的思想。缓存是指将数据存储在访问速度相对较快的存储介质中，所以从缓存中读取数据的速度更快。

另外，如果缓存中的数据是经过复杂计算得到的，那么再次使用被缓存的数据时，就无需再重复计算即可直接使用。从这个意义上讲，缓存还具有降低后端运算负载的作用。

可见，缓存在软件系统和网站架构中几乎无处不在。当然了，在系统和软件的不同级别对应有不同层级的缓存：

- 浏览器级别的缓存，会用来存储之前在网络上下载过的静态资源；
- CDN本质也是缓存，属于部署在网络服务供应商机房中的缓存；
- 反向代理服务器本质上同样也是缓存，属于用户数据中心最前端的缓存；
- 数据库中的“热点”数据，在应用服务器集群中有一级缓存，在缓存服务集群中有二级缓存；
- 甚至是用于URL和服务器IP地址转换DNS服务器，为了减少重复查询的次数也采用了缓存。

启用了缓存后，当应用程序需要读取数据时，会先试图从缓存中读取：

- 如果读取成功，我们称为缓存命中，此时就可以在很大程度上降低访问数据库的时间开销。
- 如果没有读取到数据或者缓存中的数据已经过期失效，那么应用程序就会访问数据库去获取相应的数据。获取到数据后，在把数据返回给应用程序的同时，还会把该数据写入到缓存中，以备下次使用。

**缓存主要用来存储那些相对变化较少，并且遵从“二八原则”的数据。这里的“二八原则”指的是80%的数据访问会集中在20%的数据上**。

也就是说，如果我们将这20%的数据缓存起来，那么这些数据就会具有非常高的读写比。读写比越高，说明缓存中的数据被使用的次数也就越多，从而节省的数据库访问也就越多，缓存的优势也就越明显。

需要特别注意的是，**缓存技术并不适用于那些需要频繁修改的数据**。对于这种需要频繁修改的数据来说，经常会出现刚刚写入缓存的数据还没来得及被读取就已经失效了的场景。所以，在这种情况下，缓存不仅不会带来性能提升，反而会增加系统开销。

从理论上来讲，缓存的作用是辅助提升数据的读取性能，缓存数据丢失或者缓存不可用不应该影响整个系统的可用性，因为即使没有了缓存，数据依旧可以从数据库中获得。但是，现在的数据库已经习惯了有缓存的日子，假如哪天缓存系统奔溃了，就会在短时间内有大量的请求来访问数据库，数据库就很可能会因为无法承受这样的并发压力而宕机。

为了解决这个问题，有些网站会使用缓存热备等技术手段来提供缓存的高可用性，即：当某台缓存服务器宕机的时候，会将缓存访问切换到热备的缓存服务器上。

另外，如果你采用了分布式缓存服务器集群的话，那么缓存的数据将被分布到集群中的多台服务器上，当其中一台服务器宕机的时候，也只会丢失一部分缓存数据，此时通过访问数据库来重建这些缓存数据的开销并不算太大。

目前，分布式缓存架构的主流技术方案有两种：

- **一种是，在企业级应用中广泛采用的JBoss Cache**。JBoss Cache需要在缓存集群中的每台机器上同步所有缓存的副本，当集群规模比较大的时候，同步代价会很高。而且，多份副本也会造成存储资源的浪费。但其最大的优点是速度非常快，所以JBoss Cache更适用于企业级规模不是很大的缓存集群。这种企业级的集群一般在几台到十几台服务器的规模。
<li>**另一种是，在互联网应用的主流Memcached**。Memcached属于互不通信的分布式架构，集群中各个节点缓存的数据都不一样，缓存使用者基于Hash一致性算法来定位具体的内容到底缓存在集群中的哪个节点。<br />
因此，Memcached具有缓存容量大，存储效率高，可以很方便地支持集群的扩展，但是速度相对较慢的特点。这些特点决定了Memcached非常适用于现如今的互联网产品架构，几乎成为了网站分布式缓存架构的代名词。</li>

互联网产品架构的应用服务器集群规模一般都很大，即使小规模的应用集群也有上百台机器，规模大的话可以达到上万台，这种架构下的缓存集群规模要求也非常大。

通过上面这些些缓存的基础知识，再结合着你在平时项目中积累的相关经验，相信你已经理解了缓存的原理。那么，接下来我们再从测试人员的视角来看看，在执行测试时需要考虑到哪些与缓存相关的测试场景：

- 对于前端的测试场景，需要分别考虑缓存命中和缓存不命中情况下的页面加载时间。
- 基于缓存过期测试策略的设计，需要考虑到必须要重新获取数据的测试场景。
- 需要针对可能存在的缓存“脏数据”，进行有针对性的测试。缓存“脏数据”，是指数据库中的数据已经更新，但是缓存中的数据还没来得及更新的场景。
- 需要针对可能的缓存穿透进行必要的测试。缓存穿透，是指访问的数据并不存在，所以这部分数据永远不会有被缓存的机会，因此此类请求会一直重复访问数据库。
- 系统冷启动后，在缓存预热阶段的数据库访问压力是否会超过数据库实际可以承载的压力。
- 对于分布式缓存集群来说，由于各集群使用的缓存算法不同，那么如果要在缓存集群中增加更多节点进行扩容的话，扩容对原本已经缓存数据的影响也会不同。所以，我们需要针对缓存集群扩容的场景，进行必要的测试和性能评估。

### 集群

集群也是提升网站性能和并发处理能力的典型架构设计方法。

当一台服务器不足以满足日益增长的用户流量时，我们就可以考虑使用多台服务器来组成一个集群：外部请求将统一和负载均衡器打交道；负载均衡器根据不同的负载调度算法，将访问请求传递给集群中的某台服务器处理。

需要注意的是，在这种模式下，集群中的任何一台服务器宕机都不会给整个系统带来明显的影响。此时，每台服务器的地位也都不怎么高，我们可以直接替换掉出现了问题的某台服务器。同样地，当需要支持更大的系统负载时，我们就可以在集群中添加更多的服务器。

这时，集群中的每台服务器都可以被随时替换或者淘汰掉，就像“牲口”似的可以任人宰割。所以，这种模式，就有点类似于“牲口”模式。

与“牲口”模式对应的是“宠物”模式，比如一些企业级的应用，它们往往不通过集群来扩展系统的能力和提高系统的性能，而是采用更为强劲的服务器。

这种性能非常强大的单台服务器，价格往往十分昂贵，所以通常都会被特别关照，比如给其配备最好的机房和UPS等等。另外，大家都不敢对这样的服务器有任何大的动作，生怕把它们搞坏了。此时，这些价格昂贵的服务器更像是“宠物”。

综上所述，现今的互联网应用采用的都是“牲口”模式。在这种模式下，我们在开展测试时，相应地需要额外关注以下这些测试点：

- 集群容量扩展。也就是说，集群中加入新的节点后，是否会对原有的session产生影响。
- 对于无状态应用，是否可以实现灵活的实效转移。
- 对于基于session的有状态应用，需要根据不同的session机制验证会话是否可以正常保持，即保证同一session始终都有同一个确定的节点在处理。
- 当集群中的一个或者多个节点宕机时，对在线用户的影响是否符合设计预期。
- 对于无状态应用来说，系统吞吐量是否能够随着集群中节点的数量呈线性增长。
- 负载均衡算法的实际效果，是否符合预期。
- 高并发场景下，集群能够承载的最大容量。

## 总结

今天，我以测试人员的视角，和你分享了网站高性能架构设计中，需要重点关注的点。

首先，网站的性能，在很大程度上和用户的体量有直接关系。因此，开发人员在设计网站架构时，必须要重点考虑与性能相关的架构设计。相应地，测试人员在测试网站性能时，也要考虑到这其中的架构设计。

其次，网站高性能架构设计，主要包括前端性能优化和后端服务器的性能调优。所以，我从这两个方面，和你展开了今天的分享。测试人员在理解了两大部分知识的基础上，在设计具体的测试时，要考虑到这些网站高性能架构设计的方案、技术手段，以此制定出需要额外增加的测试点，以及对应的测试方法。

最后，关于网站性能测试的理论与方法，你可以参考我在第28~34篇文章（也就是性能测试系列文章）中的相关内容。

## 思考题

在你接触过的项目中，都遇到过哪些系统层面的高性能架构设计方案？从测试的角度来看，你又会设计怎样的测试场景和用例？

感谢你的收听，欢迎你给我留言。


