扩展我们的AWS基础架构( 二 )


> Add ElasticSearch ?
 
这样可以更快,更好地控制搜索,我们不断地进行迭代,而无需对ElasticSearch服务上运行的图像进行太多更改 。
负载均衡我们在每个部署上都经历了10秒钟的停机时间 。部署由ElasticBeanstalk负责 。在较低的级别上,EB并行运行新(ondeck)和旧(当前)应用程序,并在所有执行脚本成功后执行符号链接 。由于我们使用的是一台服务器,因此此符号链接将导致5-10秒的停机时间需要解决 。
解决方案要解决此问题,我们需要在多台服务器上进行滚动部署 。这是一项相对简单的工作,只需要在由我们的ElasticBeanstalk管理的Autoscaling组前面安装一个Application Load Balancer 。

扩展我们的AWS基础架构

文章插图
> Add Load Balancing ?
 
滚动部署增加了测试的开销和更长的部署时间,但完全消除了停机时间 。
渲染和seo我们使用的是混合渲染,其中Django应用程序将提供部分渲染的html,并在客户端上运行AngularJS应用程序 。这引起了许多问题:
我们的渲染速度很慢,并阻塞了开发团队和服务器 。我们的服务器需要大量的处理能力才能进行渲染,这是我们响应时间不可避免的瓶颈 。甚至开发也变得困难,因为我们需要多次编写更改代码 。在某些时候,即使更改单个跟踪事件也很困难 。
较差的构建系统导致较高的加载时间 。因为没有用于混合渲染的AngularJS构建管理器,所以我们使用了自己的构建系统,并且我们自己的系统存在很多捆绑不一致和缓存问题,导致未优化的构建和较高的加载时间 。这也是改变和改进的麻烦 。
网站有时会挂起5-10分钟 。当我们收到来自用户或漫游器的大量请求时,服务器将打开与数据库的太多连接,从而导致数据库挂起 。在我们的A系列为Meddy带来更多业务之后,这种情况在2019年底每周发生一次 。原因是因为Django打开数据库连接并保持打开状态,直到HTML渲染结束! 由于数据库连接过多,服务器将挂起并最终为504服务 。
解决方案在系列A结束后不久,我们便着手将代码从混合渲染器转换为纯客户端渲染器 。为此,我们必须努力对后端服务请求的方式进行很多更改 。
我们决定使用S3存储桶作为前端的静态托管,CloudFront分发响应 。CloudFront还为我们提供了附加Lambda函数的选项,以对我们所需的请求进行非常精细的控制 。
我们进行混合渲染的主要原因之一是担心SEO会被动态渲染弄脏 。并且我们网站被挂起的主要原因之一是由于漫游器导致的请求高峰 。这两个问题都可以通过预渲染我们的页面并将预渲染的页面提供给bot来解决,这对于SEO来说是完美的 。
为此,我们使用了一个名为prerender.io的服务,该服务可预先渲染请求的页面,缓存这些页面并将这些页面提供给机器人 。我们在CloudFront发行版使用的Lambda Edge函数中添加了基于HTTP请求的用户代理的自动程序检测机制 。只要检测到漫游器,就会将其重定向到prerender.io以获取其缓存的页面 。
扩展我们的AWS基础架构

文章插图
> Add Pre-rendering and Bot Detection ?
 
需要注意的是,一旦我们达到300,000页并且prerender.io的成本很高,我们便决定拥有自己的本地预渲染服务 。我们使用S3和ECS Fargate实施了自己的缓存机制来托管服务 。
共享缓存和计划任务缓存资源未在服务器之间共享 。缓存资源无法在服务器之间共享,这意味着某些请求将被缓存而其他请求将不会被缓存 。此外,我们在服务器上存在Redis的问题; Redis已在服务器上安排了数据转储,这两次导致磁盘服务被另一服务吞噬时导致停机 。
在一台服务器上运行所需的计划任务 。Celery Beat具有内置功能,可以在特定日期和时间运行任务,并提供事件流,该事件流以表的形式存储在数据库中 。这对我们非常有用,因为我们使用它在约会前后的特定时间间隔发送约会的提醒SMS 。如果将其保留在服务器上,则会执行重复的任务,这将主要在我们的通知模块内引起冲突 。
解决方案由于我们现在正在负载平衡器上使用多个服务器,因此后端必须共享一个类似的缓存服务器 。为此,我们使用了ElastiCache 。设置非常简单 。更具挑战性的方面是我们的异步任务管理器,该管理器通过Celery Beat在每台服务器上进行管理 。
为了消除这种耦合,我们将在新服务上创建事件,该服务将通过向后端发出请求来调用这些事件 。该事件将仅存储需要调用的函数,该函数的参数以及调用它的时间 。它具有自己的数据库,后端可以根据后端的请求填充事件 。


推荐阅读