溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于SpringCloud的微服務架構演變史?

發布時間:2020-07-30 23:12:56 來源:網絡 閱讀:199 作者:wx5d9ed7c8443c3 欄目:編程語言

前言

一段時期以來 “微服務架構 ”一直是一個熱門詞匯,各種技術類公眾號或架構分享會議上,關于微服務架構的討論和主題也都非常多。對于大部分初創互聯網公司來說,早期的單體應用結構才是最合適的選擇,只有當業務進入快速發展期,在系統壓力、業務復雜度以及人員擴展速度都快速上升的情況下,如何快速、穩妥有序的將整個互聯網軟件系統升級成微服務架構,以滿足業務發展需要及技術組織的重新塑造,才是進行微服務架構的最主要的動力,否則空談微服務架構是沒有意義的。

而一旦決定將整個應用體系按照微服務架構體系進行升級,就需要有組織有計劃的進行業務系統、基礎架構、運維體系等多個方面的升級配套。而另一個比較尷尬的現實是,一般業務發展進入到需要進行微服務架構層面的時候,業務發展往往又都是非常迅猛的,這種業務快速發展和增長的壓力往往又會給整個技術團隊帶來非常大的挑戰,因為此時你需要取舍,是簡單方案快速支撐呢?還是選擇適當長遠一點的方案?當然這種情況大部分是技術細節方面的問題,掌控的“度”大部分情況是掌握在具體的工程師手中。

而如何整體上確保應用體系及組織結構向微服務時代快速、有序的跨越,是一件十分考驗團隊能力以及架構管理水平的事。能做到80分已然算優秀了,因為這是有其客觀規律的!

作者自身親歷了一個快速發展的互聯網公司從單體應用~以SpringCloud為技術棧的微服務架構體系的全過程。本文將主要從技術角度與大家探討如何利用SpringCloud進行微服務架構拆分,以及在這個過程中一點自己的思考。水平有限,不足之處還請包涵!

系統架構演變概述

在公司業務初創時期,面對的主要問題是如何將一個想法變成實際的軟件實現,在這個時候整個軟件系統的架構并沒有搞得那么復雜,為了快速迭代,整個軟件系統就是由“App+后臺服務”組成,而后臺服務也只是從工程角度將應用進行Jar包的拆分。此時軟件系統架構如下:

基于SpringCloud的微服務架構演變史?

而此時整個軟件系統的功能也比較簡單,只有基本的用戶、訂單、支付等功能,并且由于業務流程沒有那么復雜,這些功能基本耦合在一起。而隨著App的受歡迎程度(作者所在的公司正好處于互聯網熱點),所以App下載量在2017年迅猛增長,在線注冊人數此時也是蹭蹭往上漲。

隨著流量的迅猛增長,此時整個后臺服務的壓力變得非常大,為了抗住壓力只能不斷的加機器,平行擴展后臺服務節點。此時的部署架構如下:

基于SpringCloud的微服務架構演變史?

通過這種方式,整個軟件系統抗住了一波壓力,然而系統往往還是會偶爾出點事故,特別是因為api中的某個接口性能問題導致整個服務不可用,因為這些接口都在一個JVM進程中,雖然此時部署了多個節點,但因為底層數據庫、緩存系統都是一套,所以還是會出現一掛全掛的情況。

另一方面,隨著業務的快速發展,以往相對簡單的功能變得復雜起來,這些功能除了有用戶看得見的、也會包括很多用戶看不見的,就好像百度搜索,用戶能看見的可能只是一個搜索框,但是實際上后臺對應的服務可能是成百上千,如有些增長策略相關的功能:紅包、分享拉新等。還有些如廣告推薦相關的變現功能等。

此外,流量/業務的增長也意味著團隊人數的迅速增長,如果此時大家開發各自的業務功能還是用一套服務代碼,很難想象百十來號人,在同一個工程在疊加功能會是一個什么樣的場景。所以如何劃分業務邊界、合理的進行團隊配置也是一件十分迫切的事情了!

