SpringCloud簡單理解(轉)

(轉載地址:https://www.cnblogs.com/Java3y/p/9540386.html

一、前言

只有光頭才能變強

認識我的朋友可能都知道我這陣子去實習啦,去的公司說是用SpringCloud(但我覺得使用的力度並不大啊~~)...

所以,這篇主要來講講SpringCloud的一些基礎的知識。(我就是現學現賣了,主要當做我學習SpringCloud的筆記吧!)當然了,我的水平是有限的,可能會有一些理解錯的的概念/知識點,還請大家不吝在評論區指正啊~~

SpringCloud GitHub Demo(看完文章的同學可以自己練手玩玩):

項目結構圖:

二、集羣/分佈式/微服務/SOA是什麼?

像我這種技術小白,看到這些詞(集羣/分佈式/微服務/SOA)的時候,感覺就是遙不可及的(高大尚的技術!!)。就好像剛學Java面向對象的時候,在論壇上翻閱資料的時候,無意看到"面向切面編程",也認爲這是遙不可及的(高大尚的技術!!)。

但真正接觸到"面向切面編程"的時候,發現原來就是如此啊,也沒什麼大不了的。只不過當時被它的名字給唬住了...

不知道各位在剛接觸這些名字集羣/分佈式/微服務/SOA的時候,有沒有被唬住了呢??

  • 下面我就簡單說說這些名詞的意思

2.1什麼是集羣

以下內容來源維基百科:

計算機集羣簡稱集羣是一種計算機系統,它通過一組鬆散集成的計算機軟件和/或硬件連接起來高度緊密地協作完成計算工作。在某種意義上,他們可以被看作是一臺計算機。集羣系統中的單個計算機通常稱爲節點,通常通過局域網連接,但也有其它的可能連接方式。集羣計算機通常用來改進單個計算機的計算速度和/或可靠性。一般情況下集羣計算機比單個計算機,比如工作站或超級計算機性能價格比要高得多

集羣技術特點:

  • 通過多臺計算機完成同一個工作,達到更高的效率。
  • 兩機或多機內容、工作過程等完全一樣。如果一臺死機,另一臺可以起作用。

在維基百科上說得也挺明白的了,我來舉個例子吧。

  • 小周在公司寫Java程序,但公司業務在發展,一個Java開發者可能忙不過來,小周有的時候也得請個假呀。於是請了3y過去一起做Java開發。平時小周和3y就寫Java程序,但3y可能有事要回學校一趟。沒事,公司還有小周做Java開發呢,公司開發還能繼續運作。
    • 3y跟小周都是做Java開發
    • 3y來了,小周的工作可以分擔一些。
    • 3y請假了,還有小周在呢。

我寫了一個910便利網發佈到服務器去了,現在越來越多的人訪問了,訪問有點慢,怎麼辦???很簡單,(只有充錢才能變強),加配置吧(加cpu,加內存)。升級完配置之後,訪問人數越來越多,於是發現又不禁用啦,在這臺機器上加配置已經解決不了了,怎麼辦???很簡單,(只有充錢才能變強),我再買一臺服務器,將910便利網也發佈到新買的這臺服務器上去

特點:

  • 這兩臺服務器都是運行同一個系統--->910便利網

好處:

  • 本來只有一臺機器處理訪問,現在有兩臺機器處理訪問了,分擔了壓力
  • 如果其中一臺忘記繳費了,暫時用不了了。沒關係,還有另一臺可以用呢。

集羣:同一個業務,部署在多個服務器上(不同的服務器運行同樣的代碼,幹同一件事)

2.2什麼是分佈式

以下內容來源維基百科:

分佈式系統是一組計算機,通過網絡相互連接傳遞消息與通信後並協調它們的行爲而形成的系統。組件之間彼此進行交互以實現一個共同的目標

我也來舉個例子來說明一下吧:

  • 現在公司有小周和3y一起做Java開發,做Java開發一般jQuery,AJAX都能寫一點,所以這些活都由我們來幹。可是呢,3y對前端不是很熟,有的時候調試半天都調不出來。老闆認爲3y是真的菜!於是讓小周專門來處理前端的事情。這樣3y就高興了,可以專心寫自己的Java,前端就專門交由小周負責了。於是,小周和3y就變成了協作開發
    • 3y對前端不熟(能寫出來),但在調試的時候可能會花費很多時間
    • 小周來專門做前端的事,3y可以專心寫自己的Java程序了。
    • 都是爲了項目正常運行以及迭代。

我的910便利網已經部署到兩臺服務器去了,但是越來越多的人去訪問。現在也逐漸承受不住啦。那現在怎麼辦啊??那繼續充錢變強??作爲一個理智的我,肯定得想想是哪裏有問題。現在910便利網的模塊有好幾個,全都丟在同一個Tomcat裏邊。

其實有些模塊的訪問是很低的(比如後臺管理),那我可不可以這樣做:將每個模塊抽取獨立出來,訪問量大的模塊用好的服務器裝着,沒啥人訪問的模塊用差的服務器裝着。這樣的好處是:一、資源合理利用了(沒人訪問的模塊用性能差的服務器,訪問量大的模塊單獨提升性能就好了)。二、耦合度降低了:每個模塊獨立出來,各幹各的事(專業的人做專業的事),便於擴展

特點:

  • 將910便利網的功能拆分,模塊之間獨立,在使用的時候再將這些獨立的模塊組合起來就是一個系統了。

好處:

  • 模塊之間獨立,各做各的事,便於擴展,複用性高
  • 高吞吐量。某個任務需要一個機器運行10個小時,將該任務用10臺機器的分佈式跑(將這個任務拆分成10個小任務),可能2個小時就跑完了

分佈式:一個業務分拆多個子業務,部署在不同的服務器上(不同的服務器,運行不同的代碼,爲了同一個目的)

2.3集羣/分佈式

集羣和分佈式並不衝突,可以有分佈式集羣

現在3y的公司規模變大了,有5個小夥子寫Java,4個小夥子寫前端,2個小夥子做測試,1個小夥子做DBA。

  • Java,前端,測試,DBA的關係看作是分佈式的
  • 5個Java看作是集羣的(前端,測試同理)...

2.4分佈式/微服務/SOA

其實我認爲分佈式/微服務/SOA這三個概念是差不多的,瞭解了其中的一個,然後將自己的理解往上面套就好了。沒必要細分每個的具體概念~~(當然了,我很期待有大佬可以在評論區留言說下自己的看法哈)

參考資料:

三、CAP理論

從上面所講的分佈式概念我們已經知道,分佈式簡單理解就是:一個業務分拆多個子業務,部署在不同的服務器上

  • 一般來說,一個子業務我們稱爲節點

如果你接觸過一些分佈式的基礎概念,那肯定會聽過CAP這個理論。就比如說:你學了MySQL的InnoDB存儲引擎相關知識,你肯定聽過ACID!

首先,我們來看一下CAP分別代表的是什麼意思:

  • C:數據一致性(consistency)
    • 所有節點擁有數據的最新版本
  • A:可用性(availability)
    • 數據具備高可用性
  • P:分區容錯性(partition-tolerance)
    • 容忍網絡出現分區,分區之間網絡不可達。

下面有三個節點(它們是集羣的),此時三個節點都能夠相互通信:

由於我們的系統是分佈式的,節點之間的通信是通過網絡來進行的。只要是分佈式系統,那很有可能會出現一種情況:因爲一些故障,使得有些節點之間不連通了,整個網絡就分成了幾塊區域

  • 數據就散佈在了這些不連通的區域中,這就叫分區

現在出現了網絡分區後,此時有一個請求過來了,想要註冊一個賬戶。

此時我們節點一和節點三是不可通信的,這就有了抉擇:

  • 如果允許當前用戶註冊一個賬戶,此時註冊的記錄數據只會在節點一和節點二或者節點二和節點三同步,因爲節點一和節點三的記錄不能同步的。
    • 這種情況其實就是選擇了可用性(availability),拋棄了數據一致性(consistency)
  • 如果不允許當前用戶註冊一個賬戶(就是要等到節點一和節點三恢復通信)。節點一和節點三一旦恢復通信,我們就可以保證節點擁有的數據是最新版本
    • 這種情況其實就是拋棄了可用性(availability),選擇了數據一致性(consistency)

3.1再次梳理一下CAP理論

一般我們說的分佈式系統,P:分區容錯性(partition-tolerance)這個是必需的,這是客觀存在的。

CAP是無法完全兼顧的,從上面的例子也可以看出,我們可以選AP,也可以選CP。但是,要注意的是:不是說選了AP,C就完全拋棄了。不是說選了CP,A就完全拋棄了!

在CAP理論中,C所表示的一致性是強一致性(每個節點的數據都是最新版本),其實一致性還有其他級別的:

  • 弱一致性:弱一致性是相對於強一致性而言,它不保證總能得到最新的值;
  • 最終一致性(eventual consistency):放寬對時間的要求,在被調完成操作響應後的某個時間點,被調多個節點的數據最終達成一致

可用性的值域可以定義成0到100%的連續區間

所以,CAP理論定義的其實是在容忍網絡分區的條件下,“強一致性”和“極致可用性”無法同時達到

參考資料:

擴展閱讀:

四、SpringCloud就是這麼簡單

相信大家讀到這裏,對分佈式/微服務已經有一定的瞭解了,其實單從概念來說,是非常容易理解的。只是很可能被它的名字給唬住了。

下面我就來講講SpringCloud最基礎的知識~

4.1爲什麼需要SpringCloud?

前面也講了,從分佈式/微服務的角度而言:就是把我們一的項目,分解成多個的模塊。這些小的模塊組合起來,完成功能。

舉個可能不太恰當的例子(現實可能不會這麼拆分,但意思到位就好了):

拆分出多個模塊以後,就會出現各種各樣的問題,而SpringCloud提供了一整套的解決方案!

  • 注:這些模塊是獨立成一個子系統的(不同主機)。

SpringCloud的基礎功能

  • 服務治理: Spring Cloud Eureka
  • 客戶端負載均衡: Spring Cloud Ribbon
  • 服務容錯保護: Spring Cloud Hystrix
  • 聲明式服務調用: Spring Cloud Feign
  • API網關服務:Spring Cloud Zuul
  • 分佈式配置中心: Spring Cloud Config

SpringCloud的高級功能(本文不講):

  • 消息總線: Spring Cloud Bus
  • 消息驅動的微服務: Spring Cloud Stream
  • 分佈式服務跟蹤: Spring Cloud Sleuth

五、引出Eureka

那會出現什麼問題呢??首當其衝的就是子系統之間的通訊問題。子系統與子系統之間不是在同一個環境下,那就需要遠程調用。遠程調用可能就會想到httpClient,WebService等等這些技術來實現。

既然是遠程調用,就必須知道ip地址,我們可能有以下的場景。

  • 功能實現一:A服務需要調用B服務
    • 在A服務的代碼裏面調用B服務,顯式通過IP地址調用http://123.123.123.123:8888/java3y/3
  • 功能實現二:A服務調用B服務,B服務調用C服務,C服務調用D服務
    • 在A服務的代碼裏面調用B服務,顯式通過IP地址調用:http://123.123.123.123:8888/java3y/3,(同樣地)B->C,C->D
  • 功能實現三:D服務調用B服務,B服務調用C服務
    • 在D服務的代碼裏面調用B服務,顯式通過IP地址調用:http://123.123.123.123:8888/java3y/3,(同樣地)B->C
  • .....等等等等

萬一,我們B服務的IP地址變了,想想會出現什麼問題:A服務,D服務(等等)需要手動更新B服務的地址

  • 在服務多的情況下,手動來維護這些靜態配置就是噩夢!

爲了解決微服務架構中的服務實例維護問題(ip地址), 產生了大量的服務治理框架和產品。 這些框架和產品的實現都圍繞着服務註冊與服務發現機制來完成對微服務應用實例的自動化管理

在SpringCloud中我們的服務治理框架一般使用的就是Eureka。

我們的問題:

  • 現在有A、B、C、D四個服務,它們之間會互相調用(而且IP地址很可能會發生變化),一旦某個服務的IP地址變了,那服務中的代碼要跟着變,手動維護這些靜態配置(IP)非常麻煩!

Eureka是這樣解決上面所說的情況的:

  • 創建一個E服務,將A、B、C、D四個服務的信息都註冊到E服務上,E服務維護這些已經註冊進來的信息

A、B、C、D四個服務都可以拿到Eureka(服務E)那份註冊清單。A、B、C、D四個服務互相調用不再通過具體的IP地址,而是通過服務名來調用

  • 拿到註冊清單--->註冊清單上有服務名--->自然就能夠拿到服務具體的位置了(IP)。
  • 其實簡單來說就是:代碼中通過服務名找到對應的IP地址(IP地址會變,但服務名一般不會變)

5.1Eureka細節

Eureka專門用於給其他服務註冊的稱爲Eureka Server(服務註冊中心),其餘註冊到Eureka Server的服務稱爲Eureka Client。

在Eureka Server一般我們會這樣配置:


    register-with-eureka: false     #false表示不向註冊中心註冊自己。
    fetch-registry: false     #false表示自己端就是註冊中心,我的職責就是維護服務實例,並不需要去檢索服務

Eureka Client分爲服務提供者和服務消費者

  • 但很可能,某服務既是服務提供者又是服務消費者

如果在網上看到SpringCloud的某個服務配置沒有"註冊"到Eureka-Server也不用過於驚訝(但是它是可以獲取Eureka服務清單的)

  • 很可能只是作者把該服務認作爲單純的服務消費者,單純的服務消費者無需對外提供服務,也就無須註冊到Eureka中了

eureka:
  client:
    register-with-eureka: false  # 當前微服務不註冊到eureka中(消費端)
    service-url: 
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/  

下面是Eureka的治理機制:

  • 服務提供者
    • 服務註冊:啓動的時候會通過發送REST請求的方式將自己註冊到Eureka Server上,同時帶上了自身服務的一些元數據信息。
    • 服務續約:在註冊完服務之後,服務提供者會維護一個心跳用來持續告訴Eureka Server: "我還活着 ” 、
    • 服務下線:當服務實例進行正常的關閉操作時,它會觸發一個服務下線的REST請求給Eureka Server, 告訴服務註冊中心:“我要下線了 ”。
  • 服務消費者
    • 獲取服務:當我們啓動服務消費者的時候,它會發送一個REST請求給服務註冊中心,來獲取上面註冊的服務清單
    • 服務調用:服務消費者在獲取服務清單後,通過服務名可以獲得具體提供服務的實例名和該實例的元數據信息。在進行服務調用的時候,優先訪問同處一個Zone中的服務提供方
  • Eureka Server(服務註冊中心):
    • 失效剔除:默認每隔一段時間(默認爲60秒) 將當前清單中超時(默認爲90秒)沒有續約的服務剔除出去
    • 自我保護:。EurekaServer 在運行期間,會統計心跳失敗的比例在15分鐘之內是否低於85%(通常由於網絡不穩定導致)。 Eureka Server會將當前的實例註冊信息保護起來, 讓這些實例不會過期,儘可能保護這些註冊信息

最後,我們就有了這張圖:

舉個例子:

  • 3y跟女朋友去東站的東方寶泰逛街,但不知道東方寶泰有什麼好玩的。於是就去物業搜了一下東方寶泰商戶清單,發現一樓有優衣庫,二樓有星巴克,三樓有麥當勞。
  • 在優衣庫旁邊,有新開張的KFC,在牆壁打上了很大的標識“歡迎KFC入駐東方寶泰”。
  • 商家們需要定時交物業費給物業。
  • 物業維持東方寶泰的穩定性。如果某個商家不想在東方寶泰運營了,告訴了物業。物業自然就會將其在東方寶泰商戶清單去除。

優秀博文:

六、引出RestTemplate和Ribbon

通過Eureka服務治理框架,我們可以通過服務名來獲取具體的服務實例的位置了(IP)。一般在使用SpringCloud的時候不需要自己手動創建HttpClient來進行遠程調用。

可以使用Spring封裝好的RestTemplate工具類,使用起來很簡單:


    // 傳統的方式,直接顯示寫死IP是不好的!
    //private static final String REST_URL_PREFIX = "http://localhost:8001";
    
    // 服務實例名
    private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";

    /**
     * 使用 使用restTemplate訪問restful接口非常的簡單粗暴無腦。 (url, requestMap,
     * ResponseBean.class)這三個參數分別代表 REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型。
     */
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/consumer/dept/add")
    public boolean add(Dept dept) {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

爲了實現服務的高可用,我們可以將服務提供者集羣。比如說,現在一個秒殺系統設計出來了,準備上線了。在11月11號時爲了能夠支持高併發,我們開多臺機器來支持併發量。

現在想要這三個秒殺系統合理攤分用戶的請求(專業來說就是負載均衡),可能你會想到nginx。

其實SpringCloud也支持的負載均衡功能,只不過它是客戶端的負載均衡,這個功能實現就是Ribbon!

負載均衡又區分了兩種類型:

  • 客戶端負載均衡(Ribbon)
    • 服務實例的清單在客戶端,客戶端進行負載均衡算法分配。
    • (從上面的知識我們已經知道了:客戶端可以從Eureka Server中得到一份服務清單,在發送請求時通過負載均衡算法,在多個服務器之間選擇一個進行訪問)
  • 服務端負載均衡(Nginx)
    • 服務實例的清單在服務端,服務器進行負載均衡算法分配

所以,我們的圖可以畫成這樣:

6.1Ribbon細節

Ribbon是支持負載均衡,默認的負載均衡策略是輪詢,我們也是可以根據自己實際的需求自定義負載均衡策略的。


@Configuration
public class MySelfRule
{
    @Bean
    public IRule myRule()
    {
        //return new RandomRule();// Ribbon默認是輪詢,我自定義爲隨機
        //return new RoundRobinRule();// Ribbon默認是輪詢,我自定義爲隨機
        
        return new RandomRule_ZY();// 我自定義爲每臺機器5次
    }
}

實現起來也很簡單:繼承AbstractLoadBalancerRule類,重寫public Server choose(ILoadBalancer lb, Object key)即可。

SpringCloud 在CAP理論是選擇了AP的,在Ribbon中還可以配置重試機制的(有興趣的同學可以去搜搜)~

舉個例子:

  • 3y跟女朋友過了幾個月,又去東方寶泰了。由於記性不好,又去物業那弄了一份東方寶泰商戶清單。
  • 這次看到東方寶泰又開了一間麥當勞,一間在二樓,一間在三樓。原來生意太好了,爲了能提高用戶體驗,在二樓多開了一間麥當勞
  • 這時,3y問女朋友:“去哪間麥當勞比較好?要不我們拋硬幣決定?”3y女朋友說:”你是不是傻,肯定哪間近去哪間啊“

優秀博文:

七、引出Hystrix

到目前爲止,我們的服務看起來好像挺好的了:能夠根據服務名來遠程調用其他的服務,可以實現客戶端的負載均衡。

但是,如果我們在調用多個遠程服務時,某個服務出現延遲,會怎麼樣??

高併發的情況下,由於單個服務的延遲,可能導致所有的請求都處於延遲狀態,甚至在幾秒鐘就使服務處於負載飽和的狀態,資源耗盡,直到不可用,最終導致這個分佈式系統都不可用,這就是“雪崩”。

針對上述問題, Spring Cloud Hystrix實現了斷路器、線程隔離等一系列服務保護功能。

  • Fallback(失敗快速返回):當某個服務單元發生故障(類似用電器發生短路)之後,通過斷路器的故障監控(類似熔斷保險絲), 向調用方返回一個錯誤響應, 而不是長時間的等待。這樣就不會使得線程因調用故障服務被長時間佔用不釋放,避免了故障在分佈式系統中的蔓延
  • 資源/依賴隔離(線程池隔離):它會爲每一個依賴服務創建一個獨立的線程池,這樣就算某個依賴服務出現延遲過高的情況,也只是對該依賴服務的調用產生影響, 而不會拖慢其他的依賴服務

Hystrix提供幾個熔斷關鍵參數:滑動窗口大小(20)、 熔斷器開關間隔(5s)、錯誤率(50%)

  • 每當20個請求中,有50%失敗時,熔斷器就會打開,此時再調用此服務,將會直接返回失敗,不再調遠程服務。
  • 直到5s鍾之後,重新檢測該觸發條件,判斷是否把熔斷器關閉,或者繼續打開

Hystrix還有請求合併、請求緩存這樣強大的功能,在此我就不具體說明了,有興趣的同學可繼續深入學習~

7.1Hystrix儀表盤

Hystrix儀表盤:它主要用來實時監控Hystrix的各項指標信息。通過Hystrix Dashboard反饋的實時信息,可以幫助我們快速發現系統中存在的問題,從而及時地採取應對措施。

啓動時的頁面:

監控單服務的頁面:

我們現在的服務是這樣的:

除了可以開啓單個實例的監控頁面之外,還有一個監控端點 /turbine.stream是對集羣使用的。 從端點的命名中,可以引入Turbine, 通過它來彙集監控信息,並將聚合後的信息提供給 HystrixDashboard 來集中展示和監控

舉個例子:

  • 3y和女朋友決定去萬達玩,去到萬達的停車場發現在負一層已經大大寫上“負一層已停滿,請下負二層,負二層空餘停車位還有100個!”
  • 這時,3y就跟女朋友說:“萬達停車場是做得挺好的,如果它沒有直接告知我負一層已滿,可能我就去負一層找位置了,要是一堆人跑去負一層但都找不到車位的話,恐怕就塞死了”。3y接着說:“看停車位的狀態也做得不錯,在停車位上頭有一個感應(監控),如果是紅色就代表已被停了,如果是綠色就說明停車位是空的”。
  • 3y女朋友不屑的說:“你話是真的多”

參考資料:

八、引出Feign

上面已經介紹了Ribbon和Hystrix了,可以發現的是:他倆作爲基礎工具類框架廣泛地應用在各個微服務的實現中。我們會發現對這兩個框架的使用幾乎是同時出現的。

爲了簡化我們的開發,Spring Cloud Feign出現了!它基於 Netflix Feign 實現,整合了 Spring Cloud Ribbon 與 Spring Cloud Hystrix, 除了整合這兩者的強大功能之外,它還提
供了聲明式的服務調用(不再通過RestTemplate)。

Feign是一種聲明式、模板化的HTTP客戶端。在Spring Cloud中使用Feign, 我們可以做到使用HTTP請求遠程服務時能與調用本地方法一樣的編碼體驗,開發者完全感知不到這是遠程方法,更感知不到這是個HTTP請求。

下面就簡單看看Feign是怎麼優雅地實現遠程調用的:

服務綁定:


// value --->指定調用哪個服務
// fallbackFactory--->熔斷器的降級提示
@FeignClient(value = "MICROSERVICECLOUD-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {


    // 採用Feign我們可以使用SpringMVC的註解來對服務進行綁定!
    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") long id);

    @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
    public List<Dept> list();

    @RequestMapping(value = "/dept/add", method = RequestMethod.POST)
    public boolean add(Dept dept);
}

Feign中使用熔斷器:


/**
 * Feign中使用斷路器
 * 這裏主要是處理異常出錯的情況(降級/熔斷時服務不可用,fallback就會找到這裏來)
 */
@Component // 不要忘記添加,不要忘記添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public Dept get(long id) {
                return new Dept().setDeptno(id).setDname("該ID:" + id + "沒有沒有對應的信息,Consumer客戶端提供的降級信息,此刻服務Provider已經關閉")
                        .setDb_source("no this database in MySQL");
            }

            @Override
            public List<Dept> list() {
                return null;
            }

            @Override
            public boolean add(Dept dept) {
                return false;
            }
        };
    }
}

