Instagram成功背后的工程技術(shù)秘密
Instagram是許多創(chuàng)業(yè)公司的楷模,十幾個人的公司,從剛開始的默默無聞到***被Facebook重金收購。這么一家公司,從最開始的操作系統(tǒng)選擇,服務(wù)器到數(shù)據(jù)庫選擇,消息推送,都是如何進行的?本文編譯自Instagram工程博客,告訴你Instagram的技術(shù)“秘密”。 在選擇一個系統(tǒng)的時候,我們的核心原則就是:盡量簡單;不做重復(fù)工作;盡量采用經(jīng)過驗證的靠譜的技術(shù)。
操作系統(tǒng)/托管
因為當(dāng)時我們只有三個人,而且需求也不是很多,還沒有到自己建立服務(wù)器的地步,所以考慮托管,采用的是 Amazon EC2上的Ubuntu Linux 11.04 (Natty Narwhal )系統(tǒng),以前版本的Ubuntu在EC2上面跑的時候如果遇到高流量會莫名其妙地死機,但是Natty(Ubuntu的一個版本代號)就沒問題,可能隨著應(yīng)用發(fā)展以及使用的增加,我們會建立自己的服務(wù)器。
負(fù)載平衡
每個發(fā)送到Insagram的請求都要通過負(fù)載平衡器,當(dāng)時我們用2臺 nginx服務(wù)器以及DNS輪叫調(diào)度承載前端請求,這種方法的負(fù)面影響就是,如果一臺機器癱瘓,DNS就得花時間進行更新,于是最近我們使用亞馬遜的彈性負(fù)載均衡器(Elastic Load Balancer),我們也在ELB曾停掉了SSL,減小NGINX上CPU壓力,DNS服務(wù)則使用亞馬遜的Route53,最近AWS提供了非常不錯的GUI工具。
應(yīng)用服務(wù)器
接下來就是請求的處理,啟用的是亞馬遜 High-CPU Extra-Large 中的Django框架,隨著使用的增加,Diango數(shù)量從最開始的幾個增加到超過25個。同時我們采用 http://gunicorn.org/ 作為WSGI服務(wù)器,通常我們都習(xí)慣使用 mod_wsgi 和Apache,后來發(fā)現(xiàn)Gunicorn更容易配置,而且是CPU密集型,如果要同時運行多個實例指令,我們就采用 Fabric(最近增添了幾個有用的平行模式)。
數(shù)據(jù)儲存
我們的大多數(shù)數(shù)據(jù)(用戶信息,照,標(biāo)簽等等)都存在 PostgreSQL中,我們曾寫過關(guān)于如何在不同 Postgres實例之間共享,我們的主要共享集群包含12個 Quadruple Extra-Large內(nèi)存實例。
我們發(fā)現(xiàn)亞馬遜的網(wǎng)絡(luò)磁盤系統(tǒng)(EBS)的每秒尋道能力不足,所以就將數(shù)據(jù)盡量保存到內(nèi)存中,為了達到合理的IO性能,我們在使用Mdadm工具的RAID軟件中啟用EBS驅(qū)動。
后來發(fā)現(xiàn) vmtouch這種內(nèi)存數(shù)據(jù)管理軟件很好用,尤其是在將故障從一臺設(shè)備轉(zhuǎn)到另一臺機器時候,表現(xiàn)很不錯,這是我們我們對vmtouch運行的分析腳本,以及為了與現(xiàn)在的內(nèi)存狀態(tài)相匹配而對應(yīng)的vmtouch輸出指令,
為了將數(shù)據(jù)庫與我們的應(yīng)用服務(wù)器相連,我們采用 Pgbouncer,照片本身會直接分享到亞馬遜的S3,利用亞馬遜的CloudFront 作為我們的CDN以節(jié)省圖片載入時間。
另外,我們還使用Redis,但由于所有Redis數(shù)據(jù)都需要與內(nèi)存匹配,所以我們就停止運行一些Quadruple Extra-Large Memory案例,只在一些特定的子系統(tǒng)中分享一些Redis實例。
對于我們的 geo-search API,已經(jīng)使用PostgreSQL 幾個月了,不過如果分享了媒體入口,就會使用 Apache Solr,我們這個API還有一個非常簡單的JSON接口,對于我們的應(yīng)用來說,這相當(dāng)于另一個API。
***,和任何現(xiàn)代Web服務(wù)一樣,我們使用 Memcached 來進行緩存,現(xiàn)在我們有6個 Memcached實例,然后用pylibmc & libmemcached進行連接(亞馬遜最近還推出了一個Elastic Cache)。
任務(wù)隊列/消息推送
當(dāng)有用戶將Insagram圖片分享到Twitter或者Facebook的時候,或者當(dāng)我們想要知道用戶何時上傳圖片的時候,我們就用Danga開發(fā)的任務(wù)隊列系統(tǒng)German來處理,這樣一來,不用同時處理任務(wù)隊列,上傳媒體文件就非???。
關(guān)于消息推送,我們找到的最節(jié)約成本的方案就是https://github.com/samuraisam/pyapns,這是一個開源服務(wù),能為我們處理幾十億消息推送,絕對靠譜。
監(jiān)控
前面的服務(wù)器實例加起來差不多有100多個,所以有效監(jiān)控實例非常重要,我們用 Munin監(jiān)控我們整個系統(tǒng),系統(tǒng)任何異常就及時提醒我們。我們也基于Python-Munin寫了不少定制插件來檢測一些非系統(tǒng)及的特征(比如每秒注冊數(shù)量,每秒圖片上傳數(shù)量等),同時利用Pingdom 作為服務(wù)器外部監(jiān)控工具,并利用PagerDuty作為消息通知以及突發(fā)事件處理工具。
對于Python錯誤報告,使用開源的DIango應(yīng)用Sentry來處理,可以在任何時候登陸并實時查看系統(tǒng)中出現(xiàn)了哪些錯誤。
【編輯推薦】