Spring Cloud實戰(zhàn)微服務及架構概述
文章目錄
自從Martin Fowler在2014年寫了一篇名為Microservices的文章后,微服務就在服務端架構中開始流行起來,至今依然很火熱。
微服務架構模式是目前最流行的架構模式之一。在各互聯(lián)網(wǎng)公司中,都有著豐富的實踐案例。比如國外的有Amazon、eBay、Netflix等。國內(nèi)的有阿里巴巴、騰訊、百度等。
近年來,同花順也有諸多項目基于微服務架構實現(xiàn),積累了大量的微服務架構實踐案例。
2015年Dubbo
2017年Spring Cloud
2019年Spring Cloud In K8s
那么什么是微服務架構呢?
微服務架構的本質就是將一個原本獨立的系統(tǒng)拆分成多個小型的服務,這些小型的服務都在各自獨立的進程中運行,服務之間通過遠程通信進行調用。
我會以互聯(lián)網(wǎng)大金融綜合實訓平臺為例來講解一下微服務架構的演變過程。
有一天,產(chǎn)品跑過來說,我們需要做一個面向金融相關專業(yè)學生的模擬實踐訓練系統(tǒng)。這個系統(tǒng)的需求是這樣子的,我們需要有老師和學生兩個角色。老師能夠管理學生,舉行交易比賽和查看交易記錄。學生呢,可以相應的在上面進行模擬交易。
好,我們來梳理一下需求:
看上去很簡單嘛(SO EASY !),需求不多,開發(fā)同學們,(啥也不說,擼起袖子來),拿起鍵盤就是干。
搭框架:
Spring, Spring MVC, MyBatis。
Controller, Service, Dao。
一頓操作猛如虎,由于第一階段的需求不多,系統(tǒng)很快就開發(fā)完成了,經(jīng)過測試可以部署上線。?? ??
系統(tǒng)上線后,也滿足了實踐教學的需要。同學們可以在系統(tǒng)里真實的體驗股票交易,老師可以方便的進行查看同學們的交易記錄,提出合理的指導和給出相應的得分。大家都很開心,心里美滋滋。(好開心,好有成就感,滿滿的自豪。我們真是棒棒噠!???)
其他課程的老師看到了,嗯,這個系統(tǒng)不錯,我們也要。于是,吧啦吧啦,產(chǎn)品同學經(jīng)過一波分析和整理。我們需要上線以下功能:
交易中心,模擬公司,銀行,基金,期貨。
功能一多,產(chǎn)品設計變得復雜,期間伴隨著一大波需求變更。
OK。開發(fā)同學們一接到需求,就噼里啪啦的往里面加功能。很快,功能又開發(fā)完成了。這個時候的系統(tǒng)變成了下圖這樣子。
雖然,代碼開發(fā)完成,功能也如期提測。但是,這個時候問題也開始逐漸的暴露出來了。(?好心塞喲??? ??)
測試人員開始抱怨了…
發(fā)布怎么這么慢呀。
怎么這多BUG呀。
這個功能怎么又壞了啊。
為什么會出現(xiàn)這些問題呢?
由于單個系統(tǒng)的功能越來越多,代碼也越來越多,引用的第三方包也越來越多,導致系統(tǒng)在初始化的時候需要做更多的事情,那么啟動時間也自然變得越來越慢。
功能變得復雜,業(yè)務之間存在著關聯(lián)關系。但是,模塊和模塊之間卻沒有清晰的隔離,在完成需要跟其他模塊進行交互的功能的時候,隨意的加接口,改接口,直接查對方的數(shù)據(jù),這將導致代碼的耦合性變得越來越高,導致修改變得越來越困難。
anyway,不管怎么樣,在測試和開發(fā)同學的共同努力下,BUG也被一一解決了。測試通過,系統(tǒng)終于上線了。但是,噩夢以此為始,線上問題開始不斷冒出來。(?我太南了??? ???)
系統(tǒng)會時不時的變慢。由于,所有模塊都在一個進程中,老師進行對學生操作記錄的統(tǒng)計,導出等相關操作,一旦出現(xiàn)問題,都可能會影響到股票模塊的正常進行。
擴容造成的資源浪費。模塊和模塊之間的訪問量是不同,比如教學模塊和股票模塊,由于教學模塊主要是面向教師進行一些管理操作,而股票模塊會有更多的學生參與交易操作。簡單的講,那么我們可能需要9臺機器來部署股票模塊,1臺機器來部署教學模塊。但是呢,我們需要把整個應用一起擴容,下面灰色部分其實是多余的模塊,白白消耗了機器的資源。
開發(fā)同學們反思了一下,不能一直這樣下去,我們需要進行改變。
我們對原有的系統(tǒng)進行了一系列的拆分。我們根據(jù)業(yè)務的功能獨立性,重要程度,訪問量,IO型(文件操作)和非IO型進行了拆分,服務和服務之間通過HTTP接口相互交互?,F(xiàn)在系統(tǒng)變成了這樣。
服務和服務之間完全被隔離開來。我們來看看拆分后的結果。
對于穩(wěn)定性, 由于每個微服務都是獨立的進程,通過進程的隔離,我們能夠保證在某個服務不可用的時候,其他服務還是可以正常的使用。
對于伸縮性,我們對于業(yè)務資源的調整粒度更加的小,我們更加方便的進行業(yè)務資源的擴容和縮減,同時擴容和縮減所需要的時間也更短。
對于可修改性,我們將系統(tǒng)進行拆分,每個服務之間必須通過接口來進行遠程調用,這樣子能夠保證服務之間的耦合只存在于接口。同時,由于拆分,每個服務專注于自己的業(yè)務實現(xiàn),保持了高內(nèi)聚的特性。我們在做修改的時候只需要關注修改操作不要對接口產(chǎn)生影響即可。
到這里,我們使用拆分解決了剛剛在單體應用中遇到的幾個問題。但是,這樣就好了???
(?Naive?。。?!)
服務擴容的時候,如何把新機器的IP地址告訴調用方?
如何防止某個服務不可用帶來的雪崩效應?
如何將請求在服務之間的調用鏈路顯示出來呢?
如何管理配置和動態(tài)的將配置發(fā)布出去?
接下來我們要針對這幾個問題,一一的進行解答。
上述問題都可以通過引入微服務框架得到解決。
我們來想象一下這樣的場景:用戶量激增,原來的幾個實例不夠用了,我們需要新加幾個股票實例怎么辦?或者上課時間請求量多,非上課時間段請求量少,那么我們應該在非上課時間下線幾個實例吧。
我們找了幾臺服務器把應用部署了上去,這個時候還要去把新的IP地址配置到Nginx中,下線的時候從Nginx當中去除掉。手工操作太麻煩,太累,容易出錯。
同時,集中式的Nginx又會成為我們的瓶頸。怎么辦?
首先,我們可以將Nginx的負載均衡功能內(nèi)嵌到我們的應用當中,減少集中式的流量。
其次,我們需要部署一個注冊中心來動態(tài)的維護所有服務實例的地址信息,其需要具備以下功能:
服務啟動的時候,將自己的地址信息注冊到注冊中心
服務方定時報告健康狀態(tài)給注冊中心,如果服務掉線,注冊中心就將該實例剔除出去
調用方定時的從注冊中心獲取最新的地址列表
雪崩效應:服務之間存在著層層的依賴關系,服務A的不可用將會引起服務B的不可用,同時不可用將像滾雪球一樣放大到C和D。
在分布式系統(tǒng)中,故障無處不在,我們要應該擁抱故障,在故障出現(xiàn)時合理的處理它。對于調用其他服務,我們要始終保持懷疑,其他服務可能會是個“壞人”。
下圖中可以看到,由于股票服務出現(xiàn)故障不可用,將會導致交易中心會不斷重連,并會在連接的超時時間內(nèi)建立很多的連接請求,最終占滿交易中心的連接池,導致交易中心的服務也不可用。
交易中心不可用后,將會將錯誤蔓延到學生端。最終導致服務的全面崩潰。
那么我們應該如何去處理雪崩效應呢?
我們可以想象一下,家里的電路。當我們家里的電器發(fā)生短路時候,電路就會自動跳閘,從而保護其他電器。
斷路器模式也一樣的,當我們發(fā)現(xiàn)其他服務出現(xiàn)問題的時候,我們應該拉下電閘,不去請求對方,保護我們自己服務的正常進行。
使用斷路器時,當對下游資源的發(fā)起的請求連續(xù)失敗過多,達到閾值時,斷路器會打開。
這個時候,接下來的所有請求都會快速地失敗,不再去調用下游資源。
同時,每隔一段時間,客戶端發(fā)送一些請求試著訪問一下下游服務,看看是不是能夠訪問,如果它得到了正常的響應,將關閉斷路器。接下去的請求就又能夠成功的通過了。
我們知道,微服務之間通過網(wǎng)絡進行通信 。 我們需要快速的定位到問題出在哪個服務上。如果能夠跟蹤每個請求,了解請求經(jīng)過哪些
微服務(從而了解信息是如何在服務之間流動) 、 請求耗費時間、網(wǎng)絡延遲 、 業(yè)務邏輯
耗費時間等指標,那么就能更好地分析系統(tǒng)瓶頸、解決系統(tǒng)問題。
下圖是zipkin的界面展示圖,我們可以很清楚的看到請求在服務之間調用的先后關系和耗時。
要完成這個效果,我們需要將效果轉換成可以實現(xiàn)的數(shù)據(jù)結構,如下圖所示。整個鏈路我們稱之為Trace,每個請求的分支一一對應的就是Span。
首先,通過記錄Trace和Span的父子關系,我們可以建立一個樹形的結構。由于我們在一次請求中共享同一個TraceId,然后根據(jù)TraceId查找出所有關聯(lián)的日志信息。同時,我們可以根據(jù)SpanId的父子關系重構出當時請求的結構。
TraceId:TraceId標識一次請求中的所有日志。
SpanId:標識一個分支節(jié)點,用于單獨計算持續(xù)時間。比如遠程調用,方法調用等。
ParentSpanId:父節(jié)點的spanId。 根據(jù)和SpanId的關系我們可以整理出一個樹形的結構。通常Root節(jié)點的ParentSpanId即為TraceId。
接著,通過記錄幾個時間戳,來分析請求的耗時和先后次序。
cs(client send):客戶端發(fā)起請求的時間。
cr(client recive):客戶端接收響應的時間。
sr(server recive):服務端接收到請求的時間。
ss(server send):服務端發(fā)送響應的時間。
另外,我們根據(jù)各個端點收集到時間戳信息??梢赃M行以下的計算,
請求總耗時 = cr - cs
網(wǎng)絡耗時 = sr - cs
服務內(nèi)部處理時間 = sr - sc
最后,我們需要將各個機器上的日志集中到一起
我們在每個客戶端內(nèi)置一個client,異步的將內(nèi)存中的請求日志發(fā)送到zipkin服務端,服務端在統(tǒng)一將日志存儲起來。
隨著業(yè)務的發(fā)展、微服務架構的升級,服務的數(shù)量、程序的配置日益增多,因此集中管理配置是非常有必要的 。 同時,我們需要達到修改配置,無需重啟,實時將配置推送到客戶端。
很多時候,應用中包含著許多無需修改代碼的配置屬性。例如,我們調用其他部門的接口某天突然通知,我們的服務器地址要變了,你們也改一下吧。好吧,原先怎么做呢,配置文件需要改一下,然后重新打包發(fā)布上線。現(xiàn)在呢,鼠標點一點。配置中心改一下,然后推送到應用方,應用方自動動態(tài)更新,都不用重啟,爽。
這個時候我們需要一個配置中心協(xié)助我們管理配置和動態(tài)發(fā)布配置功能。
那么怎么做到呢?
應用方需要在本地配置配置中心的地址。
通過配置中心修改和發(fā)布配置后,調用應用的相關接口告知進行配置刷新。
然后應用主動拉取配置中心的最新配置文件,并根據(jù)最新的配置文件動態(tài)更新本地內(nèi)存中的相關數(shù)據(jù)。
剛剛所介紹的都是對微服務中幾個問題的相應解決方案,那么都有一些什么框架能夠實現(xiàn)這些方案呢。
微服務的實現(xiàn)框架有很多,比如Dubbo、Zookeeper等,我們?yōu)槭裁匆x擇Spring Cloud呢。
Spring Cloud是一個解決微服務架構實施的綜合性解決框架,它整合了諸多被廣泛實踐和證明過的框架作為實施的基礎部件,又在該體系基礎上創(chuàng)建了一些非常優(yōu)秀的邊緣組件。所有微服務實施中需要的相應解決方案,Spring Cloud都幫我們實現(xiàn)了。像Dubbo或者Apollo都只是實現(xiàn)了微服務框架中的某個組件。
服務治理:Dubbo、Eureka、Zookeeper、Consul等
配置管理:百度的Disconf、攜程的Apollo、淘寶的Diamond、Spring Cloud的Config、Netflix的Archaius等
服務跟蹤:Zipkin、Uber的Jaeger、Spring Cloud的Sleuth等
組件名稱組件用途
Spring Cloud Netflix Eureka服務注冊和發(fā)現(xiàn)
Spring Cloud Netflix Hystrix服務熔斷和降級
Spring Cloud Netflix Zuul服務網(wǎng)關
Spring Cloud OpenFeign服務調用
Spring Cloud Config配置中心
Spring Cloud Sleuth服務跟蹤
典型的基于Spring Cloud的微服務應用,其需要用到如下組件:
具體每個微服務組件怎么用呢?
且待后續(xù)系列課程 一 一分解!?。?/b>
本博客所有內(nèi)容僅供學習,不為商用,如有侵權,請聯(lián)系博主謝謝。
[1] Martin Fowler. https://martinfowler.com/articles/microservices.html
[2] Netflix. 服務全球超 1.5 億用戶的微服務實踐. https://www.infoq.cn/article/f_Q7xWtgZ93djZALqWoP
[3] 朱勇. 阿里巴巴微服務技術實踐. https://www.infoq.cn/article/KGxyTJb2Cr7hguKmjg0p
[4] 周立. Spring Cloud與Docker微服務架構實戰(zhàn).
[5] Opentracing. https://opentracing.io/docs/getting-started/
owler. https://martinfowler.com/articles/microservices.html
[2] Netflix. 服務全球超 1.5 億用戶的微服務實踐. https://www.infoq.cn/article/f_Q7xWtgZ93djZALqWoP
[3] 朱勇. 阿里巴巴微服務技術實踐. https://www.infoq.cn/article/KGxyTJb2Cr7hguKmjg0p
[4] 周立. Spring Cloud與Docker微服務架構實戰(zhàn).
[5] Opentracing. https://opentracing.io/docs/getting-started/
[6] 微服務設計.