
本文介紹了 Shopify 構(gòu)建彈性平臺(tái)的方法。這篇文章不僅讀起來(lái)有意思,而且你可以把它運(yùn)用到實(shí)踐中,構(gòu)建自有的彈性平臺(tái)。Shopify面臨的擴(kuò)展挑戰(zhàn)電商解決方案提供商 Shopify 每個(gè)月的獨(dú)立訪問(wèn)用戶大約有 3 億。注意,這些用戶訪問(wèn)并不是均勻分布的。
其中一個(gè)最大的挑戰(zhàn)是“閃購(gòu)”,即最流行的那些網(wǎng)店在特定時(shí)間內(nèi)的銷售活動(dòng)。
例如, Kanye West 開賣新款鞋子。加上 Kim Kardashian ,他們?cè)?Twitter 上有 5,000 萬(wàn)粉絲。
有些客戶還在超級(jí)碗上打廣告。因此, Shopify 根本無(wú)法預(yù)期屆時(shí)有多大的訪問(wèn)流量。想想這種情況:在 3 點(diǎn), 200,000 訪客一涌而入,參與幾小時(shí)后就會(huì)結(jié)束的特賣活動(dòng)。
Shopify 該如何擴(kuò)展,以應(yīng)對(duì)突然增加的訪問(wèn)?即使擴(kuò)展后不能很好地應(yīng)對(duì)某一場(chǎng)特賣,那么怎么確保這場(chǎng)特賣不會(huì)影響其它網(wǎng)店呢?在下一節(jié),我們首先介紹 Shopify 的應(yīng)用架構(gòu),然后以此為背景,深入地討論上述問(wèn)題。Shopify 應(yīng)用架構(gòu)去年, Shopify 全面采用 Docker ,但是仍然采用單體的應(yīng)用架構(gòu)。 Simon 告訴我,之所以這么做,是因?yàn)檗D(zhuǎn)向微服務(wù)架構(gòu)的代價(jià)不低。當(dāng)然,由于全面采用 Docker ,如果他們將來(lái)決定轉(zhuǎn)向微服務(wù)架構(gòu),也比較容易。
總之, Shopify 的架構(gòu)大致是這樣的:應(yīng)用請(qǐng)求首先發(fā)送到 Nginx ,然后再轉(zhuǎn)發(fā)到服務(wù)器應(yīng)用集群,每個(gè)服務(wù)器應(yīng)用是一個(gè)運(yùn)行 Rails 應(yīng)用的 Docker 容器。
在數(shù)據(jù)層,他們用到了:MemcachedRedisElasticSearchMySQLKafkaZooKeeper大部分軟件運(yùn)行自有的硬件上,少部分運(yùn)行在 AWS 上。
為了減少成本, Shopify 運(yùn)營(yíng)了一個(gè)多租戶平臺(tái),即不同的網(wǎng)店可能運(yùn)行在同一臺(tái)服務(wù)器上——例如, shopA.com 和 shopB.com 運(yùn)行在一臺(tái)服務(wù)器上。
雖然全面轉(zhuǎn)向 Docker 并非一帆風(fēng)順,但是最終獲得了下列好處:
只需大約 5 分鐘,就能運(yùn)行完數(shù)十萬(wàn)行 Ruby 代碼的持續(xù)集成(沒(méi)用 Docker 之前需要 15 分鐘),部署到橫跨 3 個(gè)數(shù)據(jù)中心的 300-400 臺(tái)服務(wù)器上只需 3 分鐘(以前需要 15 分鐘)。多么令人印象深刻的成效。如何處理流量激增平臺(tái)最好自己就能處理訪問(wèn)的激增。不過(guò),這還沒(méi)完全實(shí)現(xiàn),在每次大型售賣之前,他們運(yùn)行一系列的性能檢測(cè)。
以上面的 Kanye West 為例,他們提前花了兩周的時(shí)間,把平臺(tái)的關(guān)鍵部分組合在一起,進(jìn)行廣泛的被動(dòng)負(fù)載測(cè)試和性能優(yōu)化。
為了運(yùn)行不同的測(cè)試,他們用到了彈性矩陣:
摘自 Simon 的大會(huì)報(bào)告
在某項(xiàng)服務(wù)失效時(shí),彈性矩陣有助于搞清楚系統(tǒng)出了什么問(wèn)題。
假設(shè) Redis 服務(wù)不可用了。從彈性矩陣可以看出, Redis 是買單服務(wù)的一部分。這時(shí)候,是不是要整個(gè)網(wǎng)站下線,進(jìn)入維護(hù)狀態(tài)呢?當(dāng)然不,可以讓每個(gè)用戶登出網(wǎng)站,仍然允許他們?cè)跊](méi)有客戶賬戶的情況下繼續(xù)買單。然后,一旦 Redis 服務(wù)恢復(fù)了,將電子郵件地址與客戶賬戶關(guān)聯(lián),據(jù)此補(bǔ)上此前缺少的信息。
依次下線每一個(gè)服務(wù)(像網(wǎng)店前端、管理面板、API等等),看看此時(shí)系統(tǒng)的運(yùn)行情況——這是否影響到系統(tǒng)的其它部分?盡量去掉服務(wù)之間的依賴,整個(gè)應(yīng)用的彈性會(huì)因此顯著地增加。這好比一條拉鏈,最弱的那一環(huán)決定了應(yīng)用的健壯程度。
Shopify 開源了與之相關(guān)的兩個(gè)工具: Toxiproxy 和 Semian 。
Toxiproxy 能夠控制系統(tǒng)的延遲。
Semian 用于檢驗(yàn)系統(tǒng)是否存在單點(diǎn)失效。
更多細(xì)節(jié),請(qǐng)看 Simon 的大會(huì)報(bào)告(https://speakerdeck.com/sirupsen/dockercon-2015-resilient-routing-and-discovery),非常有意思的一個(gè)報(bào)告。
在彈性平臺(tái)之上,由于 Shopify 擁有自己的硬件,它能夠做到超額配置。對(duì)他們而言,這種解決方案很便宜,但是還是比在云上運(yùn)行花費(fèi)高。請(qǐng)仔細(xì)比較相應(yīng)的代價(jià)和收益,確定這種方案是否適合你的需求。
數(shù)據(jù)存儲(chǔ)的擴(kuò)展是另外一個(gè)巨大的挑戰(zhàn)。由于 Shopify 處理的是金融交易,他們的數(shù)據(jù)庫(kù)必須保持同步。解決方案是什么呢? 兩年前 Shopify 就開始實(shí)施 MySQL 分片了。他們非常激進(jìn),力求經(jīng)過(guò)一段時(shí)間后把數(shù)據(jù)庫(kù)切分成更多更小的切片。
Simon 隨即說(shuō)道,數(shù)據(jù)庫(kù)的擴(kuò)展尤其是切片是相當(dāng)難的。不到最后,別采用數(shù)據(jù)庫(kù)切片,盡可能地利用緩存。采用切片后的一個(gè)好處是有助于事故的隔離。如果在某個(gè)切片中某個(gè)客戶的數(shù)據(jù)發(fā)生災(zāi)難,也只會(huì)影響整個(gè)平臺(tái)的一小部分。
說(shuō)到對(duì)彈性的測(cè)試, Simon 強(qiáng)調(diào)說(shuō)有了彈性平臺(tái)和自動(dòng)災(zāi)后恢復(fù)機(jī)制,大部分?jǐn)?shù)據(jù)庫(kù)擴(kuò)展問(wèn)題都已經(jīng)被解決了。接下來(lái),他們準(zhǔn)備提高哪些方面?接下來(lái), Shopify 團(tuán)隊(duì)正在審視應(yīng)用之間的隔離問(wèn)題。另外一個(gè)主要問(wèn)題是如何讓網(wǎng)店同時(shí)運(yùn)行在位于不同大洲的多個(gè)數(shù)據(jù)中心上。這不僅非常有利于保證數(shù)據(jù)本地性,也能避免意外事件的影響。
我訪問(wèn) Jeremy Edberg 時(shí),他說(shuō)過(guò) Netflix 也投入很多資源研究如何避免意外事件的影響。
除此之外,他們也在研究如何實(shí)現(xiàn)一天內(nèi)的多次災(zāi)后恢復(fù)。在訪談 Simon 的頁(yè)面,你能了解到他們?nèi)绾卧谡麄€(gè)數(shù)據(jù)中心進(jìn)行災(zāi)后恢復(fù)測(cè)試。
目前,如果要實(shí)現(xiàn)整個(gè)數(shù)據(jù)中心的災(zāi)后恢復(fù),就不得不臨時(shí)關(guān)閉買單服務(wù)。他們正在尋找相關(guān)的解決方案。