為了解決上述問題,適應業務、團隊發展,架構團隊決定進行微服務拆分。而要實施微服務架構,除了需要合理的劃分業務模塊邊界外,也需要一整套完整的技術解決方案。

在技術方案的選擇上,服務拆分治理的框架也是有很多,早期的有如WebService,近期的則有各種Rpc框架(如Dubbo、Thirft、Grpc)。而Spring Cloud則是基于Springboot提供的一整套微服務解決方案,因為技術棧比較新,并且各類組件的支撐也非常全面,所以Spring Cloud就成為了首選。

經過一系列的重構+擴展,整個系統架構最終形成了以app為中心的一套微服務軟件系統,結構如下:

基于SpringCloud的微服務架構演變史?

到這里,整個軟件系統就基于SpringCloud初步完成了微服務體系的拆分。支付、訂單、用戶、廣告等核心功能抽離成獨立的微服務,與此同時各自微服務對應的數據庫也按照服務邊界進行了拆分。

在完成服務的拆分以后,原來功能邏輯之間的代碼調用關系,轉換成了服務間網絡的調用關系,而各個微服務需要根據各自所承載的功能提供相應的服務,此時服務如何被其他服務發現并調用,就成了整個微服務體系中比較關鍵的部分,使用過Dubbo框架的同學知道,在Dubbo中服務的注冊&發現是依賴于Zookeeper實現的,而在SpringCloud中我們是通過Consul來實現。另外在基于SpringCloud的架構體系中,提供了配置中心(ConfigServer)來幫助各個微服務管理配置文件,而原本的api服務,隨著各個功能的抽離,逐步演變成前置網關服務了。

聊到這里,基于SpringCloud我們進行了微服務拆分,而在這個體系結構中,分別提到了Consul、ConfigServer、網關服務這幾個關鍵組件,那么這幾個關鍵組件具體是如何支撐這個龐大的服務體系的呢?

SpringCloud關鍵組件

Consul

Consul是一個開源的,使用go語言開發的注冊中心服務。它里面內置了服務發現與注冊框架、分布一致性協議實現、健康檢查、Key/Value存儲、多數據中心等多個方案。在SpringCloud框架中還可以選擇Eurke作為注冊中心,這里之所以選擇Consul主要原因在于Consul對異構的服務的支持,如:grpc服務。

事實上,在后續的系統架構演進中,在某些服務模塊進一步向子系統化拆分的過程中,就采用了grpc作為子系統服務間的調用方式。例如,支付模塊的繼續擴張,對支付服務本身又進行了微服務架構的拆分,此時支付微服務內部就采用了grpc的方式進行調用,而服務注冊與發現本身則還是依賴于同一套Consul集群。

此時的系統架構演進如下:

基于SpringCloud的微服務架構演變史?

原有微服務架構中的模塊服務在規模達到一定程度或復雜性達到一定程度后,都會朝著獨立的體系發展,從而將整個微服務的調用鏈路變的非常長,而從Consul的角度看,所有的服務又都是扁平的。

隨著微服務規模的越來越大,Consul作為整個體系的核心服務組件,在整個體系中處于關鍵的位置,一旦Consul掛掉,所有的服務都將停止服務。那么Consul到底是什么樣服務?其容災機制又該如何設計呢?

要保證Consul服務的高可用,在生產環境Consul應該是一個集群(關于Consul集群的安裝與配置可以參考網絡資料),這是毫無疑問的。而在Consul集群中,存在兩種角色:Server、Client,這兩種角色與Consul集群上運行的應用服務并沒有什么關系,只是基于Consul層面的一種角色劃分。實際上,維持整個Consul集群狀態信息的還是Server節點,與Dubbo中使用Zookeeper實現注冊中心一樣,Consul集群中的各個Server節點也需要通過選舉的方式(使用GOSSIP協議、Raft一致性算法,這里不做詳細展開,在后面的文章中可以和大家單獨討論)來選舉整個集群中的Leader節點來負責處理所有查詢和事務,并向其他節點同步狀態信息。

