歡迎光臨
每天分享高質量文章

外行人都能看懂的SpringCloud,錯過了血虧!

來自:Java3y(微信號:java3y)

一、前言

只有光頭才能變強

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

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

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

  • https://github.com/ZhongFuCheng3y/msc-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這三個概念是差不多的,瞭解了其中的一個,然後將自己的理解往上面套就好了。沒必要細分每個的具體概念~~(當然了,我很期待有大佬可以在評論區留言說下自己的看法哈)

參考資料:

  • 分佈式與集群的區別是什麼?https://www.zhihu.com/question/20004877

  • 分佈式、集群、微服務、SOA 之間的區別https://blog.csdn.net/heatdeath/article/details/79038795

三、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理論定義的其實是在容忍網絡分割槽的條件下,“強一致性”和“極致可用性”無法同時達到

參考資料:

  • CAP理論中的P到底是個什麼意思?https://www.zhihu.com/question/54105974

  • 淺談分佈式系統的基本問題:可用性與一致性:https://m.aliyun.com/yunqi/articles/2709

  • 分佈式系統的CAP理論:http://www.hollischuang.com/archives/666

  • 為什麼CAP理論在捨棄P的情況下,可以有完美的CA?https://www.zhihu.com/question/285878189

  • 不懂點CAP理論,你好意思說你是做分佈式的嗎?http://www.yunweipai.com/archives/8432.html

擴展閱讀:

  • 淺談分佈式事務:https://m.aliyun.com/yunqi/articles/230242

四、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入駐東方寶泰”。

  • 商家們需要定時交物業費給物業。

  • 物業維持東方寶泰的穩定性。如果某個商家不想在東方寶泰運營了,告訴了物業。物業自然就會將其在東方寶泰商戶清單去除。

優秀博文:

  • Spring Cloud Eureka詳解:https://blog.csdn.net/sunhuiliang85/article/details/76222517

  • 《Spring Cloud Netflix》 — 服務註冊和服務發現-Eureka 的使用:https://zhuanlan.zhihu.com/p/26472547

  • 微服務架構:Eureka引數配置項詳解:https://www.cnblogs.com/fangfuhai/p/7070325.html

六、引出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女朋友說:”你是不是傻,肯定哪間近去哪間啊“

優秀博文:

  • 擼一擼Spring Cloud Ribbon的原理-負載均衡策略:https://www.cnblogs.com/kongxianghai/p/8477781.html

七、引出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女朋友不屑的說:“你話是真的多”

參考資料:

  • Hystrix ,為什麼說它是每個系統不可或缺的開源框架?https://zhuanlan.zhihu.com/p/34304136

  • 深入理解Hystrix之文件翻譯:https://zhuanlan.zhihu.com/p/28523060

  • 談談我對服務熔斷、服務降級的理解:https://blog.csdn.net/guwei9111986/article/details/51649240

  • Hystrix幾篇文章《青芒》:https://segmentfault.com/u/yedge/articles

八、引出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 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 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也是可以搭成集群來實現高可用的),要不要一起使用得看架構的複雜度了(業務)~~~

參考資料:

  • 微服務與API網關(上): 為什麼需要API網關?:http://blog.didispace.com/hzf-ms-apigateway-1/

  • 談談 API 網關:https://www.jianshu.com/p/b52a2773e75f

  • 談談微服務中的 API 網關(API Gateway):https://www.cnblogs.com/savorboard/p/api-gateway.html

  • API網關性能比較:NGINX vs. ZUUL vs. Spring Cloud Gateway :http://www.360doc.com/content/18/0208/05/46368139_728502763.shtml

  • 談API網關的背景、架構以及落地方案:http://www.infoq.com/cn/news/2016/07/API-background-architecture-floo

  • zuul和nginx:https://zhuanlan.zhihu.com/p/37385481

十、引出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區別

  • https://www.cnblogs.com/BlogNetSpace/p/8469033.html

總結

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

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

SpringCloud系列文章參考資料:

  • 史上最簡單的 SpringCloud 教程 | 終章https://blog.csdn.net/forezp/article/details/70148833

  • Spring Cloud基礎教程《程式員DD》http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/

  • Spring Cloud 系列文章《純潔的微笑》:http://www.ityouknow.com/spring-cloud.html

  • SpringCloud系列文章:https://www.cnblogs.com/woshimrf/tag/SpringCloud/

  • SpringCloud系列文章《狂小白》:https://www.cnblogs.com/huangjuncong/tag/SpringCloud/

  • SpringCloud官方文件:http://projects.spring.io/spring-cloud/

  • Spring Cloud 中文文件:https://springcloud.cc/spring-cloud-dalston.html#_appendix_compendium_of_configuration_properties

參考書籍:

  • 《SpringCloud 微服務實戰》

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

  • https://github.com/ZhongFuCheng3y/msc-Demo

歡迎關註作者微信公眾號:Java3y


編號812,輸入編號直達本文

●輸入m獲取文章目錄

推薦↓↓↓

Web開發

更多推薦18個技術類微信公眾號

涵蓋:程式人生、演算法與資料結構、黑客技術與網絡安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

赞(0)

分享創造快樂