編者的話|本文來自 Nginx 官方博客哩盲,是「Chris Richardson 微服務(wù)」系列的第六篇文章。第一篇介紹了微服務(wù)架構(gòu)模式闷游,并且討論了使用微服務(wù)的優(yōu)缺點(diǎn)广鳍。隨后的文章討論了微服務(wù)的不同方面,包括使用 API 網(wǎng)關(guān)蝶溶、進(jìn)程間通訊嗜历、服務(wù)發(fā)現(xiàn)和事件驅(qū)動(dòng)的數(shù)據(jù)管理。這篇文章將深入討論部署微服務(wù)的策略抖所。
作者介紹:Chris Richardson梨州,是世界著名的軟件大師,經(jīng)典技術(shù)著作《POJOS IN ACTION》一書的作者田轧,也是 cloudfoundry.com 最初的創(chuàng)始人暴匠,Chris Richardson 與 Martin Fowler、Sam Newman傻粘、Adrian Cockcroft 等并稱為世界十大軟件架構(gòu)師每窖。
Chris Richardson 所著所有文章已獨(dú)家授權(quán) DaoCloud 翻譯并刊載帮掉。
本系列包含 7 篇文章,介紹了微服務(wù)的設(shè)計(jì)窒典、構(gòu)建和部署蟆炊,并與傳統(tǒng)的單體架構(gòu)進(jìn)行了比較。本系列將分析微服務(wù)架構(gòu)的各種因素瀑志,你也將了解微服務(wù)架構(gòu)模型的優(yōu)劣涩搓、是否適合你的項(xiàng)目,以及如何應(yīng)用劈猪。
Chris Richardson 微服務(wù)系列全 7 篇:
本期內(nèi)容:
一昧甘、誘因
部署單體應(yīng)用意味著運(yùn)行大型應(yīng)用的多個(gè)相同副本,通常提供若干臺(tái)(N)服務(wù)器(物理機(jī)或虛擬機(jī))战得,在每臺(tái)服務(wù)器上運(yùn)行若干個(gè)(M)應(yīng)用實(shí)例充边。部署單體應(yīng)用并不總是簡單明了,但還是比部署微服務(wù)應(yīng)用簡單常侦。
微服務(wù)應(yīng)用由幾十甚至數(shù)百個(gè)服務(wù)組成浇冰。服務(wù)用不同的語言和框架寫成,每個(gè)都是一個(gè)小應(yīng)用刮吧,包括特定的部署湖饱、資源、擴(kuò)展和監(jiān)控需求杀捻,例如井厌,根據(jù)服務(wù)需求運(yùn)行若干數(shù)量的服務(wù)實(shí)例。此外致讥,每個(gè)服務(wù)實(shí)例必須配套提供適當(dāng)?shù)?CPU仅仆、內(nèi)存 和 I/O 資源。更具挑戰(zhàn)性的是垢袱,盡管如此復(fù)雜墓拜,部署服務(wù)還必須快速、可靠和性價(jià)比高请契。
微服務(wù)部署模式有多個(gè)咳榜,先從單主機(jī)多個(gè)服務(wù)實(shí)例開始講起。
二爽锥、單主機(jī)多服務(wù)實(shí)例模式
部署微服務(wù)的方法之一是使用單主機(jī)多服務(wù)實(shí)例模式涌韩。使用此模式,用戶要提供一到多臺(tái)物理或虛擬主機(jī)氯夷,在每個(gè)主機(jī)上運(yùn)行多個(gè)服務(wù)實(shí)例臣樱。很多情況下,這是傳統(tǒng)的應(yīng)用部署方法。每個(gè)服務(wù)實(shí)例在一個(gè)或多個(gè)主機(jī)的已知端口上運(yùn)行雇毫,主機(jī)通常被看做寵物玄捕。
下圖展示了這一模式的結(jié)構(gòu)。
這一模式有幾個(gè)變****型棚放。其中一個(gè)變型是服務(wù)實(shí)例作為進(jìn)程或進(jìn)程組枚粘。例如,在 Apache Tomcat 服務(wù)器上部署 Java 服務(wù)實(shí)例作為網(wǎng)頁應(yīng)用席吴,Node.js 服務(wù)實(shí)例可能包括一個(gè)父進(jìn)程和一個(gè)或多個(gè)子進(jìn)程赌结。
這一模式的另一個(gè)變型是在同一進(jìn)程或進(jìn)程組中運(yùn)行多個(gè)服務(wù)實(shí)例捞蛋。例如孝冒,在同一臺(tái) Apache Tomcat 服務(wù)器上部署多個(gè) Java 網(wǎng)頁應(yīng)用,或者在同一個(gè) OSGI 容器中運(yùn)行多個(gè) OSGI 捆綁組件拟杉。
單主機(jī)多服務(wù)實(shí)例模式有諸多優(yōu)點(diǎn)庄涡。****一個(gè)主要優(yōu)點(diǎn)就是資源利用相對高效,多服務(wù)實(shí)例共享服務(wù)器及其操作系統(tǒng)搬设。如果進(jìn)程或進(jìn)程組運(yùn)行多個(gè)服務(wù)實(shí)例穴店,效率更高,比如共享同一個(gè) Apache Tomcat 服務(wù)器和 JVM 的多個(gè)網(wǎng)頁應(yīng)用拿穴。
這個(gè)模式的另一大優(yōu)點(diǎn)是部署服務(wù)實(shí)例更快泣洞,只需將服務(wù)復(fù)制到主機(jī)并啟動(dòng)。如果服務(wù)用 Java 寫成默色,復(fù)制 JAR 或者 WAR 文件球凰;對于其它語言,如果是 Node.js 或者 Ruby腿宰,復(fù)制源代碼呕诉。在這兩種情況下,通過網(wǎng)絡(luò)復(fù)制的字節(jié)數(shù)比較小吃度。
此外甩挫,由于沒有太多開銷,啟動(dòng)服務(wù)通常很快椿每。如果服務(wù)自包含進(jìn)程伊者,只需要啟動(dòng)。如果是運(yùn)行在同一容器進(jìn)程或進(jìn)程組的服務(wù)實(shí)例间护,則需要?jiǎng)討B(tài)部署到容器中亦渗,或者重啟容器。
除了上述吸引力之外兑牡,單主機(jī)多服務(wù)實(shí)例模式也有一些顯著缺點(diǎn)央碟。主要缺點(diǎn)在于,除非每個(gè)服務(wù)實(shí)例是一個(gè)單獨(dú)的進(jìn)程,否則會(huì)甚少或者沒有隔離亿虽。雖然能夠準(zhǔn)確監(jiān)控每個(gè)服務(wù)實(shí)例的資源利用率菱涤,但是并不能限制每個(gè)實(shí)例使用的資源;很有可能一個(gè)異常的服務(wù)實(shí)例會(huì)消耗主機(jī)的所有內(nèi)存和 CPU洛勉。
運(yùn)行在同一進(jìn)程的多個(gè)服務(wù)實(shí)例沒有隔離粘秆,所有實(shí)例可能共享同一個(gè) JVM 堆。出現(xiàn)異常的服務(wù)實(shí)例能夠輕易中斷運(yùn)行在同一進(jìn)程中的其它服務(wù)收毫。此外攻走,也無法監(jiān)控每個(gè)服務(wù)使用的資源。
這種方法的另一顯著問題是此再,部署服務(wù)的運(yùn)維團(tuán)隊(duì)需要了解部署的具體細(xì)節(jié)昔搂。服務(wù)可能用各種語言和框架寫成,因而開發(fā)團(tuán)隊(duì)必須與運(yùn)維團(tuán)隊(duì)溝通諸多細(xì)節(jié)输拇。這種復(fù)雜性增加了部署中出錯(cuò)的風(fēng)險(xiǎn)摘符。
盡管單主機(jī)多服務(wù)實(shí)例模式頗為友好,但仍有顯著缺點(diǎn)策吠。接下來介紹其它的部署方式逛裤,能夠避免這些缺點(diǎn)。
三猴抹、單主機(jī)單服務(wù)實(shí)例模式
部署微服務(wù)的另一種方法是單主機(jī)單服務(wù)實(shí)例模式带族。在此模式中,每臺(tái)主機(jī)上運(yùn)行獨(dú)立的服務(wù)實(shí)例蟀给。這一模式有兩種不同實(shí)現(xiàn)——單虛擬機(jī)單服務(wù)實(shí)例和單容器單服務(wù)實(shí)例蝙砌。
單虛擬機(jī)單服務(wù)實(shí)例模式
使用單虛擬機(jī)單服務(wù)實(shí)例模式時(shí),把每個(gè)服務(wù)大包圍一個(gè)虛擬機(jī)鏡像坤溃,類似 Amazon EC2 AMI拍霜。每個(gè)服務(wù)實(shí)例就是一臺(tái)使用此鏡像啟動(dòng)的虛擬機(jī),譬如 EC2 實(shí)例薪介。下圖展示了此模式的結(jié)構(gòu)祠饺。
這也是 Netflix 在部署視頻流媒體服務(wù)時(shí)采用的主要方式。Netflix 使用 Aminator 把每個(gè)服務(wù)實(shí)例打包成 EC2 AMI汁政,每個(gè)正在運(yùn)行的服務(wù)實(shí)例就是一個(gè) EC2 實(shí)例道偷。
有多種工具可用來搭建自己的虛擬機(jī)。用戶能夠配置持續(xù)集成(CI)服務(wù)器(例如 Jenkins)來調(diào)用 Aminator记劈,把服務(wù)打包為 EC2 AMI勺鸦。Packer.io 是另一個(gè)自動(dòng)化創(chuàng)建虛擬機(jī)鏡像的工具。不同于 Aminator目木,它支持包括 EC2换途、DigitalOcean、VirtualBox 和 VMware 在內(nèi)的多種虛擬化技術(shù)。
Boxfuse 這家公司使用令人信服的方式構(gòu)建虛擬機(jī)鏡像军拟,克服了我上文描述的虛擬機(jī)的缺點(diǎn)剃执。Boxfuse 把 Java 應(yīng)用打包為一個(gè)最小的虛擬機(jī)鏡像。這些鏡像能夠快速構(gòu)建懈息、啟動(dòng)肾档,并且由于只暴露了有限的端口,也更安全辫继。
CloudNative 提供 Bakery 這款 SaaS 工具來創(chuàng)建 EC2 AMI怒见。用戶的微服務(wù)通過測試,能夠配置 CI 服務(wù)器來調(diào)用 Bakery姑宽,后者把服務(wù)打包為 AMI遣耍。使用 Bakery 這樣的 SaaS 工具意味著你不需要浪費(fèi)寶貴的時(shí)間來設(shè)置創(chuàng)建 AMI 的基礎(chǔ)設(shè)施。
單虛擬機(jī)單服務(wù)實(shí)例有許多優(yōu)點(diǎn)低千。****一大好處就是每個(gè)服務(wù)實(shí)例完全隔離運(yùn)行配阵,每個(gè)實(shí)例都有固定的 CPU 和內(nèi)存,不會(huì)被別的服務(wù)占用資源示血。
把微服務(wù)作為虛擬機(jī)部署的另一個(gè)優(yōu)勢就是能夠充分利用成熟的云基礎(chǔ)設(shè)施。AWS 這樣的云服務(wù)提供了負(fù)載均衡和自動(dòng)擴(kuò)展這樣實(shí)用的功能救拉。
再一個(gè)優(yōu)勢就是封裝了服務(wù)的實(shí)施技術(shù)难审。一旦服務(wù)被打包成虛擬機(jī),就變成了黑盒亿絮,虛擬機(jī)的管理 API 成為部署該服務(wù)的 API告喊。部署變得更簡單可靠。
單虛擬機(jī)單服務(wù)實(shí)例模式也有缺點(diǎn)派昧。缺點(diǎn)之一就是資源利用率低黔姜。每個(gè)服務(wù)實(shí)例占用包括操作系統(tǒng)在內(nèi)的整個(gè)虛擬機(jī)的開銷。此外蒂萎,在典型的公有 IaaS秆吵,虛擬機(jī)資源固定,很難被充分利用五慈。
此外纳寂,公有 IaaS 通常依據(jù)虛擬機(jī)數(shù)量收費(fèi),不考慮其繁忙與否泻拦。AWS 這類的 IaaS 提供了自動(dòng)擴(kuò)展毙芜,但是很難針對需求快速反應(yīng);因而很容易過度配置虛擬機(jī)争拐,增加部署成本腋粥。
這種方法的另一個(gè)缺點(diǎn)是,部署服務(wù)的新版本通常很緩慢。由于體積較大隘冲,虛擬機(jī)鏡像構(gòu)建緩慢金赦。同樣,由于體積較大对嚼,虛擬機(jī)的實(shí)例化也比較緩慢夹抗。此外,操作系統(tǒng)也需要時(shí)間啟動(dòng)纵竖。然而漠烧,鑒于存在由 Boxfuse 構(gòu)建的輕量級的虛擬機(jī),這一規(guī)律也并非普遍適用靡砌。
單虛擬機(jī)單服務(wù)實(shí)例的另一個(gè)缺點(diǎn)就是已脓,用戶或組織中的其他人要負(fù)責(zé)大量無差別的沉重的工作。除非使用 Boxfuse 這樣的工具來解決構(gòu)建和管理虛擬機(jī)的開銷通殃,否則這種必要且耗時(shí)的工作會(huì)占用你處理核心業(yè)務(wù)的時(shí)間度液。
下面來了解另一種部署微服務(wù)的方法,它比虛擬機(jī)輕量画舌,但具有其優(yōu)點(diǎn)堕担。
單容器單服務(wù)實(shí)例模式
使用單容器單服務(wù)實(shí)例模式,每個(gè)服務(wù)實(shí)例運(yùn)行在自有容器中曲聂。容器是操作系統(tǒng)級別的虛擬化機(jī)制霹购。每個(gè)容器包含一個(gè)或多個(gè)運(yùn)行在沙盒中的進(jìn)程。從進(jìn)程的角度看朋腋,它們有著自己的端口命名空間和根文件系統(tǒng)齐疙。用戶能夠限制容器的內(nèi)存和 CPU 資源,有些容器還能限制 I/O 速率旭咽。容器技術(shù)的代表包括 Docker 和 Solaris Zone贞奋。
下圖顯示了這種模式的結(jié)構(gòu):
使用這一模式時(shí),用戶將服務(wù)打包為容器鏡像穷绵。每個(gè)容器鏡像就是一個(gè)文件系統(tǒng)鏡像轿塔,由應(yīng)用和運(yùn)行服務(wù)所需的庫構(gòu)成。有的容器鏡像還包括完整的 Linux 根文件系統(tǒng)请垛,有的則更輕量催训。以部署 Java 服務(wù)為例,構(gòu)建的容器鏡像包括 Java 運(yùn)行時(shí)宗收、Apache Tomcat 服務(wù)器漫拭、以及編譯好的 Java 應(yīng)用。
一旦將服務(wù)打包為容器鏡像混稽,就啟動(dòng)一到多個(gè)容器采驻。通常每個(gè)物理機(jī)或虛擬主機(jī)上會(huì)運(yùn)行多個(gè)容器审胚,會(huì)用到 Kubernetes 或 Marathon 這樣的集群管理工具來管理容器。集群管理工具把主機(jī)看做資源池礼旅,根據(jù)每個(gè)容器需要的資源和每個(gè)主機(jī)上可用的資源來調(diào)度容器膳叨。
單容器單服務(wù)實(shí)例模式有缺點(diǎn)兼?zhèn)洹?***容器的優(yōu)點(diǎn)與虛擬機(jī)類似,服務(wù)實(shí)例之間完全隔離痘系,也能輕松監(jiān)控每個(gè)容器的資源消耗菲嘴。此外,與虛擬機(jī)相似汰翠,容器能夠封裝執(zhí)行服務(wù)的技術(shù)龄坪。容器管理 API 也可用作管理服務(wù)的 API。
不同于虛擬機(jī)复唤,容器技術(shù)更為輕量健田,容器鏡像構(gòu)建速度更快。只用短短五秒就可以在筆記本電腦上把 Spring Boot 應(yīng)用打包為 Docker 容器佛纫。由于沒有冗長的操作系統(tǒng)啟動(dòng)機(jī)制妓局,容器啟動(dòng)也非常迅速。容器啟動(dòng)呈宇,服務(wù)立刻運(yùn)行好爬。
使用容器也有一些缺點(diǎn)。雖然容器架構(gòu)迅速成長攒盈,然而并不如虛擬機(jī)架構(gòu)那般成熟抵拘。此外,由于容器之間共享主機(jī)操作系統(tǒng)的內(nèi)核型豁,因而也沒有虛擬機(jī)安全。
容器的另一個(gè)缺點(diǎn)是尚蝌,管理容器鏡像是一項(xiàng)無差別的繁重工作迎变。除非能使用 Google Container Engine 或 Amazon EC2 容器服務(wù)(ECS),否則需要同時(shí)管理容器基礎(chǔ)設(shè)施和虛擬機(jī)基礎(chǔ)設(shè)施飘言。
此外衣形,容器通常部署在以每臺(tái)虛擬機(jī)定價(jià)的基礎(chǔ)設(shè)施上,為了處理負(fù)載高峰姿鸿,你可能會(huì)過度配置虛擬機(jī)谆吴,帶來額外的成本。
有趣的是苛预,容器和虛擬機(jī)之間的區(qū)別并非涇渭分明句狼。如前文所述,Boxfuse 能夠快速構(gòu)建和啟動(dòng)虛擬機(jī)热某,Clear Container 項(xiàng)目則致力于創(chuàng)建輕量級的虛擬機(jī)腻菇,此外 unikernel 技術(shù)也引起大家注意胳螟。Docker 近期(注:2016 年 1 月 21 日)收購了 Unikernel Systems。
無服務(wù)器部署的概念也嶄露頭角筹吐,日漸流行糖耸。無服務(wù)器部署不需要選擇將服務(wù)部署在容器還是服務(wù)器。
四丘薛、無服務(wù)器部署
AWS Lambda 就是無服務(wù)器部署的例子嘉竟。它支持 Java、Node.js 和 Python 服務(wù)洋侨。要部署微服務(wù)舍扰,把服務(wù)打包為 ZIP 文件并上傳到 AWS Lambda。用戶也可以提供元數(shù)據(jù)凰兑,指定函數(shù)名稱妥粟,后者被用于處理請求(即事件)。
Lambda 函數(shù)是無狀態(tài)的服務(wù)吏够,通過調(diào)用 AWS 服務(wù)處理請求勾给。例如,當(dāng)鏡像被上傳到 S3 存儲(chǔ)桶锅知,Lambda 函數(shù)被調(diào)用播急,在 DynamoDB 鏡像中插入一項(xiàng)條目,并向 Kinesis 流發(fā)布消息售睹,觸發(fā)鏡像處理桩警。Lambda 函數(shù)也可以調(diào)用第三方網(wǎng)頁服務(wù)。
有以下四種方法來調(diào)用 Lambda 函數(shù):
- 直接調(diào)用昌妹,直接使用網(wǎng)頁服務(wù)請求
- 自動(dòng)調(diào)用捶枢,自動(dòng)響應(yīng)由 S3、DynamoDB飞崖、Knesis烂叔、或 Simple Email Service 等 AWS 服務(wù)生成的事件
- 自動(dòng)調(diào)用,自動(dòng)通過 AWS API 網(wǎng)關(guān)處理來自應(yīng)用客戶端的 HTTP 請求
- 定期調(diào)用固歪,通過類似 Cron 的定時(shí)任務(wù)實(shí)現(xiàn)
可以看出蒜鸡,AWS Lambda 是部署微服務(wù)的便捷途徑±紊眩基于請求的定價(jià)方式意味著用戶只需要為服務(wù)實(shí)際運(yùn)行的業(yè)務(wù)付費(fèi)逢防。此外,由于無需考慮 IT 基礎(chǔ)設(shè)施蒲讯,用戶也能專注于應(yīng)用開發(fā)忘朝。
然而,AWS Lambda 也有一些明顯的局限伶椿。它并不適合被用來部署長期運(yùn)行的服務(wù)辜伟,比如讀取來自第三方消息代理的信息氓侧。請求需要在 300 秒內(nèi)完成。由于 AWS Lambda 理論上能夠針對每個(gè)請求運(yùn)行單獨(dú)的實(shí)例导狡,因此服務(wù)必須保持無狀態(tài)约巷。此外,它們還必須用某一種支持的語言完成旱捧。服務(wù)也需要快速啟動(dòng)独郎,然而有時(shí)候會(huì)有超時(shí)和停止。
總結(jié)
部署微服務(wù)應(yīng)用充滿挑戰(zhàn)枚赡。幾十個(gè)甚至上百個(gè)服務(wù)用不同的語言和框架寫成氓癌,每個(gè)服務(wù)都是一個(gè)自帶特定部署、資源贫橙、擴(kuò)展和監(jiān)控需求的微型應(yīng)用贪婉。微服務(wù)部署的模式有多種,包括單虛擬機(jī)單服務(wù)實(shí)例和單容器單服務(wù)實(shí)例卢肃。另一個(gè)讓人倍感興趣的微服務(wù)部署方法則是 AWS Lambda疲迂,無服務(wù)器部署方案的代表。在本系列的最后一篇莫湘,我們將分析如何將單體應(yīng)用遷移到微服務(wù)架構(gòu)尤蒿。