3年从0到300万用户,我们怎样在高速发展中扩展云基础设施?( 二 )
解决方案
为了解决这个问题 , 我们需要在多个服务器上进行滚动部署 。 这是一个相对比较简单的过程 , 只需要在我们的ElasticBeanstalk管理的自动扩展组(Autoscalinggroup)前面添加一个[应用负载均衡器ApplicationLoadBalancer就可以了 。
https://rollout.io/blog/rolling-deployment/
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html
文章图片
添加负载均衡器
滚动部署增加了测试开销 , 也带来了更长的部署时间 , 但是彻底消除了停机的问题 。
5渲染和SEO
过去 , 我们采用了混合渲染的方式 , 其中Django应用会部分渲染HTML , 而在客户端会运行AngularJS应用 。 这导致了很多问题:
我们的渲染非常慢并且会困住开发团队和服务器 。 我们的服务器需要很多的处理能力才能进行渲染 , 响应时间出现了难以避免的瓶颈 。 甚至开发都变得非常困难 , 因为一个变更我们就需要编码很多次 。 在某些情况下 , 改变一个跟踪事件都是很困难的 。
https://docs.djangoproject.com/en/3.0/topics/performance/#alternatives-to-django-s-template-language
糟糕的构建系统导致了高负载时间 。 我们过去使用自己的构建系统 , 因为对于混合渲染来说 , 没有AngularJS构建管理器 , 我们自己的系统有很多打包不一致和缓存问题 , 这导致了低效的构建和高负载时间 。 这也是一个需要改变和改进的问题 。
网站偶尔会卡住5到10分钟 。 当我们收到来自用户或机器人的大量请求时 , 服务器会打开太多与数据库的连接 , 导致数据库被挂起 。 A轮融资为Meddy带来更多的业务之后 , 在2019年底 , 这种情况每周都会发生 。 原因在于Django会打开一个数据库连接 , 该连接会一直处于打开状态 , 直到HTML渲染结束 。 因为打开了太多的数据库连接 , 这会导致服务器卡住 , 最终生成504响应 。
解决方案
在A轮融资后 , 我们开始将代码从混合渲染转向纯客户端渲染 。 为实现这一点 , 必须对后端服务请求的方式进行大量更改 。
我们决定使用S3的桶托管前端资源 , 并使用CloudFront分发响应 。 CloudFront还允许我们附加Lambda函数 , 从而能够非常细粒度地对请求进行所需的控制 。
我们进行混合渲染的一个重要原因是担心动态渲染会影响SEO , 而我们网站卡住的一个重要原因是机器人导致的请求暴增 。 通过预先渲染页面以及为机器人提供预先渲染的页面 , 这两个问题都得到了解决 。
https://community.cloudflare.com/t/anyone-else-in-the-recent-days-getting-small-attacks-from-facebook-bots/89019
为了实现这一点 , 我们使用了一个名为prerender.io的服务 , 它能预渲染请求页面、缓存这些页面并将这些页面提供给机器人 。 基于HTTP请求的User-agent , 我们在所使用的CloudFront分发版本的LambdaEdge函数中新增了一个机器人探测机制 。 如果探测到机器人的话 , 它们就会被重定向到prerender.io , 从而得到一个缓存的页面 。
https://prerender.io/
文章图片
添加预渲染和机器人探测
【3年从0到300万用户,我们怎样在高速发展中扩展云基础设施?】很重要的一点需要注意 , 一旦我们达到300,000个页面 , prerender.io的成本就会变得非常高 , 所以必须要有自己的预渲染服务 。 于是 , 我们使用S3实现了自己的缓存机制 , 并使用ECSFargate来托管服务 。
6共享缓存和调度任务
缓存资源无法在服务器之间共享 。 缓存资源无法在服务器之间共享 , 这意味着有些请求是被缓存的 , 而有些则是没有被缓存的 。 另外 , 我们也遇到了服务器上的Redis问题 。 Redis在服务器上有调度的数据转储 , 当磁盘空间被其他服务占用的时候 , 这会导致停机 , 这样的情况曾经出现过两次 。
调度任务需要在一台服务器上运行 。 CeleryBeat具有内置的功能以便于在特定的日期和时间运行任务 , 并且会生成事件流 , 该事件流会以表的形式存储在数据库中 。 对我们来说 , 这是非常有用的 , 因为我们可以使用它在预约前后的特定时间间隔发送提醒短信 。 假如将它保存在服务器上 , 将会导致任务重复执行 , 这主要会在我们的通知模块中引发冲突 。
https://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html
解决方案
因为我们要基于负载均衡器使用多台服务器 , 后端必须要共享类似的缓存服务器 。 为了实现这一点 , 我们使用了ElastiCache 。 初始环境的搭建非常容易 , 更具挑战性的方面是我们的任务管理器 , 它在每台服务器上由CeleryBeat进行管理 。
- 李易峰笑起来太“蛊”人了,粉丝:岁月在哥哥脸上好像从来没有停留过
- “侯佩岑道歉”被骂上热搜,她母亲林月云,当年到底做了什么?
- 初三女儿总请朋友来家玩,父母无意看到监控内容,顿时火冒三丈
- 到店实拍三菱欧蓝德,前脸很经典,内饰机械感足,15.98万起
- 小时候被它粘到哭,现在村里却有农民靠采集野生鬼针草养家糊口
- 高端市场|发布至今下跌1000元,6400万四摄+8GB,从高端市场跌至中端市场
- 起售价定到四千多,魅族18自信满满,会走坚果手机老路吗?
- 这类新职业火了!超四成从业者年薪超10万元
- 降!降!降!政府工作报告提到的降费内容有哪些
- 香椿|西安香椿一斤最贵卖到45元 这两天价格回落
