当前位置: 首页 > 科技观察

如何从单个服务器扩展到拥有数百万用户的系统?

时间:2023-03-15 18:55:54 科技观察

假设你开发了一个网站(比如网店,社交网站之类的),然后你把它发布到互联网上,网站运行良好,每天有数百次访问,并且对用户响应迅速要求。但是有一天,无论出于何种原因,您的网站都出名了!每秒钟都有成千上万的用户涌入你的网站,你的网站变得越来越慢……对你来说,这是一件好事。新闻,但对您的Web应用程序来说是个坏消息。因为现在它需要扩展,你的应用需要为全球用户提供7*24的不停机服务。你如何扩展?几年前,我讨论了水平缩放与垂直缩放。简而言之,垂直扩展是指在更强大的计算机上运行相同的服务,而水平扩展是并行运行多个服务。现在几乎没有人谈论垂直缩放。原因很简单:随着计算机性能的提高,其价格呈指数增长。单台计算机的性能是有上限的,不可能垂直扩展。多核CPU意味着即使是一台计算机也可以并行运行。那么,为什么不首先并行化呢?现在我们横向扩展服务。需要什么步骤?上面这张单机+数据库的图,可能就是你的后台服务的初始模样。有一个执行业务逻辑的应用服务器(ApplicationServer)和一个存储数据的数据库。看起来不错。但是这样的配置,要想满足更高的要求,就只能跑在性能更强的电脑上,这就不太好了。添加反向代理成为??大规模服务架构的第一步是添加反向代理。类似于酒店大堂的接待处。您也可以让客人直接去他们的客房。但实际上,你需要一个中间人来检查客人是否被允许进入,如果客房没有开放,就得有人告诉客人,而不是让客人处于尴尬的境地。这些事情正是反向代理需要做的。一般来说,代理是一个接收和转发请求的进程。一般情况下,“正向代理”代理的对象是客户端,“反向代理”代理的对象是服务器。它完成了这些功能:健康检查功能确保我们的服务器一直在运行。路由转发功能将请求转发到正确的服务路径。认证功能保证用户有访问后台服务器的权限。防火墙功能确保用户只能访问他们被允许使用的网络部分等。引入负载平衡器大多数反向代理还有另一个功能:它们还可以充当负载平衡器。负载均衡器是一个简单的概念,想象一下一百个用户在一分钟内在您的在线商店付款。不幸的是,您的支付服务器在一分钟内只能处理50笔付款。这个怎么做?只需同时运行两个支付服务器即可。负载均衡器的作用是将支付请求分发到两个支付服务器。用户1向左走,用户2向右走,用户3再次向左走。..等等。如果您有500个用户需要一次性付款怎么办?准确的说,你可以扩展到十台支付服务器,然后让负载均衡器把请求分发到这十台服务器上。使用可缩放的数据库负载平衡器允许我们在多个服务器之间分配负载。但是你注意到问题了吗?虽然我们可以有数百台服务器处理请求,但它们都使用同一个数据库来存储和检索数据。那么,我们不能以同样的方式扩展数据库吗?不幸的是,这里存在一致性问题。系统使用的所有服务都需要就它们使用的数据达成一致。数据不一致会导致各种各样的问题,比如订单被多次处理,一个只有100元的账户被扣了两次90元的货款等等……那么我们在扩容数据库的时候怎么保证一致性呢?我们需要做的第一件事是将数据库分成多个部分。一部分专门用于接收和存储数据,另一部分负责检索数据。这种方案有时被称为主从模式或单实例写多副本读。这里的假设是从数据库读取的频率高于写入的频率。这种方案的好处是保证了一致性,因为数据只能由单个实例写入,然后写入的数据才能同步到其他部分。缺点是我们仍然只有一个写数据库实例。这对于中小型Web应用程序来说很好,但像Facebook这样的应用程序不会再这样做了。微服务到目前为止,我们的支付、订单、库存、用户管理等功能都在一台服务器上。这不是一件坏事,单个服务器也意味着更少的复杂性。随着规模的扩大,事情变得复杂且效率低下:开发团队随着应用程序的增长而增长。但随着越来越多的开发人员在同一台服务器上工作,发生冲突的可能性很高。只有一台服务器意味着每次发布新版本时,我们都必须等到所有工作都完成。当一个团队想快速发布而另一个团队中途发布时,这种相互依赖是很危险的。这些问题的解决方案是一种新的架构范例,即微服务。它已经席卷了开发人员:每项服务都可以单独扩展以更好地适应需求。开发团队相互独立,每个团队负责自己的微服务生命周期(创建、部署、更新等)。每个微服务都有自己的资源,例如数据库,进一步缓解了第4节中的问题。缓存和内容分发网络(CDN)如何使服务更高效?Web应用程序的很大一部分由静态资源组成,例如图像、CSS样式文件、JavaScript脚本以及一些针对特定产品的预渲染页面等。我们使用缓存而不是重新处理每个请求。缓存是用来记住上次的结果,交给其他服务或者客户端,这样我们就不用每次都去请求后端服务了。缓存的增强版称为内容分发网络(ContentDeliveryNetwork),大量的缓存遍布全球。这允许用户从物理上靠近他们的地方获取Web内容,而不是每次都将数据从源移动到用户。消息队列你去过游乐园吗?你走到售票柜台买票了吗?也许没有,也许在排队等候。政府机构、邮局和游乐园入口都是平行概念的例子。多个售票亭同时售票,但似乎永远无法立即满足所有人的需求,因此排起了长队。队列也用于大型Web应用程序。每分钟都有数千张图片上传到Instagram、Facebook,每张图片都需要处理、调整大小、分析和标记,这是一个耗时的过程。因此,图像接收服务不需要让用户等到所有步骤都完成,只需做以下三件事:存储原始的、未处理的图像。向用户确认图像已上传。创建待办任务。此待办事项列表中的任务可以由任意数量的其他服务接收,每个服务完成一项任务,直到所有待办事项完成。管理这些“待办事项列表”的称为消息队列。使用这样的队列有很多优点:解耦任务和处理。有时需要处理大量图像,有时很少。有时提供大量服务,有时提供的服务很少。简单地将任务添加到积压工作而不是直接处理它们可确保系统保持响应并且任务不会丢失。可以按需扩展。启动大量服务很耗时,所以当大量用户上传图片时再启动服务就来不及了。我们将任务添加到队列中,我们可以延迟提供额外的处理能力。那么,如果我们按照上述所有步骤进行操作,我们的系统就可以提供高流量服务了。但是,如果您想提供更大的数量怎么办?您可以做几件事。碎片化,碎片化,还是碎片化什么是碎片化?好吧,深吸一口气,你准备好了吗?让我们看一下定义:“分片是一种通过将应用程序的堆栈分成多个单元来并行化应用程序堆栈的技术,每个单元负责特定的键或名称空间”哎呀......分片到底是什么意思?其实很简单:Facebook需要为20亿用户提供个人数据,你可以把你的应用架构分解成26个mini-Facebook。如果用户名以A开头,则由mini-facebookA处理。如果用户名以B开头,则由mini-facebookB处理……分片不一定按字母顺序排列。根据业务需要,您可以基于任意数量的因素,例如位置、使用频率(特权用户被路由到良好的硬件)等。您可以根据需要以这种方式对服务器、数据库或其他方面进行切片。负载均衡负载均衡器到目前为止,我们一直在使用负载均衡器,即使你购买了一些功能强大(而且极其昂贵)的硬件负载均衡器,它们能够处理的请求量也是有硬件限制的。幸运的是,我们可以拥有一个全局的、去中心化的、稳定的层,在请求到达负载均衡器之前对其进行负载均衡。最好的部分是它是免费的,它是域名系统或简称DNS。DNS将arcentry.com等域名映射到IP,143.204.47.77。DNS允许我们为一个域名指定多个IP,每个IP解析到不同的负载均衡器。你看,扩展一个网络应用程序需要考虑很多,感谢你和我们在一起这么久。我希望这篇文章能给你一些有用的东西。但如果你从事的是IT领域相关的工作,当你阅读本文时,可能会有一个问题一直萦绕在你的脑海中:“云服务呢?”云计算/无服务器但是云服务呢?事实上,它是解决上述许多问题的最有效方法。你不需要解决这些难题。相反,这些挑战留给了云供应商,他们为我们提供了一个可以根据需要扩展而不用担心复杂性的系统。例如,Arcentry网站不执行上述任何操作(除了数据库的读写分离),而只是将这些棘手的问题留给AmazonWebServiceLambda功能,省去了用户的烦恼。但是,并不是说使用了云服务(比如AmazonWebServiceLambda)之后所有的问题就都解决了,它伴随着一系列的挑战和取舍。