微服務(wù)實(shí)戰(zhàn)(六):選擇微服務(wù)部署策略
這篇博客是用微服務(wù)建應(yīng)用的第六篇愚战,第一篇介紹了微服務(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ù)的策略刑棵。
本系列文章:
微服務(wù)實(shí)戰(zhàn)(一):微服務(wù)架構(gòu)的優(yōu)勢(shì)與不足
微服務(wù)實(shí)戰(zhàn)(二):使用API Gateway
微服務(wù)實(shí)戰(zhàn)(三):深入微服務(wù)架構(gòu)的進(jìn)程間通信
微服務(wù)實(shí)戰(zhàn)(四):服務(wù)發(fā)現(xiàn)的可行方案以及實(shí)踐案例
微服務(wù)實(shí)踐(五):微服務(wù)的事件驅(qū)動(dòng)數(shù)據(jù)管理
動(dòng)機(jī)
部署一個(gè)單體式應(yīng)用意味運(yùn)行大型應(yīng)用的多個(gè)副本巴刻,典型的提供若干個(gè)(N)服務(wù)器(物理或者虛擬),運(yùn)行若干個(gè)(M)個(gè)應(yīng)用實(shí)例蛉签。部署單體式應(yīng)用不會(huì)很直接胡陪,但是肯定比部署微服務(wù)應(yīng)用簡(jiǎn)單些。
一個(gè)微服務(wù)應(yīng)用由上百個(gè)服務(wù)構(gòu)成碍舍,服務(wù)可以采用不同語(yǔ)言和框架分別寫(xiě)就柠座。每個(gè)服務(wù)都是一個(gè)單一應(yīng)用,可以有自己的部署片橡、資源妈经、擴(kuò)展和監(jiān)控需求。例如捧书,可以根據(jù)服務(wù)需求運(yùn)行若干個(gè)服務(wù)實(shí)例吹泡,除此之外,每個(gè)實(shí)例必須有自己的CPU经瓷,內(nèi)存和I/O資源爆哑。盡管很復(fù)雜,但是更挑戰(zhàn)的是服務(wù)部署必須快速舆吮、可靠和性價(jià)比高揭朝。
有一些微服務(wù)部署的模式队贱,先討論一下每個(gè)主機(jī)多服務(wù)實(shí)例的模式。
單主機(jī)多服務(wù)實(shí)例模式
部署微服務(wù)的一種方法就是單主機(jī)多服務(wù)實(shí)例模式潭袱,使用這種模式柱嫌,需要提供若干臺(tái)物理或者虛擬機(jī),每臺(tái)機(jī)器上運(yùn)行多個(gè)服務(wù)實(shí)例屯换。很多情況下编丘,這是傳統(tǒng)的應(yīng)用部署方法。每個(gè)服務(wù)實(shí)例運(yùn)行一個(gè)或者多個(gè)主機(jī)的well-known端口趟径,主機(jī)可以看做寵物瘪吏。
下圖展示的是這種架構(gòu):
這種模式有一些參數(shù)癣防,一個(gè)參數(shù)代表每個(gè)服務(wù)實(shí)例由多少進(jìn)程構(gòu)成蜗巧。例如,需要在Apache Tomcat Server上部署一個(gè)Java服務(wù)實(shí)例作為web應(yīng)用蕾盯。一個(gè)Node.js服務(wù)實(shí)例可能有一個(gè)父進(jìn)程和若干個(gè)子進(jìn)程構(gòu)成幕屹。
另外一個(gè)參數(shù)定義同一進(jìn)程組內(nèi)有多少服務(wù)實(shí)例運(yùn)行。例如级遭,可以在同一個(gè)Apache Tomcat Server上運(yùn)行多個(gè)Java web應(yīng)用望拖,或者在同一個(gè)OSGI容器內(nèi)運(yùn)行多個(gè)OSGI捆綁實(shí)例。
單主機(jī)多服務(wù)實(shí)例模式也是優(yōu)缺點(diǎn)并存挫鸽。主要優(yōu)點(diǎn)在于資源利用有效性说敏。多服務(wù)實(shí)例共享服務(wù)器和操作系統(tǒng),如果進(jìn)程組運(yùn)行多個(gè)服務(wù)實(shí)例效率會(huì)更高丢郊,例如盔沫,多個(gè)web應(yīng)用共享同一個(gè)Apache Tomcat Server和JVM。
另一個(gè)優(yōu)點(diǎn)在于部署服務(wù)實(shí)例很快枫匾。只需將服務(wù)拷貝到主機(jī)并啟動(dòng)它架诞。如果服務(wù)用Java寫(xiě)的,只需要拷貝JAR或者WAR文件即可干茉。對(duì)于其它語(yǔ)言谴忧,例如Node.js或者Ruby,需要拷貝源碼角虫。也就是說(shuō)網(wǎng)絡(luò)負(fù)載很低沾谓。
因?yàn)闆](méi)有太多負(fù)載,啟動(dòng)服務(wù)很快戳鹅。如果服務(wù)是自包含的進(jìn)程搏屑,只需要啟動(dòng)就可以;否則粉楚,如果是運(yùn)行在容器進(jìn)程組中的某個(gè)服務(wù)實(shí)例辣恋,則需要?jiǎng)討B(tài)部署進(jìn)容器中亮垫,或者重啟容器。
除了上述優(yōu)點(diǎn)外伟骨,單主機(jī)多服務(wù)實(shí)例也有缺陷饮潦。其中一個(gè)主要缺點(diǎn)是服務(wù)實(shí)例間很少或者沒(méi)有隔離,除非每個(gè)服務(wù)實(shí)例是獨(dú)立進(jìn)程携狭。如果想精確監(jiān)控每個(gè)服務(wù)實(shí)例資源使用继蜡,就不能限制每個(gè)實(shí)例資源使用。因此有可能造成某個(gè)糟糕的服務(wù)實(shí)例占用了主機(jī)的所有內(nèi)存或者CPU逛腿。
同一進(jìn)程內(nèi)多服務(wù)實(shí)例沒(méi)有隔離稀并。所有實(shí)例有可能,例如单默,共享同一個(gè)JVM heap碘举。某個(gè)糟糕服務(wù)實(shí)例很容易攻擊同一進(jìn)程中其它服務(wù);更甚至于搁廓,有可能無(wú)法監(jiān)控每個(gè)服務(wù)實(shí)例使用的資源情況引颈。
另一個(gè)嚴(yán)重問(wèn)題在于運(yùn)維團(tuán)隊(duì)必須知道如何部署的詳細(xì)步驟。服務(wù)可以用不同語(yǔ)言和框架寫(xiě)成境蜕,因此開(kāi)發(fā)團(tuán)隊(duì)肯定有很多需要跟運(yùn)維團(tuán)隊(duì)溝通事項(xiàng)蝙场。其中復(fù)雜性增加了部署過(guò)程中出錯(cuò)的可能性。
可以看到粱年,盡管熟悉售滤,但是單主機(jī)多服務(wù)實(shí)例有很多嚴(yán)重缺陷。下面看看是否有其他部署微服務(wù)方式能夠避免這些問(wèn)題台诗。
單主機(jī)單服務(wù)實(shí)例模式
另外一種部署微服務(wù)方式是單主機(jī)單實(shí)例模式完箩。當(dāng)使用這種模式,每個(gè)主機(jī)上服務(wù)實(shí)例都是各自獨(dú)立的拉庶。有兩種不同實(shí)現(xiàn)模式:?jiǎn)翁摂M機(jī)單實(shí)例和單容器單實(shí)例嗜憔。
單虛擬機(jī)單實(shí)例模式
但是用單虛擬機(jī)單實(shí)例模式,一般將服務(wù)打包成虛擬機(jī)映像(image)氏仗,例如一個(gè)Amazon EC2 AMI吉捶。每個(gè)服務(wù)實(shí)例是一個(gè)使用此映像啟動(dòng)的VM(例如,EC2實(shí)例)皆尔。下圖展示了此架構(gòu):
Netfix采用這種架構(gòu)部署video streaming service呐舔。Netfix使用Aminator將每個(gè)服務(wù)打包成一個(gè)EC2 AMI。每個(gè)運(yùn)行服務(wù)實(shí)例就是一個(gè)EC2實(shí)例慷蠕。
有很多工具可以用來(lái)搭建自己的VMs珊拼。可以配置持續(xù)集成(CI)服務(wù)(例如流炕,Jenkins)避免Aminator將服務(wù)打包成EC2 AMI澎现。packer.io是自動(dòng)虛機(jī)映像創(chuàng)建的另外一種選擇仅胞。跟Aminator不同,它支持一系列虛擬化技術(shù)剑辫,例如EC2干旧,DigitalOcean,VirtualBox和VMware妹蔽。
Boxfuse公司有一個(gè)創(chuàng)新方法創(chuàng)建虛機(jī)映像椎眯,克服了如下缺陷。Boxfuse將java應(yīng)用打包成最小虛機(jī)映像胳岂,它們創(chuàng)建迅速编整,啟動(dòng)很快,因?yàn)閷?duì)外暴露服務(wù)接口少而更加安全乳丰。
CloudNative公司有一個(gè)用于創(chuàng)建EC2 AMI的SaaS應(yīng)用掌测,Bakery。用戶微服務(wù)架構(gòu)通過(guò)測(cè)試后成艘,可以配置自己的CI服務(wù)器激活Bakery赏半。Bakery將服務(wù)打包成AMI贺归。使用如Bakery的SaaS應(yīng)用意味著用戶不需要浪費(fèi)時(shí)間在設(shè)置自己的AMI創(chuàng)建架構(gòu)淆两。
每虛擬機(jī)服務(wù)實(shí)例模式有許多優(yōu)勢(shì),主要的VM優(yōu)勢(shì)在于每個(gè)服務(wù)實(shí)例都是完全獨(dú)立運(yùn)行的拂酣,都有各自獨(dú)立的CPU和內(nèi)存而不會(huì)被其它服務(wù)占用秋冰。
另外一個(gè)好處在于用戶可以使用成熟云架構(gòu),例如AWS提供的婶熬,云服務(wù)都提供如負(fù)載均衡和擴(kuò)展性等有用功能剑勾。
還有一個(gè)好處在于服務(wù)實(shí)施技術(shù)被自包含了。一旦服務(wù)被打包成VM就成為一個(gè)黑盒子赵颅。VM的管理API成為部署服務(wù)的API虽另,部署成為一個(gè)非常簡(jiǎn)單和可靠的事情。
單虛擬機(jī)單實(shí)例模式也有缺點(diǎn)饺谬。一個(gè)缺點(diǎn)就是資源利用效率不高捂刺。每個(gè)服務(wù)實(shí)例戰(zhàn)友整個(gè)虛機(jī)的資源,包括操作系統(tǒng)募寨。而且族展,在一個(gè)典型的公有IaaS環(huán)境,虛機(jī)資源都是標(biāo)準(zhǔn)化的拔鹰,有可能未被充分利用仪缸。
而且,公有IaaS根據(jù)VM來(lái)收費(fèi)列肢,而不管虛機(jī)是否繁忙恰画;例如AWS提供了自動(dòng)擴(kuò)展功能宾茂,但是對(duì)隨需應(yīng)用缺乏快速響應(yīng),使得用戶不得不多部署虛機(jī)拴还,從而增加了部署費(fèi)用刻炒。
另外一個(gè)缺點(diǎn)在于部署服務(wù)新版本比較慢。虛機(jī)鏡像因?yàn)榇笮≡騽?chuàng)建起來(lái)比較慢自沧,同樣原因坟奥,虛機(jī)初始化也比較慢,操作系統(tǒng)啟動(dòng)也需要時(shí)間拇厢。但是這并不一直是這樣爱谁,一些輕量級(jí)虛機(jī),例如使用Boxfuse創(chuàng)建的虛機(jī)孝偎,就比較快访敌。
第三個(gè)缺點(diǎn)是對(duì)于運(yùn)維團(tuán)隊(duì),它們負(fù)責(zé)許多客制化工作衣盾。除非使用如Boxfuse之類的工具寺旺,可以幫助減輕大量創(chuàng)建和管理虛機(jī)的工作;否則會(huì)占用大量時(shí)間從事與核心業(yè)務(wù)不太無(wú)關(guān)的工作势决。
那么我們來(lái)看看另外一種仍然具有虛機(jī)特性阻塑,但是比較輕量的微服務(wù)部署方法。
單容器單服務(wù)實(shí)例模式
當(dāng)使用這種模式時(shí)果复,每個(gè)服務(wù)實(shí)例都運(yùn)行在各自容器中陈莽。容器是運(yùn)行在操作系統(tǒng)層面的虛擬化機(jī)制。一個(gè)容器包含若干運(yùn)行在沙箱中的進(jìn)程虽抄。從進(jìn)程角度來(lái)看走搁,他們有各自的命名空間和根文件系統(tǒng);可以限制容器的內(nèi)存和CPU資源迈窟。某些容器還具有I/O限制私植,這類容器技術(shù)包括Docker和Solaris Zones。
下圖展示了這種模式:
使用這種模式需要將服務(wù)打包成容器映像车酣。一個(gè)容器映像是一個(gè)運(yùn)行包含服務(wù)所需庫(kù)和應(yīng)用的文件系統(tǒng)曲稼。某些容器映像由完整的linux根文件系統(tǒng)組成,其它則是輕量級(jí)的骇径。例如躯肌,為了部署Java服務(wù),需要?jiǎng)?chuàng)建包含Java運(yùn)行庫(kù)的容器映像破衔,也許還要包含Apache Tomcat server清女,以及編譯過(guò)的Java應(yīng)用。
一旦將服務(wù)打包成容器映像晰筛,就需要啟動(dòng)若干容器嫡丙。一般在一個(gè)物理機(jī)或者虛擬機(jī)上運(yùn)行多個(gè)容器拴袭,可能需要集群管理系統(tǒng),例如k8s或者M(jìn)arathon曙博,來(lái)管理容器拥刻。集群管理系統(tǒng)將主機(jī)作為資源池,根據(jù)每個(gè)容器對(duì)資源的需求父泳,決定將容器調(diào)度到那個(gè)主機(jī)上般哼。
單容器單服務(wù)實(shí)例模式也是優(yōu)缺點(diǎn)都有。容器的優(yōu)點(diǎn)跟虛機(jī)很相似惠窄,服務(wù)實(shí)例之間完全獨(dú)立蒸眠,可以很容易監(jiān)控每個(gè)容器消耗的資源。跟虛機(jī)相似杆融,容器使用隔離技術(shù)部署服務(wù)楞卡。容器管理API也可以作為管理服務(wù)的API。
然而脾歇,跟虛機(jī)不一樣蒋腮,容器是一個(gè)輕量級(jí)技術(shù)。容器映像創(chuàng)建起來(lái)很快藕各,例如池摧,在筆記本電腦上,將Spring Boot 應(yīng)用打包成容器映像只需要5秒鐘座韵。因?yàn)椴恍枰僮飨到y(tǒng)啟動(dòng)機(jī)制险绘,容器啟動(dòng)也很快踢京。當(dāng)容器啟動(dòng)時(shí)誉碴,后臺(tái)服務(wù)就啟動(dòng)了。
使用容器也有一些缺點(diǎn)瓣距。盡管容器架構(gòu)發(fā)展迅速黔帕,但是還是不如虛機(jī)架構(gòu)成熟。而且由于容器之間共享host OS內(nèi)核因此并不像虛機(jī)那么安全蹈丸。
另外成黄,容器技術(shù)將會(huì)對(duì)管理容器映像提出許多客制化需求,除非使用如Google Container Engine或者Amazon EC2 Container Service (ECS)逻杖,否則用戶將同時(shí)需要管理容器架構(gòu)以及虛機(jī)架構(gòu)奋岁。
第三,容器經(jīng)常被部署在按照虛機(jī)收費(fèi)的架構(gòu)上荸百,很顯然闻伶,客戶也會(huì)增加部署費(fèi)用來(lái)應(yīng)對(duì)負(fù)載的增長(zhǎng)。
有趣的是够话,容器和虛機(jī)之間的區(qū)別越來(lái)越模糊蓝翰。如前所述光绕,Boxfuse虛機(jī)啟動(dòng)創(chuàng)建都很快,Clear Container技術(shù)面向創(chuàng)建輕量級(jí)虛機(jī)畜份。Unikernel公司的技術(shù)也引起大家關(guān)注诞帐,Docker最近收購(gòu)了Unikernel公司。
除了這些之外爆雹,server-less部署技術(shù)停蕉,避免了前述容器和VM技術(shù)的缺陷,吸引了越來(lái)越多的注意钙态。下面我們來(lái)看看谷徙。
Serverless 部署
AWS Lambda是serverless部署技術(shù)的例子,支持Java驯绎,Node.js和Python服務(wù)完慧;需要將服務(wù)打包成ZIP文件上載到AWS Lambda就可以部署∈JВ可以提供元數(shù)據(jù)屈尼,提供處理服務(wù)請(qǐng)求函數(shù)的名字(一個(gè)事件)。AWS Lambda自動(dòng)運(yùn)行處理請(qǐng)求足夠多的微服務(wù)拴孤,然而只根據(jù)運(yùn)行時(shí)間和消耗內(nèi)存量來(lái)計(jì)費(fèi)脾歧。當(dāng)然細(xì)節(jié)決定成敗,AWS Lambda也有限制演熟。但是大家都不需要擔(dān)心服務(wù)器鞭执,虛擬機(jī)或者容器內(nèi)的任何方面絕對(duì)吸引人。
Lambda 函數(shù) 是無(wú)狀態(tài)服務(wù)芒粹。一般通過(guò)激活A(yù)WS服務(wù)處理請(qǐng)求兄纺。例如,當(dāng)映像上載到S3 bucket激活Lambda函數(shù)后化漆,就可以在DynamoDB映像表中插入一個(gè)條目估脆,給Kinesis流發(fā)布一條消息,觸發(fā)映像處理動(dòng)作座云。Lambda函數(shù)也可以通過(guò)第三方web服務(wù)激活疙赠。
有四種方法激活Lambda函數(shù):
直接方式,使用web服務(wù)請(qǐng)求
自動(dòng)方式朦拖,回應(yīng)例如AWS S3圃阳,DynamoDB,Kinesis或者Simple Email Service等產(chǎn)生的事件
自動(dòng)方式璧帝,通過(guò)AWS API網(wǎng)關(guān)來(lái)處理應(yīng)用客戶端發(fā)出的HTTP請(qǐng)求
定時(shí)方式捍岳,通過(guò)cron響應(yīng)–很像定時(shí)器方式
可以看出,AWS Lambda是一種很方便部署微服務(wù)的方式∷钔基于請(qǐng)求計(jì)費(fèi)方式意味著用戶只需要承擔(dān)處理自己業(yè)務(wù)那部分的負(fù)載作喘;另外,因?yàn)椴恍枰私饣A(chǔ)架構(gòu)晕城,用戶只需要開(kāi)發(fā)自己的應(yīng)用泞坦。
然而還是有不少限制。不需要用來(lái)部署長(zhǎng)期服務(wù)砖顷,例如用來(lái)消費(fèi)從第三方代理轉(zhuǎn)發(fā)來(lái)的消息贰锁,請(qǐng)求必須在300秒內(nèi)完成,服務(wù)必須是無(wú)狀態(tài)滤蝠,因?yàn)槔碚撋螦WS Lambda會(huì)為每個(gè)請(qǐng)求生成一個(gè)獨(dú)立的實(shí)例豌熄;必須用某種支持的語(yǔ)言完成,服務(wù)必須啟動(dòng)很快物咳,否則锣险,會(huì)因?yàn)槌瑫r(shí)被停止。
總結(jié)
部署微服務(wù)應(yīng)用也是一種挑戰(zhàn)览闰。用各種語(yǔ)言和框架寫(xiě)成的服務(wù)成百上千芯肤。每種服務(wù)都是一種迷你應(yīng)用,有自己獨(dú)特的部署压鉴、資源崖咨、擴(kuò)充和監(jiān)控需求。有若干種微服務(wù)部署模式油吭,包括單虛機(jī)單實(shí)例以及單容器單實(shí)例击蹲。另外可選模式還有AWS Lambda,一種serverless方法婉宰。
在下一篇也是本系列最后一篇博客中歌豺,我們來(lái)討論如何將一個(gè)單體式應(yīng)用遷移到微服務(wù)架構(gòu)。
本文為翻譯文章芍阎,閱讀原文世曾,請(qǐng)點(diǎn)擊左下角閱讀原文鏈接。