Instagram是许多创业公司的楷模,十几个人的公司,从刚开始的默默无闻到***被Facebook重金收购。这么一家公司,从最开始的操作系统选择,服务器到数据库选择,消息推送,都是如何进行的?本文编译自Instagram工程博客,告诉你Instagram的技术“秘密”。 在选择一个系统的时候,我们的核心原则就是:尽量简单;不做重复工作;尽量采用经过验证的靠谱的技术。
操作系统/托管
因为当时我们只有三个人,而且需求也不是很多,还没有到自己建立服务器的地步,所以考虑托管,采用的是 Amazon EC2上的Ubuntu Linux 11.04 (Natty Narwhal )系统,以前版本的Ubuntu在EC2上面跑的时候如果遇到高流量会莫名其妙地死机,但是Natty(Ubuntu的一个版本代号)就没问题,可能随着应用发展以及使用的增加,我们会建立自己的服务器。
负载平衡
每个发送到Insagram的请求都要通过负载平衡器,当时我们用2台 nginx服务器以及DNS轮叫调度承载前端请求,这种方法的负面影响就是,如果一台机器瘫痪,DNS就得花时间进行更新,于是最近我们使用亚马逊的弹性负载均衡器(Elastic Load Balancer),我们也在ELB曾停掉了SSL,减小NGINX上CPU压力,DNS服务则使用亚马逊的Route53,最近AWS提供了非常不错的GUI工具。
应用服务器
接下来就是请求的处理,启用的是亚马逊 High-CPU Extra-Large 中的Django框架,随着使用的增加,Diango数量从最开始的几个增加到超过25个。同时我们采用 http://gunicorn.org/ 作为WSGI服务器,通常我们都习惯使用 mod_wsgi 和Apache,后来发现Gunicorn更容易配置,而且是CPU密集型,如果要同时运行多个实例指令,我们就采用 Fabric(最近增添了几个有用的平行模式)。
数据储存
我们的大多数数据(用户信息,照,标签等等)都存在 PostgreSQL中,我们曾写过关于如何在不同 Postgres实例之间共享,我们的主要共享集群包含12个 Quadruple Extra-Large内存实例。
我们发现亚马逊的网络磁盘系统(EBS)的每秒寻道能力不足,所以就将数据尽量保存到内存中,为了达到合理的IO性能,我们在使用Mdadm工具的RAID软件中启用EBS驱动。
后来发现 vmtouch这种内存数据管理软件很好用,尤其是在将故障从一台设备转到另一台机器时候,表现很不错,这是我们我们对vmtouch运行的分析脚本,以及为了与现在的内存状态相匹配而对应的vmtouch输出指令,
为了将数据库与我们的应用服务器相连,我们采用 Pgbouncer,照片本身会直接分享到亚马逊的S3,利用亚马逊的CloudFront 作为我们的CDN以节省图片载入时间。
另外,我们还使用Redis,但由于所有Redis数据都需要与内存匹配,所以我们就停止运行一些Quadruple Extra-Large Memory案例,只在一些特定的子系统中分享一些Redis实例。
对于我们的 geo-search API,已经使用PostgreSQL 几个月了,不过如果分享了媒体入口,就会使用 Apache Solr,我们这个API还有一个非常简单的JSON接口,对于我们的应用来说,这相当于另一个API。
***,和任何现代Web服务一样,我们使用 Memcached 来进行缓存,现在我们有6个 Memcached实例,然后用pylibmc & libmemcached进行连接(亚马逊最近还推出了一个Elastic Cache)。
任务队列/消息推送
当有用户将Insagram图片分享到Twitter或者Facebook的时候,或者当我们想要知道用户何时上传图片的时候,我们就用Danga开发的任务队列系统German来处理,这样一来,不用同时处理任务队列,上传媒体文件就非常快。
关于消息推送,我们找到的最节约成本的方案就是https://github.com/samuraisam/pyapns,这是一个开源服务,能为我们处理几十亿消息推送,绝对靠谱。
监控
前面的服务器实例加起来差不多有100多个,所以有效监控实例非常重要,我们用 Munin监控我们整个系统,系统任何异常就及时提醒我们。我们也基于Python-Munin写了不少定制插件来检测一些非系统及的特征(比如每秒注册数量,每秒图片上传数量等),同时利用Pingdom 作为服务器外部监控工具,并利用PagerDuty作为消息通知以及突发事件处理工具。
对于Python错误报告,使用开源的DIango应用Sentry来处理,可以在任何时候登陆并实时查看系统中出现了哪些错误。
【编辑推荐】