《使用微服務(wù),你考慮好了嗎?》要點(diǎn):
本文介紹了使用微服務(wù),你考慮好了嗎?,希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
微服務(wù)已經(jīng)成為了當(dāng)前最熱門的架構(gòu)模式,然而也許微服務(wù)對(duì)你來說并不適用,繼續(xù)閱讀來尋找答案吧.
目前,幾乎所有人都對(duì)微服務(wù)趨之若鶩.打開你的新聞聚合客戶端你會(huì)發(fā)現(xiàn),幾乎每篇文章都在講微服務(wù)架構(gòu),沒有一個(gè)公司不是通過微服務(wù)技術(shù)拯救了他們的研發(fā)部門.也許你曾經(jīng)在這么一家公司工作過,通過這種輕量魔術(shù)般的服務(wù)來解決了所有遺留系統(tǒng)帶來的問題.
當(dāng)然,事后看來,我們反而離真相更遠(yuǎn)了.就像我們能看到視力表最末行,其實(shí)是由于提前看過了視力表導(dǎo)致的.
作為一個(gè)嘗試將單體應(yīng)用拆分為微服務(wù)來拯救世界的公司員工,我將討論微服務(wù)運(yùn)動(dòng)的一些主要謬誤和陷阱.當(dāng)然這篇博客并非簡單的將微服務(wù)與不好劃等號(hào),只是希望大家通過閱讀它能夠思考微服務(wù)架構(gòu)是否真的適合你們.
世界上沒有標(biāo)準(zhǔn)的定義,微服務(wù)應(yīng)該包含什么、不應(yīng)該包含什么.當(dāng)然一些人已經(jīng)成功實(shí)施微服務(wù)的人將規(guī)范編撰成冊(cè).
我再強(qiáng)調(diào)一點(diǎn),微服務(wù)不是一個(gè)單體.確切的說,單個(gè)微服務(wù)只處理一個(gè)非常有限的領(lǐng)域,它只處理它在你的技術(shù)棧中應(yīng)當(dāng)處理的工作.一個(gè)更確切一點(diǎn)的例子比如:一個(gè)銀行在線銀行業(yè)務(wù)中有一個(gè)“交易服務(wù)”(起名太困難,你懂就好),現(xiàn)在你打算增加一個(gè)訪問用戶交易記錄的業(yè)務(wù),你應(yīng)當(dāng)把它放到交易服務(wù)之外.
另外,大家談?wù)撐⒎?wù)時(shí),總是隱含地討論微服務(wù)彼此之間需要遠(yuǎn)程通訊.盡管他們是顯而易見的不同進(jìn)程,并且通常運(yùn)行在不同的計(jì)算節(jié)點(diǎn)上.所以通常服務(wù)之間使用REST或者其他RPC協(xié)議進(jìn)行通訊.
剛剛開始時(shí),這一切看起來還非常簡單.似乎我們只需要簡單的把領(lǐng)域服務(wù)通過RESTAPI暴露給其他微服務(wù),讓微服務(wù)之間通過網(wǎng)絡(luò)訪問即可.然而根據(jù)我的經(jīng)驗(yàn),大多數(shù)人認(rèn)為的五項(xiàng)事實(shí)實(shí)際上并非實(shí)情:
謬誤1:微服務(wù)能讓我的代碼更簡潔
“不要把網(wǎng)絡(luò)邊界當(dāng)作寫更好代碼的借口.”
一個(gè)簡單的事實(shí)是,任何技術(shù)棧,包括微服務(wù)在內(nèi),都不能成為寫更簡潔更易于維護(hù)的代碼的動(dòng)力.雖然當(dāng)條件減少時(shí),你寫出來不科學(xué)的代碼的可能性會(huì)降低,但是這就像是通過減少商店里的貴重物品來降低犯罪率一樣,沒有解決任何問題.
一個(gè)流行的方法是圍繞一個(gè)領(lǐng)域的邏輯服務(wù)構(gòu)建你的代碼結(jié)構(gòu).這反映了微服務(wù)的理念:它可以幫助你顯式地管理領(lǐng)域所需的依賴關(guān)系,并使得關(guān)鍵業(yè)務(wù)邏輯不會(huì)蔓延到多個(gè)地方.此外這些服務(wù)之間的調(diào)用不再過度使用網(wǎng)絡(luò),也避免了一些潛在問題的發(fā)生.
這種方法的好處在于,基于良好的前期設(shè)計(jì)和對(duì)領(lǐng)域的準(zhǔn)確理解,你很容易將它抽取出來,一旦你決定了采用微服務(wù)架構(gòu),它能幫助你非常準(zhǔn)確地圍繞微服務(wù)構(gòu)建面向服務(wù)架構(gòu).一個(gè)堅(jiān)固的SOA方法開始于代碼本身,并隨著時(shí)間地推移,將它擴(kuò)展到整個(gè)技術(shù)棧當(dāng)中.
謬誤2:微服務(wù)容易實(shí)現(xiàn)
“分布式事務(wù)從來不簡單.”
雖然最開始看起來非常簡單,但是大多數(shù)領(lǐng)域(尤其是對(duì)那些初創(chuàng)公司需要經(jīng)過多次原型迭代和改造的領(lǐng)域)并不適合將他們規(guī)規(guī)矩矩地劃分成為不同的領(lǐng)域.通常一個(gè)特定的子領(lǐng)域需要訪問其他子域的數(shù)據(jù)來正確地完成相應(yīng)的工作.當(dāng)需要向它自己以外的領(lǐng)域?qū)懭霐?shù)據(jù)時(shí),事情會(huì)變得更加的復(fù)雜.一旦你打破了自己的業(yè)務(wù)范圍,并且需要其他人參與請(qǐng)求流來存儲(chǔ)修改數(shù)據(jù)時(shí),那你就必須面對(duì)分布式事務(wù)(有時(shí)被稱作Sagas).
在一個(gè)請(qǐng)求中涉及到多個(gè)遠(yuǎn)程服務(wù)需要通訊時(shí),復(fù)雜的問題便隨之而來了.例如調(diào)用是否可以并行,或者必須串行完成?你是否意識(shí)到這些調(diào)用中任何一個(gè)環(huán)節(jié)都有潛在地發(fā)生錯(cuò)誤的可能性(包括應(yīng)用錯(cuò)誤和網(wǎng)絡(luò)錯(cuò)誤)?這對(duì)請(qǐng)求本身來說意味著什么?通常每個(gè)分布式事務(wù)都需要他們自己來處理可能發(fā)生的故障,這很可能帶來巨大的工作量,不僅僅是錯(cuò)誤的解析、錯(cuò)誤的處理,更包括如何在出現(xiàn)錯(cuò)誤時(shí)恢復(fù)事務(wù).
謬誤3:微服務(wù)更快
“一些簡單的優(yōu)化可以在單體系統(tǒng)中獲得巨大的性能提升.”
這條似乎很難被否定,因?yàn)槭聦?shí)上你可以通過減少單個(gè)系統(tǒng)的依賴或者做事情的數(shù)量來提高他們的速度.但這是一個(gè)看起來如此的方法.我并不懷疑轉(zhuǎn)向微服務(wù)架構(gòu)后通過代碼路徑的隔離讓系統(tǒng)速度提升,但是你也應(yīng)該意識(shí)到,系統(tǒng)內(nèi)增加了通過網(wǎng)絡(luò)的調(diào)用.網(wǎng)絡(luò)請(qǐng)求永遠(yuǎn)不會(huì)像同一系統(tǒng)中調(diào)用那樣快,盡管通常它可以足夠快.
此外,許多關(guān)于性能提升的故事實(shí)際上是在宣傳一種新的語言或者技術(shù)棧帶來的好處,而不僅僅是通過將代碼架構(gòu)遷移到微服務(wù)上.將原有系統(tǒng)從RubyonRails、Django或者NodeJS遷移至像Scala和Go(微服務(wù)架構(gòu)中兩種流行的選擇),這樣語言技術(shù)本身就能帶來很多性能改善.但是這些語言并不真的“關(guān)心”是否工作在“微”服務(wù)里面,他們只是單純的為了提高性能而存在.
此外,對(duì)于大多數(shù)應(yīng)用來講,CPU和內(nèi)存永遠(yuǎn)不是性能瓶頸,I/O才是.通過網(wǎng)絡(luò)進(jìn)行的調(diào)用,會(huì)為你的系統(tǒng)增加更多的I/O請(qǐng)求.
謬誤4:對(duì)開發(fā)人員更簡單
“開發(fā)人員工作在彼此隔離的代碼庫時(shí)容易導(dǎo)致‘不是我的問題’綜合癥.”
雖然聽起來一個(gè)小團(tuán)隊(duì)專注于一個(gè)問題上,處理問題會(huì)更加簡單,然而這會(huì)帶來許多其他的問題,比如更難以從根本上解決問題.
最大的問題是你必須多做許多工作,你必須運(yùn)行越來越多的服務(wù),即使為了很小的一個(gè)變化.這樣你不得不投入一些精力來建立和維護(hù)能讓工程師在本地運(yùn)行他們的辦法.Docker技術(shù)可以讓著更容易些,但是仍需要有人來維護(hù)他們.
另外,這讓寫測(cè)試也變得更加困難,因?yàn)橐粋€(gè)恰當(dāng)?shù)募蓽y(cè)試意味著需要理解并覆蓋所有服務(wù)之間的彼此調(diào)用,以及捕獲處理相應(yīng)的錯(cuò)誤等.這也意味著需要花更多的時(shí)間來理解系統(tǒng)才能更好的開發(fā).雖然我永遠(yuǎn)不會(huì)說工程師花時(shí)間理解系統(tǒng)是在浪費(fèi)時(shí)間,但是我要警告大家的是,不要過早地添加這些復(fù)雜性,除非你真的認(rèn)為你需要他們.
最后,它也會(huì)造成一些社交上的問題.跨越多個(gè)服務(wù)的Bug需要多處修改才能解決,多個(gè)團(tuán)隊(duì)需要同步協(xié)調(diào)他們解決問題的進(jìn)程.它也有可能造成一種情況,就是人們對(duì)Bug缺乏責(zé)任感,并盡可能地將問題推給其他團(tuán)隊(duì).當(dāng)工程師在同一個(gè)代碼庫中進(jìn)行工作時(shí),他們共享所有的知識(shí),承擔(dān)共同的責(zé)任,而不是成為孤立王國的國王和王后.
謬誤5:可擴(kuò)展性更強(qiáng)
“擴(kuò)容微服務(wù)就像擴(kuò)容單體應(yīng)用一樣簡單.”
將服務(wù)打包成離散單元,然后通過類似Docker的方式進(jìn)行擴(kuò)展,這似乎是一個(gè)水平伸縮的好方法,不過遺憾的是,這種說法并不對(duì).
說它不正確,是因?yàn)檫@種方法不僅僅能用于微服務(wù),更可以用于單體服務(wù).你可以為你的單體應(yīng)用創(chuàng)建邏輯集群,只處理某項(xiàng)業(yè)務(wù)的流量.比如API請(qǐng)求、前端儀表盤和后臺(tái)任務(wù)服務(wù)器可以在相同的代碼庫里面,但并不需要每個(gè)都處理三個(gè)不同的業(yè)務(wù).
好處就像是微服務(wù)一樣,不同的集群承擔(dān)不同的工作負(fù)載,可以單獨(dú)擴(kuò)容一個(gè)集群來應(yīng)對(duì)流量的激增.所以,雖然微服務(wù)提供了很多方法,你同樣可以把這些方法引入到單體應(yīng)用中去.
“當(dāng)你準(zhǔn)備好成為一個(gè)工程化組織時(shí).”
最后我想說,時(shí)間恰當(dāng)時(shí),可以遷移至微服務(wù)(或者你知道這是否是正確的開始方式).
實(shí)現(xiàn)微服務(wù)的一個(gè)至關(guān)重要最堅(jiān)實(shí)可行的重要步驟是,你能夠正確理解你正在工作的領(lǐng)域.如果你不理解它,或者你正在試圖弄清它,那么微服務(wù)則是有害無利.當(dāng)你真正深刻地理解你的領(lǐng)域,知道邊界在哪里依賴是什么,那么遷移至微服務(wù)架構(gòu)才有可能是正確的選擇.
另一個(gè)重要的事情是處理你的業(yè)務(wù)流,具體來說,就是業(yè)務(wù)如何進(jìn)行分布式事務(wù).如果你知道每一類請(qǐng)求通過系統(tǒng)的路徑,并且了解每個(gè)路徑上可能失敗的位置、方式和原因,那么你可以著手開始構(gòu)建一個(gè)處理請(qǐng)求的分布式模型.
除了了解您的業(yè)務(wù)流之外,還需要監(jiān)控你的工作流程.監(jiān)控是微服務(wù)和單體之爭(zhēng)的事情,但是它應(yīng)當(dāng)是你的工程化的核心工作之一.因?yàn)槟阈枰罅康臄?shù)據(jù)來發(fā)現(xiàn)系統(tǒng)為何性能不佳甚至引發(fā)錯(cuò)誤.只有你能找到一個(gè)可靠的方法來監(jiān)視系統(tǒng)的各個(gè)部分,你才可以知道如何來優(yōu)化它.
最后,當(dāng)你真正可以向研發(fā)團(tuán)隊(duì)和業(yè)務(wù)方展示價(jià)值時(shí),遷移到微服務(wù)才可以幫助你承擔(dān)增長的業(yè)務(wù)、擴(kuò)容和賺錢.雖然說嘗試新鮮事物是有趣的,但是你真正開始前,應(yīng)當(dāng)明白對(duì)于許多公司來說,什么是他們的底線.如果因?yàn)橐黄┛臀恼赂嬖V你單體應(yīng)用不科學(xué),而導(dǎo)致新功能的延期交付進(jìn)而影響到業(yè)務(wù)收入時(shí),你必須去迎合你的業(yè)務(wù).有時(shí)候這些權(quán)衡是值得的,有時(shí)候不是.能正確認(rèn)識(shí)到當(dāng)前應(yīng)當(dāng)著力解決的問題,并以此來做技術(shù)的權(quán)衡,長期來看才是真正有益的.
最后的最后
希望下次有人提出微服務(wù)架構(gòu)時(shí),你能想明白實(shí)施微服務(wù)架構(gòu)的條件是否成熟.就像我一開始所說的,本文并不是來說微服務(wù)是糟糕的,是希望你開始之前,能夠避免這條道路上會(huì)出現(xiàn)的一些坑.
如果你問我應(yīng)當(dāng)怎么做,我建議通過代碼中清晰定義的模塊結(jié)構(gòu)來建立內(nèi)部服務(wù),并且隨著時(shí)間的推移,逐漸將他們劃分成獨(dú)立的服務(wù).這種方法不一定是最好,但也不失為避免爛代碼進(jìn)入系統(tǒng)的一個(gè)方法.當(dāng)你準(zhǔn)備好時(shí),它能很快地幫你遷移到微服務(wù)架構(gòu)上.
文章出處:Docker(訂閱號(hào)ID:dockerone)
轉(zhuǎn)載請(qǐng)注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/4394.html