1. 程式人生 > >使用SpringCloud將單體遷移至微服務

使用SpringCloud將單體遷移至微服務

智能 約束 進入 feign 準備 自身 zip 路由策略 pen

使用SpringBoot構建單體項目有一段時間了,準備對一個老項目重構時引入SpringCloud微服務,以此奠定後臺服務能夠應對未知的業務需求。

現在SOA架構下的服務管理面臨很多挑戰,比如面臨一個非常大型的代碼庫,版本合並困難,甚至存在不同項目不同版本,維護量極其龐大,無法快速響應不同的業務需求;同時這些大型代碼庫由於沒有前後端分離,導致打包成一個大型的WAR包,服務自身無法獨立打包部署,在運行階段,隨著項目應用規模擴大無法平滑伸縮,只能通過部署新的應用服務器粗粒度應付;還有一個問題就是大量環境配置的管理相當復雜。

從單體遷移到微服務的實踐之道是:前後端分離,後端暴露restful api給前端。只有前後端分離,前端和後端才能分離部署,只有使用基於http的restful接口,後端才與周圍環境真正分離,如果只是使用RPC,雙方還和java接口耦合,而使用rest/json數據格式,雙方只要進行序列化和反序列化,雙方耦合沒有那麽緊密,這非常類似異步通訊中消息數據格式的耦合,用性能小降代價換來後端服務與周圍環境的解耦,只有這樣我們才能對後端再進行切分成微小服務,打包進入Docker,放入K8s平臺中調度運行。說白了,挖樹需要把樹根與周圍分離,整個樹才能移植,後端服務只有通過rest API前後端分離,才能安裝上Docker+K8s。

SpringBoot默認情況下已經開啟restful端口,這種約定大於配置的做法大大簡化了編程過程,同時也“強行”將微服務與Rest接口進行了綁定。

系統=大前端(SpringMVC或SPA等)+REST+後端

當後端服務從前端的約束羈絆中解放出來以後,完全走向了自由,可以為多個前端客戶端或其他系統提供服務API,當然系統也由此走上了分布式不歸路,服務之間調用不再通過JVM內部直接方法調用,而是通過rest/json交互,整個系統的復雜性也由此上升,SpringCloud為基於SpringBoot的分布式微服務開發提供了透明且開箱即用的開發方式,將很多屬於系統管理配置職責帶入了開發,由此對開發人員素質提出更高要求,這也是devops一詞的來由,devops=開發+運維。

下面談談SpringCloud的幾個分布式架構組件是如何簡化分布式開發和系統運維配置的。

配置服務器

配置服務器能夠將各種配置集中在一起,配置信息是一種鍵值對,暴露rest API,可以加密,能夠快速失效,也可以強制更新,在運行時能夠通過下面方式強行刷新到最新配置:

curl –X POST http://localhost:8080/refresh

CONFIG SERVER

這是一個很簡單方式,但是也要防止程序員不小心一個delete數據庫的災難事情發生。

API網關

如果說後端微服務組成了一個服務群,這個群是群主的,群主可以批準你加入也可以剔除你,API網關就是微服務的守門人,專業上稱為邊緣服務,微服務是核心,它是邊緣。

API網關的群主職責也還有其他:

1.設計上的適配層,或稱Facade模式,後端微服務可能過於細粒度,通過API網關進行內外適配,前後端轉換,如果220v轉換成110v一樣。

2.運行階段:將外部請求路由分發到內部各個微服務,負載平衡和路由策略是需要的。

Springcloud之前使用NETFLIX ZUUL作為API網關,雖然它有很多好處,容易設置,限速和日誌過濾,可授權,智能負載平衡,攻擊探測和阻止,但是很難管理網關和API的超時。使用Spring ZUUL編程時,最大特征就是編制各種過濾器,事前過濾器 路由過濾器和事後過濾器。

在很多地方,也有使用Nginx作為API網關,Nginx官方有不少文章講述Nginx如何在微服務架構中扮演重要角色的.

