我们公司最近正在开始为拥有大用户群的客户构建应用程序。这意味着我们需要摒弃传统的服务器设置,开始扩展服务器,以便一次性处理数百个请求。这要求我了解传统服务器设置与目前更加现代的方法之间的区别。
向云进发
回想 “旧” 时代(整整 20 年前),向操作中添加更多服务器空间涉及到让某人安装硬件,然后让人们为您维护该硬件。不仅购买和维护硬件需要成本,服务器上的物理空间也需要成本。考虑到每个服务器都仅拥有有限的空间,增长太快可能带来问题。
如今,只需单击几次鼠标,就可以在云中获得一个服务器:基本上讲,其他人会负责为您维护硬件的问题,您可以在千里之外配置您的新硬件。您还可以添加许多的服务器,无需占用任何额外的空间。这使得扩展变得比过去容易得多。
传统设置
传统设置包括一个托管您应用程序的服务器和一个单独的数据库服务器。此设置通常非常适合小项目以及不需要扩展的项目。有时,过度优化您的设置并没有意义。我们公司以这种方式托管着许多项目。
“我们正在将一些较大的项目迁移到更现代的基础架构,该基础架构会让我们的应用程序能够优雅地扩展。” |
构建可扩展的基础架构
我们正在使用可扩展的基础架构创建可扩展的应用程序。抱着成为更优秀的开发场所的想法,我们决定遵循 Heroku 的 “12 因素(Twelve-Factor)应用程序” 方法,该流程是专为构建 SaaS(软件即服务)应用程序而设计的。简言之,该流程通过保持各部分分离,帮助您确保您的应用程序容易扩展。您应能够取出组合中的某一部分,无需担心会毁坏所有部分。换句话说,您的资源不应过度彼此依赖,以至于移动或更改一个组件会毁坏您的基础架构。
12 因素应用程序方法很容易理解。不是我们的所有项目都符合该方法,但我们会努力让项目尽可能符合该方法。谈到扩展,请特别注意有关可处置性的因素 9:通过快速启动和优雅的关闭实现最高的健壮性。
最佳实践
您可以尝试优化所有部分,或者可高效地使用时间,努力实现容易实现的目标,让您的应用程序与该方法有 80% 相符。我们领先的基础架构工程师喜欢 80/20 方法:20% 的工作实现 80% 的目标。这一节将介绍一些可帮助您接近想要实现的目标的简单方法。让我们看看一些例子。
1. 设置负载平衡
场景 A:您的网页登上了 Reddit 的头版,您突然获得了异常高的流量。您会怎么做?
这时有一个负载平衡器并 让一些服务器保持运行可能有所帮助。可以将负载平衡器视为空中交通指挥员。它接受所有传入的流量,并将其定向到可处理它的服务器。它也知道,如果一台服务器宕机,那么不应朝该方向发送任何流量。也可以将负载平衡器视为一个黑匣子:您不需要担忧负载平衡如何 完成,只需放心地相信它将 会完成。新传入的流量不会到达宕机的服务器,因为负载平衡器会将新流量定向到可以处理它的服务器。
场景 B:一次自然灾难袭击了整个东海岸。您的应用程序将会如何反应?
如果即将出现这种情况,那么应该一切正常,因为您会在不同的可用性区域运行服务器,对吧?您的负载平衡器会知道您在东海岸的所有服务器都已单击,然后它会开始将流量发送到西海岸的服务器。
2. 保持不同的环境看起来一样
我们公司有 4 个不同的环境:本地、开发、暂存和生产。我们尝试保持它们彼此尽可能相似。这可以预防在各个阶段发生任何可能归咎于环境变量的问题。例如,您一定不要依靠在生产环境中无法访问的开发环境中的任何资源。
3. 使用无状态服务器
作为一条规则,不要将您需要访问的信息存储在 Web 应用程序的服务器中。服务器的每个副本看起来都应该是相同的,而且您不需要将信息从一个服务器复制到下一个服务器。理想情况下,您已经创建了应用程序的服务器镜像,能够使用该镜像建立其他许多服务器。让您的数据库与应用服务器分开。
4. 经常停止您的服务器
应急训练有时看起来可能很傻,但熟能生巧。至关重要的是,每个人都应该知道在发生紧急情况时如何应对,实际练习过实际发生紧急情况时如何做。发生火灾时,人们可能知道他们应该前往紧急出口,但您不希望他们在实际发生火灾时忘记紧急出口是什么样的。
服务器问题也是如此。您可能认为您已做好应对最糟的情况的准备,但除非您知道在服务器宕机时系统将如何应对,否则您就没有做好应对不是您导致的服务器宕机情况的准备。这正是使用无状态服务器至关重要的原因。不要过度依赖您的服务器 — 经常关闭它们。您应能够停止并恢复服务器,而不害怕您将毁坏什么东西。
您希望能够确信,一些服务器在晚上发生宕机时,系统将在您能够在早上解决问题之前正常运行。
5. 集中精力解决瓶颈
瓶颈需要您确定是什么实际导致您的应用程序变慢。您不想盲目地追查可能不是实际问题的因素;查找最大的瓶颈并花时间尝试修复这些问题。
我们公司使用了 Django,所以我们喜欢使用 Django Debug Toolbar 来确定是什么实际减缓了我们的运行速度。运行减慢可能是由不必要地频繁查询数据库等操作导致的。消除瓶颈,可能对确保您的应用程序更高效地执行有很大帮助。
6. 运行后台任务
如果您可将一些任务推迟到以后,可考虑使用后台任务。例如,您可能需要执行一次很耗资源的 API 调用,所以您不需要立即向用户返回信息。我们使用 Celery Task Queue 来管理我们可推迟到以后执行的任务。有时我们不需要用户获得即时反馈,所以只要可能,我们就会将该任务延后到我们能对它给予应得的关注时运行。
7. 尽可能缓存
如果您有一个提供大量静态内容的网站,缓存无疑会加快您网站的反应速度。反复访问您的网站的用户只需加载新的内容。如果自他们上次访问您的网站以来,内容没有多大改变,那么加载将会很快。
可以采用多种缓存方式:浏览器缓存和使用内容分发网络 (CDN),后者能提供具有高可用性和高性能的内容。您可以设置资源的有效期,所以一个不错的想法是在不常更改的资源上设置较长的有效期,频繁更改的资源则相反。例如,徽标图像可能很少发生更改,而您的 HTML 网页则会非常频繁地更改。基本上讲,缓存有助于提高性能,且无需更改您的硬件。
8. 设置自动扩展
您现在只需单击一个按钮即可建立新的服务器。由于拥有如此轻松地建立和销毁服务器的能力,所以您可以确保您始终拥有足够的服务器来处理您尝试处理的流量。您甚至可以将服务器设置为在高流量期间运行,在低流量期间消失。如果知道用户模式,您可以在任何时候增加和减少服务器数量。
9. 让整个团队都参与进来
团队的每个人都可以从某种程度上帮助提高性能和扩展。每个人都可以出一份力,帮助确保团队更轻松地实施保护措施,确保您的应用程序能够处理峰值流量或一直很高的流量。
确保团队的每个人询问正确的问题。例如,某些特性是真的需要还是锦上添花?
10. 花时间执行测试
一定要在建立的时间表中给基础架构测试留出时间。不是所有功能从一开始就能顺利运行。您需要对应用程序执行压力测试,需要在生产环境中检查您的应用程序。如果时间表中没有安排对应用程序进行扩展测试的时间,那么您可能会发现需要延误工作才能修复的重大问题。
11. 考虑容器
我们公司正计划采用一种更现代的 Web 应用程序处理方法。在理想情况下,我们希望将基础架构更换为使用容器。
在听到容器时,我脑海里想到的第一件事是,容器与虚拟机之间有何区别。对我而言,它们听起来很相似。事实证明,容器能比虚拟机更好地保持了应用程序的可扩展性。它们类似于虚拟机,但它们没有大量的重复硬件。我们现在可以运行单个 Linux 实例,在其上建立容器,让所有容器都共享同一个操作系统。所以容器似乎是更加轻量的、具有更高成本效益的应用程序扩展解决方案。
结束语
尽管这些实践可能无法预防所有问题,但它们会帮助您在开始构建应用程序时考虑到扩展功能,让您为需要处理数千万个用户的时刻打好基础。
要确保您正在朝建立高度可扩展的应用程序基础架构的方向而努力,您应该采取以下行动:
- 使用一个负载平衡器。
- 使用自动扩展功能。
- 不要害怕随机停止您的服务器。
- 修复需要修复的问题,而不是修复您认为应该修复的问题。
- 确保您拥有测试应用程序和修复任何问题所需的时间。