3年从0到300万用户,我们怎样在高速发展中扩展云基础设施?

原标题:3年从0到300万用户 , 我们怎样在高速发展中扩展云基础设施?
作者|KareemAyesh
译者|张卫滨
策划|万佳
Meddy是一家创业公司 , 成立4年 , 用户从0增长到300万 。 高速发展过程中 , 它经历了很多技术方面的变化 。 本文分享了它们在云基础设施方面的实践 。
1我们的单体应用
我记得CEO告诉我 , 他的代码比我写的任何代码都好 , 当我问他为什么 , 他说“因为我的代码已经被成千上万的人使用了” 。
……他是对的 。

3年从0到300万用户,我们怎样在高速发展中扩展云基础设施?
文章图片
技术债
使用单体结构本身并不是什么问题 。 只是 , 对于大多数单体应用来讲 , 随着它不断演化 , 最终将会作茧自缚 , 而这恰好是我们经历的 。
也就是说 , 这意味着在项目的生命周期中会出现很多的问题 。
但是 , 我们所担心的并不是技术方面本身的问题 , 而是最终无法解决它们的宿命 。
单体的存在就意味着问题就像进入了死胡同 。 请求添加的特性越多 , 出现的问题也就越多 , 解决这些问题就像创建新特性一样自然 。
基础设施最初的重构和更新对应用的增长是至关重要的 , 这反过来又为可能出现的问题提前提供了潜在的解决方案 。 这样一来 , 对新功能的要求就不会引发一连串的推诿扯皮或更糟的“我认为现在这是不可能的” 。
2敲门砖
在当前的单体架构中 , 数据持久化是一个令人头疼的大问题 。 上传的镜像、数据库和日志都必须备份到根文件系统中 , 当新实例启动的时候会用到它们 。 当时没有staging实例 , 所以测试都是在生产环境进行的 , 服务器频繁出现故障 , 从而危及我们的数据 。
另外一个需要解决的大问题就是部署 。 部署是通过SSH和直接从Githuborigin上gitpull代码完成的 , 没有任何形式的脚本来自动化新进程启动、运行测试以及报告错误的过程 。
解决方案
显然 , 我们需要有一些变化 , 我们决定除了应用代码的变更外 , 还需要对基础设施进行一些小的变更 , 也就是将数据库和上传的文件放到单独的服务中 。
通过使用AWS的三个服务 , 解决了如下三个问题:
使用RDS管理Postgres数据库使用S3存储上传的媒体文件使用ElasticBeanstalk管理部署
3年从0到300万用户,我们怎样在高速发展中扩展云基础设施?
文章图片
重申一下 , 我们在这个项目中所做的整体变更并没有对基础设施带来很大的改善 。 这种分离只是保证应用程序中未来的问题不会损害任何敏感的东西 。 此外 , 由于在主EC2实例上只有一个应用程序 , 这意味着任何额外的资源都可以存在于独立的服务器或服务上而没有任何问题 。
但这并不完美:
Celery和Redis运行在和应用本身所在的服务器上前端应用采用了AngularJS和Django的混合渲染 , 有时候这会阻塞处理器日志存储在文件服务器上(并没有其他可用的地方)当时 , 业务量比较低 , 我们并没有太多的服务甚至太多的特性 , 所以这些问题都是可以容忍的 。
不过 , 这个项目提供了一个很重要的敲门砖 , 并为以后奠定了坚实的基础 。
3搜索
搜索是一个令人沮丧的功能 , 它会耗费很长时间 , 但并不是十分精准 。 我们以前使用Postgres的TrigramSimilarity来实现搜索功能 。 针对大量记录进行搜索的话 , 它并不是最快的方案 , 而且针对多字段的搜索也并不准确 。
最重要的是 , 我们无法真正控制这些搜索的行为 。 我们希望跟踪所有在搜索查询中遇到的问题 。

3年从0到300万用户,我们怎样在高速发展中扩展云基础设施?
文章图片
我们用GoogleSheet记录了所有想要对搜索功能进行的改善
解决方案
搜索会占用其所在实例的大量资源 。 与其扩展实例并继续在实例中运行搜索 , 我们决定采用一个不同的方案 , 那就是启用一个单独的服务 , 在EC2实例上运行ElasticSearch 。 每当有新的记录创建或更新的时候 , 我们就会更新该EC2实例中的一个索引 。 另外 , 还有一个cronjob定时更新完整的索引 。

3年从0到300万用户,我们怎样在高速发展中扩展云基础设施?
文章图片
添加ElasticSearch
经过我们反复迭代 , 最终形成了更好以及更加可控的搜索功能 , 这个过程中没有对ElasticSearch服务上运行的镜像进行太大的修改 。
4负载均衡
在每次部署的时候 , 我们都会经历10秒钟的停机时间 。 部署是由ElasticBeanstalk负责的 。 在底层 , EB会并行运行新的(ondeck)和旧的(current)应用 , 并且会在所有的执行脚本成功时进行一个符号链接(symlink) 。 因为我们使用的是一个服务器 , 所以符号链接会导致5到10秒的停机时间 , 这是我们需要解决的 。