Client角色則是相對無狀態的,只是簡單的代理轉發RPC請求到Server節點,之所以存在Client節點主要是分擔Server節點的壓力,作一層緩沖而已,這主要是因為Server節點的數量不宜過多,因為Server節點越多也就意味著達成共識的過程越慢,節點間同步的代價也就越高。對于Server節點,一般建議3-5臺,而Client節點則沒有數量的限制,可以根據實際情況部署數千或數萬臺。事實上,這也只是一種策略,在現實的生產環境中,大部分應用只需要設置3~5臺Server節點就夠了,作者所在的公司一套生產集群中的Consul集群的節點配置就是5個Server節點,并沒有額外再設置Client節點。

另外,在Consul集群中還有一個概念是Agent,事實上每個Server或Client都是一個consul agent,它是運行在Consul集群中每個成員上的一個守護進程,主要的作用是運行DNS或HTTP接口,并負責運行時檢查和保持服務信息同步。我們在啟動Consul集群的節點(Server或Client)時,都是通過consul agent的方式啟動的。例如:

consul agent -server -bootstrap -syslog \
    -ui \
    -data-dir=/opt/consul/data \
    -dns-port=53
    -recursor=10.211.55.3
    -config-dir=/opt/consul/conf \
    -pid-file=/opt/consul/run/consul.pid \
    -client=10.211.55.4 \
    -bind=10.211.55.4 \
    -node=consul-server01 \
    -disable-host-node-id &

以實際的生產環境為例,Consul集群的部署結構示意圖如下:

基于SpringCloud的微服務架構演變史?

實際生產案例中并沒有設置Client節點,而是通過5個Consul Server節點組成的集群,來服務整套生產集群的應用注冊&發現。這里有細節需要了解下,實際上5個Consul Server節點的IP地址是不一樣的,具體的服務在連接Consul集群進行服務注冊與查詢時應該連接Leader節點的IP,而問題是,如果Leader節點掛掉了,相應的應用服務節點,此時如何連接通過Raft選舉產生的新Leader節點呢?難道手工切換IP不成?

顯然手工切換IP的方式并不靠譜,而在生產實踐中,Consul集群的各個節點實際上是在Consul Agent上運行DNS(如啟動參數中紅色字體部分),應用服務在連接Consul集群時的IP地址為DNS的IP,DNS會將地址解析映射到Leader節點對應的IP上,如果Leader節點掛掉,選舉產生的新Leader節點會將自己的IP通知DNS服務,DNS更新映射關系,這一過程對各應用服務則是透明的。

通過以上分析,Consul是通過集群設計、Raft選舉算法,Gossip協議等機制來確保Consul服務的穩定與高可用的。如果需要更高的容災級別,也可以通過設計雙數據中心的方式,來異地搭建兩個Consul數據中心,組成一個異地災備Consul服務集群,只是這樣成本會更高,這就看具體是否真的需要了。

ConfigServer(配置中心)

配置中心是對微服務應用配置進行管理的服務,例如數據庫的配置、某些外部接口地址的配置等等。在SpringCloud中ConfigServer是獨立的服務組件,它與Consul一樣也是整個微服務體系中比較關鍵的一個組件,所有的微服務應用都需要通過調用其服務,從而獲取應用所需的配置信息。

隨著微服務應用規模的擴大,整個ConfigServer節點的訪問壓力也會逐步增加,與此同時,各個微服務的各類配置也會越來越多,如何管理好這些配置文件以及它們的更新策略(確保不因生產配置隨意改動而造成線上故障風險),以及搭建高可用的ConfigServer集群,也是確保微服務體系穩定很重要的一個方面。

