为下一个重大事件准备Web应用程序,第2部分-IDC帮帮忙

在我之前的博文中,我讨论了负载测试和监控应用程序的重要性,以便为大型事件做准备。这可能是计划中的事情,例如营销活动或在线销售,或者某些意外情况,例如您的应用程序正在传播。

在本文中,我将讨论您可以采用的其他体系结构模式,以便在高流量发生之前提高应用程序的性能,可伸缩性和可用性。

自动缩放
对于典型的Web应用程序,对于基础架构的任何给定组件(例如,Web服务器)在其不堪重负并且用户体验受到影响之前可以处理的内容总是存在理论上的限制。

显然,可以对应用程序代码,Web服务器的配置和底层操作系统进行增强。但是,一旦达到组件的资源限制,在增加负载下维持性能的唯一方法是垂直扩展(获取更大的服务器)或水平扩展(添加更多服务器)。

自动扩展是一种机制,允许您随着应用程序需求的增长自动配置其他资源,并在需求消失后终止这些资源。在云计算出现之前,处理大量流量需要预先配置服务器以提前预计系统上的最大负载,因此即使在没有需求的情况下也会产生该容量的成本。

在深入研究如何有效扩展应用程序之前,需要考虑许多架构因素,因为可伸缩性确实增加了一些额外的复杂性。

用户会话管理
当用户在浏览器中加载您的应用程序时,假设您的应用程序不仅仅是一个静态网站,用户会话允许Web服务器在您与应用程序多次交互时存储有关该特定用户的持久信息。

用户会话可以包含其认证信息(例如认证令牌),购物车内容或一些其他用户特定的配置/信息。如果在每个单独的Web服务器上处理用户会话,则始终需要将用户的请求返回到同一Web服务器。如果您在负载均衡器后面有一个Web服务器场(是自动调整的或静态服务器),则需要有一种方法让用户每次都返回到保存其会话数据的服务器,或者有一些方法可以服务器场中的每个服务器都可以检索其用户会话,因此用户的体验是一致且稳定的(例如,每次与其他服务器交互时,他们都不会注销,因为他们的身份验证数据存储在用户会话中)。

一种方法是在负载均衡器上启用粘性会话。粘性会话允许负载均衡器生成将客户端与单个服务器相关联的浏览器cookie。虽然这种方法有效,但并不理想; 特别是在自动缩放组的情况下。如果终止自动缩放组中的某个Web服务器,则与该服务器关联的用户将丢失所有会话状态并返回到空会话。登录,购物车数据和其他会话信息将丢失。

粘性会话也可能导致服务器需求不均匀。当服务器添加到池中时,只会将新会话定向到这些服务器。现有服务器将继续在先前建立的会话的负载下挣扎,而不是在该组中的所有服务器上均匀分布流量,从而导致“热点”的发展,或者车队中负载的不均匀分布。

管理用户会话的更好方法是将用户会话与Web服务器分离。最常见和首选的方法是在单独运行到Web服务器的一个或多个服务器上使用诸如Redis或Memcached之类的缓存引擎。

上述两种缓存引擎虽然功能略有不同,但大致归类为内存中的键值数据库。在缓存中保留用户会话将允许每个Web服务器引用缓存以获取会话数据,从而为用户提供一致且稳定的体验,无论他们与哪个服务器进行交互,并使负载均衡器能够在所有主机上均匀分配所有负载。外部化用户会话的另一个好处是,如果Web服务器发生故障或从自动缩放组中删除,用户将不会受到影响。

共享存储
几乎所有Web应用程序都在某种程度上依赖于存储。最明显的用例是Web服务器向应用程序用户提供的HTML,Javascript或其他静态资产(如图像,CSS文件等)。另一个用例可以是用户上传到您的服务器以供应用程序处理的数据,如音频文件或图像。

在可扩展的基础架构中,所有服务器通常都需要访问用户上传的任何文件。因为它们通常上传到特定服务器,所以在整个机群中保持这些文件同步可能是一个挑战。幸运的是,有许多不同的方法可以解决这个问题,每个方法都可以单独使用,也可以相互组合使用:

使用分布式文件系统,例如网络文件系统,GlusterFS或Amazon的EFS
在亚马逊S3上托管静态资产
跨所有Web服务器自动同步文件
每种解决方案都有其优点和缺点。使用分布式文件系统是最透明的方法,因为很少需要从应用程序的角度进行更改。就您的应用程序而言,文件可以像普通磁盘一样访问,只需要让底层操作系统知道更改。这具有可能的性能瓶颈的缺点,因为对分布式文件系统的所有读写操作将通过网络。

Amazon EFS还需要考虑磁盘IO的影响。EFS吞吐量随着文件系统的增长而扩展。这意味着存储在EFS卷中的数据越多,提供的吞吐量就越多。在首次实施EFS以确保其满足应用程序的性能要求时,应对应用程序进行适当的基准测试并仔细观察相关的Cloudwatch指标。