調用:

九、引出Zuul

基於上面的學習,我們現在的架構很可能會設計成這樣:

這樣的架構會有兩個比較麻煩的問題:

  1. 路由規則與服務實例的維護間題:外層的負載均衡(nginx)需要維護所有的服務實例清單(圖上的OpenService)
  2. 簽名校驗、 登錄校驗冗餘問題:爲了保證對外服務的安全性, 我們在服務端實現的微服務接口,往往都會有一定的權限校驗機制,但我們的服務是獨立的,我們不得不在這些應用中都實現這樣一套校驗邏輯,這就會造成校驗邏輯的冗餘。

還是畫個圖來理解一下吧:

每個服務都有自己的IP地址,Nginx想要正確請求轉發到服務上,就必須維護着每個服務實例的地址

  • 更是災難的是:這些服務實例的IP地址還有可能會變,服務之間的劃分也很可能會變。

http://123.123.123.123

http://123.123.123.124

http://123.123.123.125

http://123.123.123.126

http://123.123.123.127

購物車和訂單模塊都需要用戶登錄了纔可以正常訪問,基於現在的架構,只能在購物車和訂單模塊都編寫校驗邏輯,這無疑是冗餘的代碼。

爲了解決上面這些常見的架構問題,API網關的概念應運而生。在SpringCloud中了提供了基於Netfl ix Zuul實現的API網關組件Spring Cloud Zuul

