可扩展性

既然你已经知道如何在一台服务器上运行Django,让我们来研究一下,如何扩展我们的Django安装。 这一部分我们将讨论,如何把一台服务器扩展为一个大规模的服务器集群,这样就能满足每小时上百万的点击率。

有一点很重要,每一个大型的站点大的形式和规模不同,因此可扩展性其实并不是一种千篇一律的行为。 以下部分会涉及到一些通用的原则,并且会指出一些不同选择。

首先,我们来做一个大的假设,只集中地讨论在Apache和mod_python下的可扩展性问题。 尽管我们也知道一些成功的中型和大型的FastCGI策略,但是我们更加熟悉Apache。

运行在一台单机服务器上

大多数的站点一开始都运行在单机服务器上,看起来像图20-1这样的构架。

可扩展性 - 图1

图 20-1: 一个单服务器的Django安装。

这对于小型和中型的站点来说还不错,并且也很便宜,一般来说,你可以在3000美元以下就搞定一切。

然而,当流量增加的时候,你会迅速陷入不同软件的 资源争夺 之中。 数据库服务器和Web服务器都 喜欢 自己拥有整个服务器资源,因此当被安装在单机上时,它们总会争夺相同的资源(RAM, CPU),它们更愿意独享资源。

通过把数据库服务器搬移到第二台主机上,可以很容易地解决这个问题。

分离出数据库服务器

对于Django来说,把数据库服务器分离开来很容易: 只需要简单地修改 DATABASE_HOST ,设置为新的数据库服务器的IP地址或者DNS域名。 设置为IP地址总是一个好主意,因为使用DNS域名,还要牵涉到DNS服务器的可靠性连接问题。

使用了一个独立的数据库服务器以后,我们的构架变成了图20-2。

可扩展性 - 图2

图 20-2: 将数据库移到单独的服务器上。

这里,我们开始步入 n-tier 构架。 不要被这个词所吓坏,它只是说明了Web栈的不同部分,被分离到了不同的物理机器上。

我们再来看,如果发现需要不止一台的数据库服务器,考虑使用连接池和数据库备份将是一个好主意。 不幸的是,本书没有足够的时间来讨论这个问题,所以你参考数据库文档或者向社区求助。

运行一个独立的媒体服务器

使用单机服务器仍然留下了一个大问题: 处理动态内容的媒体资源,也是在同一台机器上完成的。

这两个活动是在不同的条件下进行的,因此把它们强行凑和在同一台机器上,你不可能获得很好的性能。 下一步,我们要把媒体资源(任何 不是 由Django视图产生的东西)分离到别的服务器上(请看图20-3)。

可扩展性 - 图3

图 20-3: 分离出媒体服务器。

理想的情况是,这个媒体服务器是一个定制的Web服务器,为传送静态媒体资源做了优化。 lighttpd和tux (http://www.djangoproject.com/r/tux/) 都是极佳的选择,当然瘦身的Apache服务器也可以工作的很好。

对于拥有大量静态内容(照片、视频等)的站点来说,将媒体服务器分离出去显然有着更加重要的意义,而且应该是扩大规模的时候所要采取的 第一步措施

这一步需要一点点技巧,Django的admin管理接口需要能够获得足够的权限来处理上传的媒体(通过设置 MEDIA_ROOT )。如果媒体资源在另外的一台服务器上,你需要获得通过网络写操作的权限。 如果你的应用牵涉到文件上载,Django需要能够面向媒体服务器撰写上载媒体 如果媒体是在另外一台服务器上的,你需要部署一种方法使得Django可以通过网络去写这些媒体。

实现负担均衡和数据冗余备份

现在,我们已经尽可能地进行了分解。 这种三台服务器的构架可以承受很大的流量,比如每天1000万的点击率。

这是个好主意。 请看图 20-3,一旦三个服务器中的任何一个发生了故障,你就得关闭整个站点。 因此在引入冗余备份的时候,你并不只是增加了容量,同时也增加了可靠性。

我们首先来考虑Web服务器的点击量。 把同一个Django的站点复制多份,在多台机器上同时运行很容易,我们也只需要同时运行多台机器上的Apache服务器。

你还需要另一个软件来帮助你在多台服务器之间均衡网络流量: 流量均衡器(load balancer) 。你可以购买昂贵的专有的硬件均衡器,当然也有一些高质量的开源的软件均衡器可供选择。

Apaches 的 mod_proxy 是一个可以考虑的选择,但另一个配置更棒的选择是: memcached是同一个团队的人写的一个负载均衡和反向代理的程序.(见第15章)

记录

如果你使用FastCGI,你同样可以分离前台的web服务器,并在多台其他机器上运行FastCGI服务器来实现相同的负载均衡的功能。 前台的服务器就相当于是一个均衡器,而后台的FastCGI服务进程代替了Apache/mod_python/Django服务器。

现在我们拥有了服务器集群,我们的构架慢慢演化,越来越复杂,如图20-4。

可扩展性 - 图4

图 20-4: 负载均衡的服务器设置。

值得一提的是,在图中,Web服务器指的是一个集群,来表示许多数量的服务器。 一旦你拥有了一个前台的均衡器,你就可以很方便地增加和删除后台的Web服务器,而且不会造成任何网站不可用的时间。

慢慢变大

下面的这些步骤都是上面最后一个的变体:

  • 当你需要更好的数据库性能,你可能需要增加数据库的冗余服务器。 MySQL内置了备份功能;PostgreSQL应该看一下Slony (http://www.djangoproject.com/r/slony/) 和 pgpool (http://www.djangoproject.com/r/pgpool/) ,这两个分别是数据库备份和连接池的工具。

  • 如果单个均衡器不能达到要求,你可以增加更多的均衡器,并且使用轮训(round-robin)DNS来实现分布访问。

  • 如果单台媒体服务器不够用,你可以增加更多的媒体服务器,并通过集群来分布流量。

  • 如果你需要更多的高速缓存(cache),你可以增加cache服务器。

  • 在任何情况下,只要集群工作性能不好,你都可以往上增加服务器。

重复了几次以后,一个大规模的构架会像图20-5。

可扩展性 - 图5

图 20-5。 大规模的Django安装。

尽管我们只是在每一层上展示了两到三台服务器,你可以在上面随意地增加更多。