# 做大的艺术 – 大型网站的架构设计

- 作者：邓侃
- 发布时间：2010-03-06 15:38
- 原文：https://www.ifanr.com/18827

如果说1980年代是PC的时代，1990年代是互联网的时代，那么当下呢？当下是移动互联网的时代。移动互联网的基本要义，一言以蔽之，就是把手机与网站相连，每部手机在网站上都有独立的个人空间，成为手机的镜像。

一部小小的手机里面，可能同时装载着数十个软件。而且在同一时刻，可能好几个软件在同时运行。另外，还得时刻准备暂停运行，把手机CPU等资源让给电话通话等优先级别高的工作。还有，时刻需要准备应付网络连接中断，手机电池耗尽等等情况。总之，手机软件的结构设计，是做小的艺术。

移动网站的架构设计，与手机软件的架构设计有着本质的不同。如果说手机软件的特点在于小，那么网站的特点在于大。仅中国就有几亿手机用户，作为服务于移动业务的网站，它的质量来自于是否能够同时为大规模并发用户提供服务，是否能够处理海量数据，是否能够在需要扩大网站吞吐量的时候，只需要增加机器，而不需要对网站架构做大手术。这是做大的艺术。

提到做大规模网站，大家一定会想到云计算，想到Google File System，Chubby， BigTable，MapReduce等等。这些技术固然很好，但是它们仅仅是构成一个大型网站的技术要素。实际构建一个大型网站时，光知道技术要素是不够的，还得明白如何把各个要素有机地结合到一起。

“Flickr 网站架构研究”（http://www.ccthere.com/article/2357486）是一篇值得反复阅读的好文章。这篇文章不仅对一个大型网站的架构进行了系统解剖，逐条梳理，而且行文深入浅出。可惜这样的文章不多见。关于大型网站实例的讨论，散落在各处，而且内容零散。

学习和掌握构建大型网站的架构，需要汇总散落的文章，梳理零散的内容。做好这项工作很有意义，但是也比较困难。我们的体会是，不妨抓住以下几个主题，逐个分析大型网站的实例，然后横向比较。

1\. Database

数据存储历来是麻烦，尤其是需要存储海量数据的时候，往往单个数据库容量不够，甚至一个数据库集群也不够。常见的解决办法是分割，譬如按用户ID把海量数据分割成若干块，每块存储到一个独立的数据库里去。但是分割的做法降低了join操作的效率。

Google Bigtable的效率如何？好处是什么，缺陷是什么？Bigtable对什么样的情景最适用？根据Bigtable原理实现的开源软件，Hadoop/HBase的运行效率如何？

2\. Cache

用户访问网站时，通常读的操作比写的操作更频繁。为了提高读的操作，不妨把相关内容缓存到内存里，减少Disk IO的消耗。

MemCached 最近大热，Wikipedia, YouTube, Digg, Twitter等等大型网站都在用MemCached作为缓存工具。SquidCache和Varnish等等工具，也与缓存沾边。Twitter的做法是把MemCached和Varnish结合起来，同时使用。什么样的内容，应该用什么样的缓存工具？不同的工具间如何协调？各大网站的实际运行的结果，有哪些经验和教训？

3\. File System

有些内容，既没必要存放在数据库里，也不适合存放在缓存中，譬如log 和images。在这种情况下，我们需要文件系统。当有海量内容需要存放在文件系统中时，我们需要使用分布式文件系统。Google File System对于什么样的情景适用，什么样的情景不适用？分布式文件系统常常需要相应的锁机制，保证并发的读写操作不相互干扰。Chubby有什么好处？什么情形下不适用？

据说MogileFS更适合存储大量的，但是单体尺寸不大的文件，譬如images。而Google File System更适合存放大尺寸但是数量不多的文件。有没有可能把小尺寸的多个文件，合并成一个大文件，然后存储到Google File System中去。在这种情况下，比较MogileFS与Google FS的性能，是否有高下之分？

4\. Thread Management

一套工序通常由若干任务组成。多线程的办法是由一根线程全权负责整套工序的操作。另外一个办法是把工序斩成几段，每一段由一根或几根线程负责，这种办法称为工作台。

常见的是多线程的办法。但是工作台的做法有利于集中计算资源处理繁重的任务，避免瓶颈的出现。但是缺陷是需要在不同线程之间，传递记录中间状态的数据。什么样的情形适合用多线程，什么时候用工作台？

5\. Scheduler

同一个网站通常会提供多种服务，不同的服务需要调用不同的业务逻辑。有些业务逻辑可以在同一台服务器上完成，但是当业务逻辑复杂的时候，需要调用多台服务器合作完成。不同服务的受众对象不同，流量也不同，不同时段的流量也不同，同一时段不同服务的流量也不同，所以需要动态地分配计算资源。这是 scheduler的工作。

Scheduler给不同服务器分配工作时，最简单的办法是启动预先安装在该服务器上的相关程序。由于不能保证每个程序都十分完美，当一个程序发生错误时，应当避免整个服务器因此而崩溃，影响其它工作的正常进行。是否需要动用virtual machine，实现各个不同工作之间相互隔绝？

6\. Signal Flow and Data Flow

大型网站后台系统经常由众多服务器组成，服务器与服务器之间时不时会发生数据交换，譬如Web Server解析完用户请求后，把请求转发给某一台App Server，这一台App Server完成了部分工作后，把中间数据转发给下一台App Server。而第二台App Server完成任务后，整个工作就结束了，结果应该返回给Web Server。

问题是如何让第一台App Server如何知道应该把中间结果给第二台App Server，而第二台App Server又如何知道它的目的地是Web Server？一个比较有效率的做法，是区别数据流和控制流。Server与Server之间常设通道，专供控制流使用，传递指令去控制数据流的发送。数据流不占用控制流通道，只有在需要时，才建立数据流的通道。

控制流和数据流的组织，需要结合具体的业务逻辑，才能优化设计，减少带宽消耗，缩短数据传输的时间。

7\. Instrumentation

网站后台各个部分是否运转正常，哪里是瓶颈，哪里空闲。这些都需要实时监控。不仅及时避免整个后台系统的崩溃，而且可以分析各个部分运行的规律，从而找到优化系统的途径。

问题是，应该选用什么样的监控工具，才能够尽量减少对系统程序的干扰，同时提供有价值的信息？

8\. Anti-abuse

通常网站面对的是形形色色的用户，绝大多数用户的行为是友好的，但是不排除少数用户蓄意恶作剧。如果事先没有设计防范措施，少数恶意用户的胡作非为，会干扰其他用户享受正常的服务。

问题是，如何防范并且及时制止恶意行为的发生？

9\. Exception Handling

不论预先设想有多周密，实际运行时，总会遇到这样那样的意外情况。譬如敏感词的出现，往往事先没有征兆。所以，在设计系统架构时，应该给网管提供必要工具，应付突发事件。