S3对静态资产特别有用,但是,您的应用程序需要进行一些修改才能指向每个对象的位置。这可能还需要使用软件开发工具包,该工具包可以处理对象的读取和写入。

此外,由于其透明的文件复制,S3具有用于写后读的最终一致性模型。这意味着在S3中更新然后立即从S3读回的文件可能不会返回最新版本,直到更改已在区域中的整个S3结构中完全传播。通常,此延迟将以毫秒或单个数字秒为单位进行测量。但是,如果您的应用程序需要立即读写后一致性,则可能会对您的用户产生负面影响。

最后,使用rsync等工具自动在所有Web服务器上同步文件可以解决可能的磁盘IO问题,因为文件现在是每台服务器的本地文件。但是,此方法需要使用Cron,Windows任务计划程序 或类似实用程序来安排同步作业。这也意味着对文件的更改将比S3的写后读写一致性具有更长的延迟,有时需要五分钟或更长时间,具体取决于所做更改的大小和数量以及同步作业的间隔。

数据库只读副本
根据您正在使用的数据库技术,可以选择设置数据库的只读副本。当您的应用程序是密集读取时,只读副本是有益的,因为它允许您将读写应用程序拆分到单独的服务器,从而释放主数据库以进行写入操作,同时在副本上执行更多资源密集型读取。此外,只读副本允许备份,商业智能,报告和分析在生产时间运行,而不会影响主数据库的性能。如果在主数据库服务器上发生中断,也可以将只读副本提升为主数据库,从而提高体系结构的容错能力。

在Amazon的关系数据库服务环境中,可以为Amazon Aurora,MySQL,PostgreSQL和MariaDB 创建只读副本。

您将需要一种方法来在应用程序级别拆分读取和写入,以便充分利用读取副本。大多数应用程序框架都提供这样的机制。

数据库缓存
我之前提到Redis和Memcached与会话状态有关。这些相同的工具可用于在内存中存储数据库响应,为从数据库中提取可能需要更长时间的常见查询提供极快的响应时间。

此外,由于它们缓存了数据库响应,因此可以使数据库不必响应每个请求,从而可能无需更大的数据库服务器,并且可以在不牺牲性能的情况下节省成本。

大多数应用程序框架都支持Redis和Memcached - 内置或通过库。实现可以像应用程序配置中的单行更改一样简单,也可能需要更复杂的重构才能充分利用引擎的功能。

内容分发网络
内容分发网络或CDN是全球分布的服务器网络,可根据最终用户的地理位置向最终用户提供静态或动态内容。

例如,假设您的应用程序托管在美国东海岸,但您的大多数用户都在东南亚 - 可以假设当流量流向世界中途时产生的延迟将对用户体验产生负面影响。CDN将通过在东南亚的缓存节点中缓存内容来改善最终用户体验,从而为该地区的用户提供极大改进的响应时间。

此外,由于CDN正在缓存定期请求的内容,因此它还具有减轻Web服务器处理每个请求的额外好处。这可能允许您缩小基础架构的一些部分,例如Web服务器,这可以在处理相同的流量时节省成本。

CDN还可以充当某些类型的拒绝服务攻击的缓冲区,否则这些攻击会导致您扩展基础架构以满足增加的需求。

有不同类型的CDN可用。它们可以大致分为推或拉CDN。推送CDN要求您将内容上传到CDN,然后在您的应用程序中引用CDN的分发URL。拉CDN更像是一个反向代理,它将根据终端客户端的请求动态缓存内容。除了缓存静态内容之外,一些CDN还提供基于标头或查询字符串缓存动态内容的功能。

虽然CDN对最终用户是透明的,但它对您或您的应用程序并不完全透明。所需的配置步骤将根据您使用的CDN类型而有所不同。但是,在高级别,您将需要:

配置CDN并配置您的来源。原点通常是您的Web服务器或负载均衡器。但是,您也可以选择在对象存储(如S3)中托管静态资源。对于亚马逊的CDN CloudFront,您可以将S3配置为静态资产的来源。
重新配置您的应用程序,以从CDN的URL输出静态资产的URL,而不是您自己的URL。例如,而不是图像的URL为https : / / myapplication / image. png目前可以https :  / /  cdn.mycacheprovider  /myapplicationscdn/ image .png
为您的应用程序配置DNS。这将涉及为您的应用程序创建指向CDN的DNS记录,而不是您的原始服务器或负载均衡器。这将确保您网站的访问者仅通过CDN访问您的应用程序,并且不会意外地直接访问您的服务器。
在本系列的最后两篇文章中,我研究了 负载测试和监控应用程序,以及您可以对应用程序的基础架构进行的所有上述更改,以帮助它扩展。请继续关注我在本系列中的下一篇文章,其中我将介绍正确调整您的基础设施以适应高流量事件。