NGINX和zuul 1.0是堵塞的,而Zuul 2.0、Spring Cloud Gateway和Linkerd, Envoy是非堵塞的,後兩者借助API網關推出服務網格概念,能夠統一對成千上百微服務進行管理,不過這好像又回到了服務器為王的時代,微服務好不容易打破服務器的約束,走出服務器的多租戶空間獨立成王,現在又會被打著API網關旗幟的新的統一管理方式關起來嗎?

SpringCloud提供Reactive響應式架構,使得分布式網絡通訊效率大大提高,分布式系統的IO不再成為性能瓶頸。

服務發現

在分布式環境,許多服務實例都不斷因為開發而不斷變化,時而上線,時而下線,微服務之間如何好好發現活著的對方也是個問題,這就是需要服務註冊器,每個微服務向其註冊,其他需要調用的微服務通過註冊器發現對方進行調用,調用時可加入負載平衡策略.

Spring Cloud推薦使用NETFLIX EUREKA,用CAP定理來看,它屬於AP,而Zookeeper屬於CP,因此後者不是非常適合應用在服務發現場合,它本來誕生於大數據應用場景,雖然後來被Hadoop拋棄。

NETFLIX EUREKA易於設置,基於Rest的服務註冊,支持復制,支持客戶端緩存,速度快雖然數據容易不一致(AP)。

如果直接基於Eureka進行服務註冊和發現,需要手工將負載平衡策略與REST處理綁定在一起,而通過Feign組件能夠默認實現負載平衡+REST方式的通訊,只要像普通REST調用即可,大大提高了開發效率,其內部使用Ribbon負載平衡器和hystrix斷路器。


@FeignClient(name="PengProducerService")
public interface ConsumerService {

@GetMapping("/articles")
List<Article> getAllArticles();
}
運維

SpringCloud提供了SLEUTH方便跟蹤請求級別的微服務調用,是一種分布式跟蹤解決方案,與Zipkin等結合,形成生產運維監控管理,能夠掌握每個微服務實例調用時間。

HYSTRIX斷路器能夠增強系統的彈性,在微服務無法訪問時重試,重試幾次後就放棄,也能進行快速失效,不把時間耗費在無謂的等待上,防止故障爆炸。提供儀表板實時情況。

身份驗證和授權

前後端通過REST分離以後,需要一種基於令牌的方法來與前端對話,還需要對每個請求進行身份驗證和權限驗證。

OAuth2是一種開放的標準授權協議規範,雖然目前不能完全取代OAuth1.0a,但是會不斷日趨完善。

一旦用戶請求通過OAuth進行了身份驗證和權限驗證,API網關會放行這個請求到後端微服務中,但是如果請求中沒有攜帶身份信息,在後端微服務實例之間轉了幾個圈後,微服務無法確保是否可以接受這個請求了,因此,需要在每個請求裏攜帶通過驗證的用戶身份信息,這就需要采取JWT(JSON WEB TOKEN), JWT能使用HMACSHA256進行簽名,或者使用RSA進行公有/私有鍵值對簽名,可以通過URL,POST參數或者在HTTP header發送,因為數據量小,傳輸速度也很快,由此避免了各個微服務多次查詢數據庫以搞清楚當前請求的身份信息。

總結:

了解了SpringCloud架構以後,遷移之路也就明細了:

整個核心是服務註冊和發現,因此首先開始應用服務註冊,但是服務註冊中心容易變成單點風險,談不上高可用性,一旦這個單點崩潰,全局奔潰,那麽準備兩套註冊中心,引入配置服務器,在兩套註冊中心之間進行切換變得非常重要,由於配置服務器一旦修改,需要通知很多組件,因此需要引入異步通訊,由此需要Spring Cloud Bus。

第一步:註冊中心

第二步:配置服務器

第三步:Spring Cloud bus通訊總線

第四步是數據庫的切分,使得每個微服務只有一兩個數據庫。

第五步是切入基於事件的事務架構,比如EventSourcing等等。

第六步是安裝上底座:Docker化和Kubernetes調度Paas平臺化。
---------------------

參考:https://blog.csdn.net/gupao123456/article/details/81030839

使用SpringCloud將單體遷移至微服務