編者的話 |本文來自 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 微服務(wù)系列全 7 篇:
1. 微服務(wù)架構(gòu)概念解析
2. 構(gòu)建微服務(wù)架構(gòu):使用 API Gateway
3. 深入微服務(wù)架構(gòu)的進(jìn)程間通信
4. 服務(wù)發(fā)現(xiàn)的可行方案以及實(shí)踐案例
5. 微服務(wù)的事件驅(qū)動(dòng)數(shù)據(jù)管理
6. 選擇微服務(wù)部署策略(本篇文章)
7. 將單體應(yīng)用改造為微服務(wù)
誘因
部署單體應(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í)的虛擬機(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í)別的虛擬化機(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)浯履H萜鞯膬?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í)的虛擬機(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)烹困。
文章轉(zhuǎn)載自:http://blog.daocloud.io/microservices-6/