本文轉載自微信公衆號「SH的全棧筆記」,做者leonhlh 。轉載本文請聯繫SH的全棧筆記公衆號。前端
這篇博客的本意是但願看到這篇文章的讀者可以很輕鬆的理解我想表達的意思。但程序向的分享常常會不經意間就貼上了代碼,極可能就會讓人看的很懵。並且我認爲分享一個東西,只有對方真正明白了其中的邏輯,纔是有意義的分享。因此接下來我會嘗試用你們都能理解的語言來聊一聊」微服務「。算法
【寫在前面】編程
那麼,什麼是微服務呢?你不必定知道微服務,可是你必定知道麥某勞,並且知道麥某勞有個甜品站。你可能會問,甜品站和微服務有什麼關聯呢?後端
讓咱們先假設不把甜品站獨立出來,而是普通的麥某勞店。經營一段時間你會發現,這個地方雖然人流量很大,也有顧客,可是顧客的需求80-90%都集中在甜品,致使甜品供不該求,而其他的菜品則沒多少人購買。可是把這個店關了嗎?那也不行,始終是有流量的。緩存
因此綜合考慮下來,方案就是把甜品這個「模塊」從整個店中獨立出來,單獨對外提供服務。這樣既能保住流量,也能避免浪費。安全
微服務也是同樣的,好比電商的服務,假設裏面耦合了商品、庫存、訂單、用戶的服務,可是訂單這個模塊可能會訪問的特別頻繁,而用戶和商品被訪問的頻率沒有那麼高,若是爲了同時給更多用戶提供服務,而再部署一個包含了商品、庫存、訂單和用戶的服務,有兩個模塊的資源其實沒有被充分利用到。服務器
跟甜品站的思路是同樣的,若是把商品、庫存、訂單和用戶分紅四個服務模塊,每一個服務只負責處理的本身的事情,就像甜品站只賣甜點同樣,若是訂單的訪問量大, 那也只須要再部署一個訂單的模塊,而不會形成資源利用不充分、耦合性強的狀況。微信
最開始的「整家麥某勞」店對應的概念就是單體應用,後面獨立出的「甜品站」就是從單體應用中抽離出的「微服務」。不知道什麼是單體應用和微服務是什麼不要緊,不知道單體應用爲何、以及如何轉變成微服務的也不要緊,讓咱們經過一個故事來完整的理解這個概念。架構
假設正在閱讀這篇文章的你,擁有一家飯店。負載均衡
0.【夢開始的地方】
你盤下了一個店面想賣炸雞和甜品,因而你簡單的把店裝修了一下,購置了相關的設備,而後僱了廚師、服務員等相關的工做人員,就開始掛上招牌對外營業了,
0.1 店面
就是咱們日常去使用的各類C端產品,若是你沒有一個概念,那麼能夠直接把它理解成釘釘、微信這樣一個咱們平常都在用的APP就好,它們就是C端產品。
店的招牌(好比肯打雞和麥某勞)就能夠理解爲咱們日常APP裏所能看到的,所能使用的東西,咱們叫它客戶端。
整個實體店就能夠理解爲開篇提到的「單體應用」,爲客戶提供實際的服務。
0.2 裝修和購置設備
對應的是咱們的開發團隊,從產品經理接到客戶的需求開始,根據需求整理好原型圖,不停的跟客戶溝通交流細節,反覆的修改原型圖,最終定下來的需求。
而後咱們的UI同窗介入,根據原型圖出UI圖,並最終肯定下來。而後就是前端和後端的開發同窗根據原型圖中的邏輯,和UI圖的樣式細節開始迭代開發,並最終將產品上線。
0.3 炸雞和甜品
有了前面麥某勞的例子,這個應該很好理解。炸雞和甜品其實就是做爲一個C端產品,提供給用戶的不一樣種類的服務。
例如咱們平常在用的釘釘,能夠用來聊天、開視頻會議和預約會議室。
1.【漸入佳境】
隨着你不斷的推出新的菜品,以及份量足,性價比高,朋友之間口口相傳—「那家蒼蠅館子還能夠」,也留住了大量回頭客。慢慢的,來店裏吃飯的客人愈來愈多,後廚漸漸忙不過來了。不少慕名而來的客人因爲等了太長時間仍然沒有上菜,更有甚者連座位沒有。客人對美食的渴望轉化成了失望和憤怒,因而反手就是一個超級差評。
1.1 不斷的推出新的菜品
表明咱們的產品迭代,不斷的推出新功能,以此來爲用戶提供更多元化的服務,吸引更多的用戶來使用咱們的產品。例如疫情期間,釘釘在在線學習這塊推出了不少新的功能。
1.2 朋友間的口口相傳
則表明的是部分用戶開始代替廣告這種傳播途徑,開始了社羣內的用戶自傳播。這是不少產品都想達到的目的,把產品的潛力挖掘到極致,讓產品說話,爲本身代言。
比起漫天飛的廣告,這種來自朋友們的推薦,更加受到用戶的信任。
1.3 關於差評
「後廚忙不過來」是指用戶數量上漲,平常的請求數就會隨之增多,而單個服務實例在某個時間單位內可以處理請求的數量是有限的(也就是後廚人數有限,就那麼幾個廚師,能作的菜數量也有限),這也直接致使了部分用戶請求十分緩慢,甚至直接沒法訪問(後廚實在忙不過來了,有些客人就要等好久)。而用戶對於產品的耐心是十分有限的,出現這種狀況會致使部分甚至大量用戶流失。
2.【蜂擁而至】
隨着差評愈來愈多,你漸漸坐不住了。你以爲再這麼下去你可能就要涼了,因而你想,廚師不夠用那就多招幾個嘛,因而雷厲風行的你貼出了招聘啓事,而後順利的招到了人。
人的問題解決了,那還有座位的問題。以前你沒有想到會有這麼人多來光顧,因此店裏面的桌子和椅子擺的很寬鬆,可是實際上從新規劃一下,仍是可以多放好幾張桌子的,這樣一來就可以同時容納更多人在店裏用餐。
2.1 多招人
咱們每一個服務所能使用的資源是有限制的,例如你能夠給你的JVM設置最大堆內存爲1G,也能夠加到2G。啊?什麼是JVM?不重要,讓咱們從新理解前面一句話。2個廚師一分鐘能夠作5個菜,你轉手再招2個廚師,那一分鐘就能夠作10個菜,這對應的概念是擴容,也就是增長服務器可以支配的運行資源,服務器就可以處理更多的請求,服務更多的用戶。
這裏的擴容是針對CPU和內存
2.2 從新規劃桌椅擺放
剛開始開發時沒有到用戶會有這麼大致量,因此大部分的API沒有作什麼優化,整個服務端應用的框架也搭建的很隨意,由於上線的時間很緊,這可能會形成應用在維護性、擴展性和性能上的弊端。
通俗點來講就是,當時爲了店裏擺放好看,追求ins風,桌椅之間擺的太寬了,可是後來人多了,外面一堆人排隊,店裏面卻熙熙攘攘,可是實際上你倒是已經「坐滿了」。
這種狀況十分不利於後續的迭代的。因此對應到開發中的概念就是,對代碼和框架進行重構,優化算法,讓API儘可能少佔用系統資源,下降響應延遲,從而提升整個服務的服務能力。這樣一來,服務實例就能扛住更多的請求。
不過有的時候,下降延遲和少佔用系統資源不可兼得。若是對響應速度要求很高,就可能會多佔一些系統資源,用空間來換時間。
就像你把店裏從新擺放了,店裏容納的人多了(佔用資源多了),這個時候服務的響應時間可能就會變慢(上菜就會變慢),那麼用空間換時間是什麼呢?就是你會提早準備不少食材、甚至是半成品的食材堆在那裏,這樣以來,只須要花平時一半的時間就能夠把菜作好(好比提早準備好熟油,各類輔料等等)。
3.【山窮水盡】
雖然多招了幾個廚師,也從新規劃了店裏桌椅擺放,可是隨着時間的推移,天天來店裏吃飯的人仍是愈來愈多,廚師已經不能再招了,已經沒有那麼多竈臺了。以前的「差評熱潮」又開始在店裏上演。你想着,雖然店裏火爆是好事,可是天天有那麼多的人來店裏看到沒有位置就走了,這不是有錢賺不了嗎?
並且不少目標用戶在第三方網站上看到了這些差評,將會直接影響到客戶是否願意來店裏,這會使你喪失大量的隱藏客戶。因而你開始了轟轟烈烈的開分店業務,在附近又開了一家店。仍是同樣的配方,就是這個味~
3.1 開分店
開分店對應的概念是多實體部署,就是把一個一樣的服務再部署一個,這樣一來來自用戶的流量就從一個服務扛變成了兩個服務扛。
分店就能夠把本來要把總店塞爆的流量給接過去,緩解了壓力。
4.【柳暗花明】
隨着時間的推移,分店越開越多,生意天然也是蒸蒸日上。可是你做爲一個可以不僅看表面的佈局者,你發現了實際上的狀況並無表現出來的那麼好。
有些區域人流量大,而有些區域雖然人流量大,可是對店感興趣的人很少,甚至分店周圍根本沒有什麼人。而有些地方的分店則異常火爆。雖然熱門的店賺的錢可以抵上冷門的店的虧損,可是追求完美的你認爲這種狀況必需要獲得改善,由於這始終是存在對資源的浪費。
因此通過一番調研,你決定在中心區域開一個顧客中心,全部想來餐廳的人都統一的來顧客中心,由顧客中心的人根據各個分店的火爆狀況來分批次的把顧客送過去。這樣一來,也就解決了有些店火爆,而有些店冷清的狀況了。
4.1 人流量分佈不均勻
這種狀況主要發生在服務端運行了多個實例,那也就對於多個IP地址,而要調用哪一個是由客戶端來決定的,若是設計的不夠好,就會出現某些時候某些實例成爲熱點實例,甚至出現「差評」實例這種狀況,而其他實例則沒有承擔多少來自用戶的流量。
說人話就是,我要是顧客,我去哪家店不是看我心情嗎?我想去哪家店就去哪家店。固然實際狀況沒有這麼誇張,客戶端會有本身的策略。
並且同時維護如此多的服務端地址也是很麻煩的一件事,若是服務端此時又增長了實例,客戶端則須要同步的更新。可是若是用戶體量大的話,由於這種問題頻繁的發包讓用戶更新,會對用戶形成很差的體驗。
4.2 顧客中心
這個比喻有些誇張,現實中有人這麼幹可能早破產了。「顧客中心」就是咱們說的「網關」。有了網關,客戶端就不用關心服務有多少個實例,也不用去維護全部的HOST,全部的請求直接從網關走,由網關來決定將當前請求分發到哪一個實例。
「客戶中心分批次根據狀況送顧客」其實對應到的概念是負載均衡,什麼意思呢?就是要讓客戶端產生的流量對全部實例雨露均沾。其實現的方式也有不少,大體分爲隨機、輪詢、一致性哈希、加權等等。
而網關除了負載均衡,還有不少其餘的特性。例如,動態的路由、限流、認證、日誌、熔斷、可編程插件配置等等。
5. 【微服務的關注點】
看完了這個故事,你可能會以爲沒有什麼,可是實際上你已經瞭解了一個應用從單體應用架構轉爲微服務的架構生命週期以及過程。這其中也包括爲何須要轉爲微服務架構,和轉到微服務架構的好處在哪裏。若是你都沒有意識到本身理解了這個概念,能夠再閱讀一遍上面的小故事。
其實實際上的微服務要比上面故事所呈現出來的複雜不少,微服務中須要關注的點要比傳統的單體應用多的多。在微服務中咱們須要關注服務的發現、負載均衡,統一的配置管理,微服務集羣的自愈和彈性伸縮,服務的調度和發佈,微服務中的調用鏈監控,包括Metrics監控,日誌監控,服務的安全考慮,API的統一管理等等。
首先把強耦合在一塊兒的代碼有條理的拆分出來就是一件很複雜的事情,微服務的劃分粒度也是一個很大的挑戰。例如很複雜的系統,一個用戶服務的代碼可能有好幾千上萬行,可是它仍然是一個微服務,沒有再拆分用戶服務A和用戶服務B。而有的服務可能代碼量只有幾百行,這須要根據實際的業務狀況來選擇劃分的粒度。
除了拆分服務的粒度,微服務自己還有不少組件。你們在故事中只瞭解了網關。其實還有不少組件。
服務發佈就涉及到Jenkins,把咱們的應用打包成Docker Image,而後經過自動化工具發佈到對應的環境中。咱們的應用跑在Docker中,那麼咱們就須要有一個容器編排工具來管理這麼多容器。例如咱們如今使用的就是Docker Swarm,跟業界如今流行的Kubernetes同樣,有不少人在使用。
有了容器編排工具,就有工具的可視化界面,Docker Swarm對應的Portainer,和Kubernetes對應的Rancher。除此以外咱們還要使用Gitlab來作咱們的代碼版本管理工具,MySQL和MongoDB做爲數據存儲的解決方案。Redis做爲緩存的解決方案。同時須要有一個地方來統一管理全部服務的配置,咱們叫微服務的配置中心。
除此以外,服務之間要相互調用就必需要知道對方的地址,就須要一個註冊中心,來保管全部服務的地址,並及時的更新服務的狀態。
還有不少細節,例如如何去構建一個Jenkins的構建流水線,若是實現一套CI/CD的流程,若是使用ELK去作統一的日誌收集,若是在集羣內實現SSO啊等等,因爲篇幅緣由就不在此一一贅述了。
【編輯推薦】
【責任編輯:武曉燕 TEL:(010)68476606】