HelloFresh是一家食品電商初創(chuàng)公司,用戶(hù)根據(jù)選定的菜譜下單,HelloFresh把菜譜所需要的食材送至用戶(hù)家中。來(lái)自HelloFresh的技術(shù)負(fù)責(zé)人ítalo Lelis在博客上分享了HelloFresh的API網(wǎng)關(guān)落地實(shí)踐,本文為該博文的譯文,并已獲得原網(wǎng)站的翻譯授權(quán)。 HelloFresh的規(guī)模一直保持著增長(zhǎng)的態(tài)勢(shì),我們的產(chǎn)品在持續(xù)改進(jìn),新的想法不斷涌現(xiàn)出來(lái),我們擁有完全自動(dòng)化的供應(yīng)鏈。持續(xù)的增長(zhǎng)給我們帶來(lái)了驚喜,同時(shí)也帶來(lái)了技術(shù)方面的挑戰(zhàn)。
在這篇文章里,我將會(huì)和大家分享我們的基礎(chǔ)設(shè)施所經(jīng)歷的一次重大遷移,這次遷移保證了以后的路我們可以走得更快、更靈活,也更安全。
我們最近開(kāi)發(fā)了一個(gè)API網(wǎng)關(guān)(github.com/hellofresh/janus),所以接下來(lái)需要在不停機(jī)的情況下對(duì)網(wǎng)關(guān)后面的主API(單體系統(tǒng))進(jìn)行遷移改造。升級(jí)之后,我們希望能夠開(kāi)發(fā)更多的微服務(wù)系統(tǒng),并且無(wú)縫對(duì)接到目前我們的基礎(chǔ)架構(gòu)中。
API網(wǎng)關(guān)處在基礎(chǔ)設(shè)施的最外層,它每天需要接收大量的請(qǐng)求,所以我們選擇了Go語(yǔ)言來(lái)構(gòu)建網(wǎng)關(guān),因?yàn)镚olang性能好、簡(jiǎn)單易用,而且提供了優(yōu)雅的并發(fā)解決方案。我們手頭已經(jīng)有很多現(xiàn)成的工具,它們可以簡(jiǎn)化我們的遷移工作。
服務(wù)發(fā)現(xiàn)和客戶(hù)端負(fù)載均衡
我們使用Consul作為服務(wù)發(fā)現(xiàn)工具,它和HAProxy配合起來(lái)使用可以幫我們解決微服務(wù)架構(gòu)的兩個(gè)主要問(wèn)題:服務(wù)發(fā)現(xiàn)(新服務(wù)上線(xiàn)時(shí)會(huì)自動(dòng)注冊(cè))和客戶(hù)端負(fù)載均衡(把請(qǐng)求均衡地分發(fā)到各個(gè)服務(wù)器上)。
我們的工具箱里最有用的工具或許要數(shù)基礎(chǔ)設(shè)施的自動(dòng)化。我們使用Ansible在云端管理資源,包括單機(jī)、網(wǎng)絡(luò)、DNS、運(yùn)行持續(xù)集成工具的主機(jī),等等。按照我們的慣例,開(kāi)發(fā)一個(gè)新服務(wù)時(shí),我們工程師的第一件事情就是為這個(gè)服務(wù)創(chuàng)建Ansible腳本。
從某種程度上說(shuō),我們應(yīng)該監(jiān)控基礎(chǔ)設(shè)施里的所有東西。在日志和監(jiān)控應(yīng)用方面,我們有一些最佳實(shí)踐。
辦公室里有儀表盤(pán)(就是國(guó)內(nèi)公司里的大電視屏,顯示系統(tǒng)狀態(tài)),我們?cè)谌魏螘r(shí)候都可以查看系統(tǒng)的運(yùn)行情況。
我們使用ELK技術(shù)棧來(lái)收集日志,從而可以快速地分析服務(wù)的運(yùn)行情況。
我們使用Statsd和Grafana作為監(jiān)控工具,這些工具總會(huì)給我們帶來(lái)驚喜。
Grafana的儀表盤(pán)為性能度量指標(biāo)提供了非常完美的視角。
盡管有了這些工具,我們?nèi)匀挥幸粋€(gè)棘手的問(wèn)題需要解決:理清當(dāng)前的架構(gòu),然后想清楚如何順利地進(jìn)行遷移。我們花了一些時(shí)間對(duì)遺留系統(tǒng)進(jìn)行了重構(gòu),讓它們支持新的網(wǎng)關(guān),同時(shí)我們也加入了認(rèn)證服務(wù)。在這個(gè)過(guò)程中,我們遇到了一些問(wèn)題。
雖然我們可以對(duì)移動(dòng)應(yīng)用進(jìn)行更新,但也要考慮到有些用戶(hù)可能不愿意升級(jí),所以我們要保持向后兼容,比如DNS,我們要確保舊版本也能正常工作。
我們需要整理出所有公開(kāi)和私有的API端點(diǎn),并讓它們自動(dòng)地注冊(cè)到網(wǎng)關(guān)上。
我們需要把認(rèn)證工作從主API遷移到新的認(rèn)證服務(wù)上。
確保網(wǎng)關(guān)和微服務(wù)之間通信的安全性。
為了解決這些問(wèn)題,我們寫(xiě)了一個(gè)Go腳本,這個(gè)腳本會(huì)讀取OpenAPI規(guī)范(Swagger)文件并為API資源創(chuàng)建規(guī)則(比如速率限定、配額、CORS等)代理。
我們?cè)趕taging環(huán)境搭建了整個(gè)基礎(chǔ)設(shè)施,并在上面運(yùn)行自動(dòng)化測(cè)試,對(duì)服務(wù)間的通信進(jìn)行了測(cè)試。不得不說(shuō),自動(dòng)化staging測(cè)試在整個(gè)遷移過(guò)程中起到了很大的作用。我們有很多功能測(cè)試用例,這些用例保證了主API的功能是完好的。
在確保了staging環(huán)境一切正常之后,我們開(kāi)始考慮如何將它們推到生產(chǎn)環(huán)境。
可以告訴大家的是,我們的第一次嘗試簡(jiǎn)直是災(zāi)難性的。盡管我們已經(jīng)做足了計(jì)劃,不過(guò)仍然不足以把它們推向生產(chǎn)環(huán)境。先來(lái)看看我們的初始計(jì)劃。
把最新的API網(wǎng)關(guān)部署到staging環(huán)境
把主API的變更部署到staging環(huán)境
在staging環(huán)境運(yùn)行自動(dòng)化功能測(cè)試
通過(guò)網(wǎng)站和移動(dòng)端進(jìn)行staging環(huán)境的手動(dòng)測(cè)試
把最新的API網(wǎng)關(guān)部署到生產(chǎn)環(huán)境
把主API的變更部署到生產(chǎn)環(huán)境
在生產(chǎn)環(huán)境運(yùn)行自動(dòng)化功能測(cè)試
通過(guò)網(wǎng)站和移動(dòng)端進(jìn)行生產(chǎn)環(huán)境的手動(dòng)測(cè)試
慶祝勝利
在staging環(huán)境一切進(jìn)展得都很順利,當(dāng)我們準(zhǔn)備進(jìn)入生產(chǎn)環(huán)境時(shí),問(wèn)題出現(xiàn)了。
數(shù)據(jù)庫(kù)被沖垮,我們不得不馬上回滾。幸運(yùn)的是,我們的監(jiān)控系統(tǒng)捕獲到了從認(rèn)證服務(wù)獲取令牌的問(wèn)題。
從第一次失敗中吸取了教訓(xùn),我們知道我們還沒(méi)有為進(jìn)入生產(chǎn)環(huán)境做好準(zhǔn)備,于是在回滾之后,立即對(duì)問(wèn)題展開(kāi)診斷。在再次嘗試之前,我們做了一些改進(jìn)。
準(zhǔn)備藍(lán)綠(blue-green)部署過(guò)程。我們?yōu)樯a(chǎn)環(huán)境創(chuàng)建了一個(gè)副本,包括已經(jīng)部署好的網(wǎng)關(guān),通過(guò)一些簡(jiǎn)單的配置變更就能讓整個(gè)集群運(yùn)行起來(lái),如果需要回滾,也只需做一些簡(jiǎn)單的配置變更。
從當(dāng)前的系統(tǒng)收集更多的度量指標(biāo),這樣可以幫助我們決定該使用多少機(jī)器來(lái)處理負(fù)載。我們利用第一次嘗試時(shí)所使用的數(shù)據(jù)作為探針,并使用Gatling來(lái)運(yùn)行負(fù)載測(cè)試,確保我們可以應(yīng)付預(yù)期的流量。
再次進(jìn)入生產(chǎn)環(huán)境之前,我們對(duì)認(rèn)證服務(wù)的已知問(wèn)題進(jìn)行了修復(fù),包括一個(gè)大小寫(xiě)問(wèn)題、一個(gè)JWT簽名的性能問(wèn)題,并添加了更多的日志和監(jiān)控。
我們花費(fèi)了一個(gè)禮拜來(lái)完成上述的工作,之后的部署進(jìn)展得很順利,中間沒(méi)有停機(jī)。不過(guò)盡管部署進(jìn)展得很順利,我們?nèi)匀话l(fā)現(xiàn)了一些在自動(dòng)化測(cè)試中沒(méi)有發(fā)現(xiàn)的個(gè)別問(wèn)題,不過(guò)這些問(wèn)題最終得到修復(fù),并沒(méi)有對(duì)系統(tǒng)造成太大影響。
最終的架構(gòu)如下圖所示。
主API
4個(gè)應(yīng)用服務(wù)器
4個(gè)應(yīng)用服務(wù)器
其它
使用Ansible批量管理遠(yuǎn)程服務(wù)器
使用Amazon CloudFront作為CDN/WAF
使用Consul和HAProxy作為服務(wù)發(fā)現(xiàn)和客戶(hù)端負(fù)載均衡工具
使用Stasd和Grafana收集系統(tǒng)度量指標(biāo)并觸發(fā)告警
使用ELK技術(shù)棧從不同的服務(wù)收集日志
使用Concourse CI作為持續(xù)集成工具
今日薦文
點(diǎn)擊下方圖片即可閱讀