本指南总结了扩展的基本原则,从一台服务器扩展到能够服务数百万用户的Web应用程序。它面向在技术领域工作的新手和非开发人员。因此,如果您刚刚部署了您的多云平台VPN设置,那么本文并不适合您。
话不多说,那就让我们开始吧!
你刚刚完成了你的网站、在线商店、社交网络或其他任何你想做的事情,把它放到网上,一切都很顺利:每天有数百名访问者经过你的网站,请求得到快速响应,订单立即得到处理,一切都很顺利。
但随后可怕的事情发生了:你变得成功了!
越来越多的用户蜂拥而至,数以千计,数以万计,每小时、每分、每秒……对您的企业来说,好消息对您的基础设施来说是坏消息;因为现在,它需要扩展。这意味着它需要能够:
几年前,这篇文章一开始会讨论“垂直”与“水平”缩放(也称为向上扩展与向外扩展)。简而言之,垂直扩展意味着在更强大的计算机上运行相同的东西,而水平扩展意味着并行运行多个进程。
如今,几乎没有人再进行垂直/水平扩展。原因很简单:
好了,就是水平扩展了!但所需的步骤是什么呢?
这可能就是您的服务器最初的样子。运行业务逻辑的单个应用程序服务器和存储长期数据的数据库。事情很简单,但这种设置满足更高要求的唯一方法是在更强大的计算机上运行-这不是很好。
为更大规模的体系结构做好准备的第一步是添加“反向代理”。可以把它想象成酒店的接待处。当然,你可以直接让客人去他们的房间。但实际上,你想要的是一个中介,检查客人是否被允许进入,她的所有文件是否整齐,并正在前往一个实际存在的房间的路上。如果一个房间关门了,你希望有人用友好的声音告诉客人,而不是让他们陷入困境。这正是反向代理所做的事情。一般来说,代理只是一个接收和转发请求的进程。通常,这些请求会从我们的服务器发送到互联网。然而,这一次,请求来自互联网,需要被路由到我们的服务器,所以我们称之为“反向代理”。
这样的代理可以完成多项任务:
大多数“反向代理”还有一个诀窍:它们还可以充当负载均衡器。负载均衡器是一个简单的概念:假设在给定的一分钟内,有100名用户准备在您的在线商店付款。不幸的是,您的支付服务器一次只能处理50笔付款。解决办法?您只需同时运行两个支付服务器即可。
负载均衡器现在的工作是在这两个服务器之间拆分传入的支付请求。用户1向左,用户2向右,用户3向左,以此类推。
如果有500名用户想要一次性付款,你会怎么做?确切地说,您可以扩展到10个支付服务器,并让负载均衡器在它们之间分配传入的请求。
使用负载均衡器允许我们在多个服务器之间分担负载。但你能发现问题所在吗?虽然我们可以利用数十、数百甚至数千台服务器来处理我们的请求,但它们都在同一个数据库中存储和检索数据。那么,我们就不能以同样的方式扩展数据库吗?不幸的是没有。这里的问题是一致性。我们系统的所有部分都需要就他们使用的数据一致
。不一致的数据导致了各种各样的问题-订单被多次执行,从一个持有100元的账户中扣除两笔90元的款项,等等问题。那么,我们如何在确保一致性的同时扩大我们的数据库?
我们能做的第一件事就是把它分成多个部分。一部分专门负责接收和存储数据,所有其他部分负责检索存储的数据。此解决方案有时称为主从分离或读写分离。我们的假设是,服务器从数据库读取数据的频率远远高于向数据库写入数据的频率。此解决方案的好处是保证了一致性,因为数据只写入单个实例,并从那里单向流动,从写到读。缺点是我们仍然只有一个数据库实例可供写入。对于中小型网络项目来说,这是可以的,但如果你运行淘宝或微博,那就不行了。
到目前为止,我们只与一台服务器打交道:处理支付、订单、库存、为网站提供服务、管理用户账户等。
这不一定是一件坏事,单台服务器意味着更低的复杂性,因此对我们的开发人员来说也不会那么头疼。但随着规模的扩大,事情开始变得复杂和低效:
这些问题的解决方案是一种席卷开发世界的体系结构范例:微服务
。这个想法很简单,将您的服务器拆分成多个功能单元,并将它们部署为独立的、相互连接的微型服务器。
这有很多好处:
还有什么比高效工作更好的呢?根本不用工作!我们的Web应用程序的很大一部分是由静态资源组成的(一些永远不会改变的内容,如图像、javascript和css文件、某些产品的预渲染登录页等)。与其在每次请求时重新计算或重新服务这些资源,我们可以使用“缓存”(一个小的存储),它只记住最后的结果并将其分发给每个感兴趣的人,而不会打扰底层服务器。
缓存的大兄弟被称为“内容分发网络”或简称CDN–一个分布在世界各地的巨大的缓存阵列。这使我们能够从离用户物理位置很近的供应商向用户提供内容,而不是每次都将数据传输到全球各地。
你去过游乐园吗?你是不是刚走到售票处买票?可能不会——很有可能你已经在排队等候了。政府机构、邮局和游乐园入口处都是一个很好的例子,这个概念被称为“随需添加的并行性”–是的,它们是并行的:多个售票亭同时售票——但似乎从来没有足够的数量来立即为每个人提供服务,结果,开始排起了长队。
同样的概念也适用于大型网络应用程序。每分钟都有数十万张图片上传到Instagram、Facebook和Co,每一张图片都需要进行处理、调整大小、分析和标记–这是一个耗时的过程。因此,与其让用户等待他们的上传完成所有这些步骤,还不如让他们等待。
接收图像的服务器只做三件事:
从这里开始,这个笔记被其他任意数量的服务器接收,每个服务器完成它的一个任务,勾选它,然后把笔记放回堆栈——直到我们的待办事项列表完成。管理这堆笔记的系统称为“消息队列”。
使用这样的队列有许多优点:
如果我们遵循上面的所有步骤,我们的系统现在已经准备好服务于相当大的流量。但如果我们想做大–真的很大–我们能做什么呢?好吧,我们还有几个选择。
什么是分片?它是这样的:
分片是一种将应用程序的功能并行化的技术,方法是将应用程序功能划分为多个单元,每个单元负责特定的键或命名空间
那么这到底是什么意思呢?实际上很简单:需要为20亿用户提供Facebook个人资料吗?将你的体系结构分解成26个迷你Facebook,每个都为用户提供不同的字母表。亚伦·亚伯拉罕?你会被斯塔克·A·扎卡里亚斯·扎克伯格传球吗?堆栈Z它是…。
分片不一定是基于字母,但可以基于任何数量的因素,例如位置、使用频率(高级用户被引导到好的硬件)等等。根据您的需要,您可以通过这种方式共享服务器、数据库或堆栈的几乎任何方面。
单个负载均衡器只能做到这一点–即使您开始购买一些功能非常强大(也非常昂贵)的硬件负载均衡器,它们可以处理的请求数量也是有硬性限制的。
幸运的是,有一个全球范围的、分散的和令人难以置信的稳定的层,可以在流量达到负载均衡器之前就用于负载平衡。最棒的是什么呢?这绝对是免费的。这一层是“域名系统”–或简称为“域名系统”。将“arcenty.com”等域名映射到“143.204.47.77”等IP的全球注册表。该注册表允许我们为每个域名指定多个IP,每个IP指向不同的负载均衡器。