经验分享:从高流量的单体PHP应用到无服务器


我们的平台基于自动扩展组中的亚马逊的AWS EC2实例,它是由强大的RDS MySQL数据库支持。随着最近对应用程序的更改,数据库变得越来越成为环境的瓶颈,因此我们需要将其扩展,从而导致更高的AWS账单。
我们不喜欢这样工作,并建议与客户进行头脑风暴会议,以改善平台。在与客户的这次会议中,我们很快得出结论,我们都希望远离传统的基础设施,这将涉及必须从头开始编码。我们的想法是将经典的单体PHP设置转换为完全无服务器的架构。

为什么无服务器
我们需要一个平台,几乎可以立即从每分钟处理0到50k请求以及更多。正常的自动缩放无法处理这个问题所以我们需要在盒子外面思考。
通过使用AWS的无服务器组件,我们很快意识到这些是这个用例的完美选择。您只需为实际使用的运行时付费,并且在不需要运行额外容量时没有任何空闲成本。

怎样的数据库
旧平台在RDS上运行,这是一个瓶颈。我们查看了存储的数据并得出结论,nosql数据库最适合。我们根据需要选择了最近宣布的DynamoDB,因为这样只需支付我们消费的费用,我们就不必过度配置表来处理流量峰值。

为什么要添加Kinesis
在无服务器环境中尽可能地解耦是关键,因此我们通过在API网关和数据库后面的Lambda函数之间添加Kinesis来应用AWS的一个良好架构模式。通过这样做,如果数据库层出现问题,我们将有一个缓冲区。最重要的是,Kinesis提供了在规定时间内保存记录的功能。这增加了数据的可靠性。

通过POC和负载测试确认
在进行初始设计之后,我们需要验证新设计的平台是否能够处理估计的负载,最高可达50k请求/分钟。
在开发基本api功能时,我们已准备好进行测试。很明显,Lambda不会成为瓶颈。然而,负载测试表明,当负载测试的并发性增加时,记录从Kinesis到Dynamodb的时间显着增加。
这需要在我们继续之前修复......

Kinesis可以轻松捕获所有数据。然而,瓶颈是由Kinesis触发的Lambda函数,负责将数据推送到DynamoDB。在调整每个Lambda函数处理的块的批量大小后,我们没有注意到任何显着的改进。
在挖掘Kinesis的文档后,我们发现我们达到了Kinesis的读取限制(每个碎片每秒5次)。有两个选项:我们可以增加分片,这会将事件增加到Lambda,从而增加并行运行的Lambda函数的数量。选项2是启用Kinesis的增强扇出功能; 这将通过为每个消费者提供其自己的吞吐量限制来改善每个分片的读取并行性。
我们选择增加碎片的数量,并通过负载测试确认,从Kinesis到Lambda功能的6个碎片和批量大小为300,我们可以满足项目所需的容量。我们还确认该平台可以通过增加Kinesis中的分片来处理更多。

结果
为了将所有东西粘在一起,我们使用了Concourse CI。在管道中,我们自动化了代码和基础架构的所有部署。这使客户能够专注于开发,而不是整理出如何以一致和受控的方式部署代码。

这个过程产生了一个新设计的应用程序,可以满足客户的未来需求。前端托管在S3和Cloudfront上,与Lambda上运行的后端代码完全分开。持久层是未来的证明,基础设施的空闲成本大大降低。

在此期间,该平台提供154.396个会话,浏览量超过4300万,峰值为25.000个并发用户,平均页面加载时间为1.07秒。

我们能够将AWS账单总额从4.636,41美元(对于类似的广告系列)减少到400,19美元,与之前的广告系列相比(节省91%),同时正常运行时间为100%。
有趣的事实:注意如何将Lambda的实际计算成本合并到该类别中Other Services; Lambda的总成本仅为2.05美元。