在生產實踐中,因為像Consul、ConfigServer這樣的關鍵組件,需要搭建獨立的集群,并且部署在物理機而不是容器里。在上一節介紹Consul的時候,我們是獨立搭建了5個Consul Server節點。而ConfigServer因為主要是http配置文件訪問服務,不涉及節點選舉、一致性同步這樣的操作,所以還是按照傳統的方式搭建高可用配置中心。具體結構示意圖如下:

基于SpringCloud的微服務架構演變史?

我們可以單獨通過git來管理應用配置文件,正常來說由ConfigSeever直接通過網絡拉取git倉庫的配置供服務獲取就可以了,這樣只要git倉庫配置更新,配置中心就能立刻感知到。但是這樣做的不穩定之處,就在于git本身是內網開發用的代碼管理工具,如果讓線上實時服務直接讀取,很容易將git倉庫拉掛了,所以,我們在實際的運維過程中,是通過git進行配置文件的版本控制,區分線上分支/master與功能開發分支/feature,并且在完成mr后還需要手工(通過發布平臺觸發)同步一遍配置,過程是將新的master分支的配置同步一份到各個configserver節點所在主機的本地路徑,這樣configserver服務節點就可以通過其本地目錄獲取配置文件,而不用多次調用網絡獲取配置文件了。

而另一方面,隨著微服務越來越多,git倉庫中的配置文件數量也會越來越多。為了便于配置的管理,我們需要按照一定的組織方式來組織不同應用類型的配置。在早期所有的應用因為沒有分類,所以導致上百個微服務的配置文件放在一個倉庫目錄,這樣一來導致配置文件管理成本增加,另外一方面也會影響ConfigServer的性能,因為某個微服務用不到的配置也會被ConfigServer加載。

所以后期的實踐是,按照配置的層次關系進行組織,將公司全局的項目配置抽象到頂層,由ConfigServer默認加載,而其他所有的微服務則按照應用類型進行分組(通過git項目空間的方式分組),相同的應用放在一個組,然后這個組下單獨設立一個名為config的git倉庫來存放這個組下相關微服務的配置文件。層次結構如下:

基于SpringCloud的微服務架構演變史?