Spring Cloud Zuul是這樣解決上述兩個問題的:

  • SpringCloud Zuul通過與SpringCloud Eureka進行整合,將自身註冊爲Eureka服務治理下的應用,同時從Eureka中獲得了所有其他微服務的實例信息。外層調用都必須通過API網關,使得將維護服務實例的工作交給了服務治理框架自動完成
  • 在API網關服務上進行統一調用來對微服務接口做前置過濾,以實現對微服務接口的攔截和校驗

Zuul天生就擁有線程隔離和斷路器的自我保護功能,以及對服務調用的客戶端負載均衡功能。也就是說:Zuul也是支持Hystrix和Ribbon

關於Zuul還有很多知識點(由於篇幅問題,這裏我就不細說了):

  • 路由匹配(動態路由)
  • 過濾器實現(動態過濾器)
  • 默認會過濾掉Cookie與敏感的HTTP頭信息(額外配置)

9.1可能對Zuul的疑問

Zuul支持Ribbon和Hystrix,也能夠實現客戶端的負載均衡。我們的Feign不也是實現客戶端的負載均衡和Hystrix的嗎?既然Zuul已經能夠實現了,那我們的Feign還有必要嗎?

或者可以這樣理解:

  • zuul是對外暴露的唯一接口相當於路由的是controller的請求,而Ribbonhe和Fegin路由了service的請求
  • zuul做最外層請求的負載均衡 ,而Ribbon和Fegin做的是系統內部各個微服務的service的調用的負載均衡