這樣應用加載配置的優先級就是“本地配置->common配置->組公共配置->項目配置”這樣的順序。例如某服務A,在項目工程的默認配置文件(“bootstrap.yml/application.yml”)中配置了參數A,同時也在本地項目配置“application-production.yml”配置了參數B,而與此同時,ConfigServer中的common倉庫下的配置文件“application.yml/application-production.yml”又分別存在參數C、參數D,同時有個組叫“pay”,其下的默認配置文件“application.yml/application-production.yml”存在參數E、參數F,具體項目pay-api又存在配置文件“pay-api-production.yml”其覆蓋了common倉庫中參數C、參數D的值。那么此時如果該應用以“spring.profiles.active=production”的方式啟動,那么其能獲取到的配置參數(通過鏈接訪問:http://{spring.cloud.config.uri}/pay-api-production.yml)就是A、B、C、D、E、F,其中C、D的參數值為pay-api-production.yml中最后覆蓋的值。

而對于ConfigServer服務本身來說,需要按照這樣的組織方式進行配置類型匹配,例如上述的例子中,假設還存在finance的配置倉庫,而pay組下的服務訪問配置中心的時候,是不需要finance空間下的配置文件的,所以ConfigServer可以不用加載。這里就需要在ConfigServer服務配置中進行一些配置。具體如下:

spring:
  application:
    name: @project.artifactId@
    version: @project.version@
    build: @buildNumber@
    branch: @scmBranch@
  cloud:
    inetutils:
      ignoredInterfaces:
        - docker0
    config:
      server:
        health.enabled: false
        git:
          uri: /opt/repos/config
          searchPaths: 'common,{application}'
          cloneOnStart: true
          repos:
            pay:
                pattern: pay-*
                cloneOnStart: true
                uri: /opt/repos/example/config
                searchPaths: 'common,{application}'
            finance:
                pattern: finance-*
                cloneOnStart: true
                uri: /opt/repos/finance/config
                searchPaths: 'common,{application}'

通過在ConfigServer服務本身的application.yml本地配置中,設置其配置搜索方式,來實現這樣的目的。

網關服務&服務熔斷&監控

通過上面兩小節的內容,我們相對詳細地介紹了基于SpringCloud體系中比較關鍵的兩個服務組件。然而在微服務架構體系中,還有很多關鍵的問題需要解決,例如,應用服務在Consul中部署了多個節點,那么調用方如何實現負載均衡?

關于這個問題,在傳統的架構方案中是通過Nginx實現的,但是在前面介紹Consul的時候只提到了Consul的服務注冊&發現、選舉等機制,并沒有提到Consul如何在實現服務調用的負載均衡。難道基于SpringCloud的微服務體系中的應用服務都是單節點在提供服務,哪怕即使部署了多個服務節點?事實上,我們在服務消費方通過@EnableFeignClients注解開啟調用,通過@FeignClient("user")注解進行服務調用時,就已經實現了負載均衡,為什么呢?因為,這個注解默認是會默認開啟Robbin代理的,而Robbin是實現客戶端負載均衡的一個組件,通過從Consul拉取服務節點信息,從而以輪詢的方式轉發客戶端調用請求至不同的服務端節點來實現負載均衡。而這一切都是在消費端的進程內部通過代碼的方式實現的。這種負載方式寄宿于消費端應用服務上,對消費端存在一定的代碼侵入性,這是為什么后面會出現Service Mesh(服務網格)概念的原因之一,這里就不展開了,后面有機會再和大家交流。

另一需要解決的關鍵問題是服務熔斷、限流等機制的實現,SpringCloud通過集成Netflix的Hystrix框架來提供這種機制的支持,與負載均衡機制一樣也是在消費端實現。由于篇幅的關系,這里也不展開了,在后面的文章中有機會再和大家交流。

此外還有Zuul組件來實現API網關服務,提供路由分發與過濾相關的功能。而其他輔助組件還有諸如Sleuth來實現分布式鏈路追蹤、Bus實現消息總線、Dashboard實現監控儀表盤等。由于SpringCloud的開源社區比較活躍,還有很多新的組件在不斷的被集成進來,感興趣的朋友可以持續關注下!

微服務之運維形態

在微服務體系結構下,隨著服務數量大量的增長,線上的部署&維護的工作量會變得非常大,而如果還采用原有的運維模式的話,就能難滿足需要了。此時運維團隊需要實施Devops策略,開發自動化運維發布平臺,打通產品、開發、測試、運維流程,關注研發效能。

另外一方面也需要推進容器化(Docker/Docker Swarm/k8s)策略,這樣才能快速對服務節點進行伸縮,這也是微服務體系下的必然要求。

微服務泛濫問題

這里還需要注意一個問題,就是實施微服務架構后,如何在工程上管控微服務的問題。盲目的進行微服務的拆分也不是一件很合理的事情,因為這會導致整個服務調用鏈路變得深不可測,對問題排查造成難度,也浪費線上資源。

重構問題

在早期單體架構方式向微服務架構的轉變過程中,重構是一個非常好的方式,也是確保服務規范化,業務系統應用架構合理化的很重要的手段。但是,一般來說,在快速發展階段也就意味著團隊規模的迅速增長,短時間內如何讓新的團隊有事可做也是一件非??简灩芾硭降氖虑?,因為如果招了很多人,并且他們之間呈現一種過渡的競爭狀態的話,就會出現讓重構這件事變得有些功利的情況,從而導致重構不徹底、避重就輕,導致表象上看是很高大上的微服務架構,而業務系統實際上比較爛的情況。

另外,重構是在一定階段后作出的重要決策,不僅僅是重新拆分,也是對業務系統的重新塑造,所以一定要考慮好應用軟件的系統結構以及實施它們所需要付出的成本,切不可盲目!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女