有了Zuul,還需要Nginx嗎?他倆可以一起使用嗎?

  • 我的理解:Zuul和Nginx是可以一起使用的(畢竟我們的Zuul也是可以搭成集羣來實現高可用的),要不要一起使用得看架構的複雜度了(業務)~~~

參考資料:

十、引出SpringCloud Config

隨着業務的擴展,我們的服務會越來越多,越來越多。每個服務都有自己的配置文件。

既然是配置文件,給我們配置的東西,那難免會有些改動的。

比如我們的Demo中,每個服務都寫上相同的配置文件。萬一我們有一天,配置文件中的密碼需要更換了,那就得三個都要重新更改

在分佈式系統中,某一個基礎服務信息變更,都很可能會引起一系列的更新和重啓

Spring Cloud Config項目是一個解決分佈式系統的配置管理方案。它包含了Client和Server兩個部分,server提供配置文件的存儲、以接口的形式將配置文件的內容提供出去,client通過接口獲取數據、並依據此數據初始化自己的應用

  • 簡單來說,使用Spring Cloud Config就是將配置文件放到統一的位置管理(比如GitHub),客戶端通過接口去獲取這些配置文件。
  • 在GitHub上修改了某個配置文件,應用加載的就是修改後的配置文件。

SpringCloud Config其他的知識:

  • 在SpringCloud Config的服務端, 對於配置倉庫的默認實現採用了Git,我們也可以配置SVN。
  • 配置文件內的信息加密和解密
  • 修改了配置文件,希望不用重啓來動態刷新配置,配合Spring Cloud Bus 使用~

使用SpringCloud Config可能的疑問:application.yml和 bootstrap.yml區別

總結

本文主要寫了SpringCloud的基礎知識,希望大家看完能有所幫助~

SpringCloud的資料也很多,我整理一些我認爲比較好,想要深入的同學不妨看看下邊的資源~~~

SpringCloud系列文章參考資料:

參考書籍:

  • 《SpringCloud 微服務實戰》

SpringCloud GitHub Demo(看完文章的同學可以自己練手玩玩,寫好了ReadMe了):

如果想看更多的原創技術文章,歡迎大家關注我的微信公衆號:Java3y。Java技術羣討論:742919422。公衆號還有海量的視頻資源哦,關注即可免費領取。

可能感興趣的鏈接:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章