我眼中的微服務架構

引言

隨着業務的發展,無數公司開始面向服務開發,轉向微服務架構。java

說句大實話,今年秋招,算法和Java崗人才爆炸,不容易。nginx

落魄的Java開發.jpg

忙着找工做,很久沒寫過博客了。華軟新版本基本完成,趁着有時間正好給你們講一講傳說中的微服務架構。算法

微服務

這裏的微服務,並非單指咱們用的spring-cloudspring-cloud只是微服務的一種最佳實踐。對於創業來講,在沒有穩定的資金支撐自研中間件的狀況下,spring-cloud是咱們最好的選擇。spring

在提出微服務架構以前,咱們先分析一下咱們以往的系統有哪些問題。segmentfault

單體架構

單體架構,就像咱們以前寫得系統同樣,一個spring-boot項目實現了全部的業務邏輯,部署的時候mvn packagejava -jar就算跑起來了一個後臺項目。後端

缺點很明顯,咱們也遇到過。這裏我列出個人幾個觀點:緩存

可用

若是這個實例宕機了,由於單體應用的強依賴性,整個系統都變爲不可用的狀態。服務器

image.png

由於系統對API的強依賴,一旦API實例宕機了,整個系統就完了。網絡

對於計量和學校的業務,要求尚未這麼高,可是若是對於銀行的項目,就沒這麼容易接受了。架構

併發

除了加服務器,咱們沒有辦法有針對性地解決高併發。

假設,Alice的學生管理項目遇到了高併發致使的性能問題,咱們只能這麼幹。

image.png

部署多個API節點,經過配置nginx分發策略進行負載均衡。

可是,可能有100接口,每每只有5-10個接口是學生/老師們經常使用的,像綜合查詢之類的不存在併發問題。這樣部署屬實浪費資源。

咱們沒法針對項目中某些經常使用的接口在硬件部署級別上實施優化。

語言

這個是我在參考甲方提供的華軟另外一版本的Web項目得出的思考。

項目架構以下所示:

image.png

一個先後端不分離的JavaEE項目,去調用另外一個專門提供華軟接口的.NET項目。

這是否是看起來很酷,一個項目的後臺,採用兩種語言,兩個服務之間經過HTTP調用進行通訊。

若是服務之間是經過@Autowired在容器中進行依賴,那全部功能都須要使用Java實現,沒法發揮各類語言的優點。

微服務架構

服務高可用

假設咱們要保證驗證碼微服務的高可用,咱們可使用服務註冊與發現:

image.png

服務註冊中心,存儲服務到實例地址的映射。

當系統啓動時,右側的三個驗證碼微服務會向服務註冊中心進行註冊,表示本身要提供服務。這個過程稱爲服務註冊。

服務註冊中心就存儲着相似這樣的數據:

VerificationCode:
  - code1.instrument.yunzhiclub.com
  - code2.instrument.yunzhiclub.com
  - code3.instrument.yunzhiclub.com

表示驗證碼有三個微服務提供,地址分別是code1.instrument.yunzhiclub.comcode2.instrument.yunzhiclub.comcode3.instrument.yunzhiclub.com

若是前臺要使用驗證碼服務,Gateway會向服務註冊中心詢問,有哪一個微服務提供驗證碼的功能,獲取到列表,再進行轉發。

這個向服務註冊中心獲取其餘服務實例的過程,稱爲服務發現。

同理,其餘微服務想調用該服務,執行的也是與網關相同的服務發現。

爲何能保證高可用?

你們思考一下,爲何這樣設計就能保證高可用呢?

image.png

微服務和服務註冊中心之間是經過心跳來續約的,若是超過閥值,服務沒有向註冊中心發送數據,中心就認爲這個實例已經死亡,將其從可用列表中剔除。

假設某天,驗證碼微服務1宕機了,再也不發送本身的心跳信息,服務註冊中心中的維護的數據就變成了(實例1被剔除):

VerificationCode:
  - code2.instrument.yunzhiclub.com
  - code3.instrument.yunzhiclub.com

這樣能保證若是有實例宕機,可讓系統以最快的速度恢復。

哪怕用戶目前正在請求code1實例,本次失敗了,在一段時間的心跳事後,數據更新,用戶重試,也能保證服務可用。

既然這麼依賴服務註冊中心,那服務註冊中心宕機了怎麼辦?

image.png

在系統部署時,服務註冊中心每每是三臺實例以上的集羣。因此大可沒必要考慮這個問題。

服務註冊中心之間會進行數據同步,我以爲這個和路由器之間交換路由表很相似。

上面的諸多技術都是理論,落實到的是spring-cloud中的一個個組件。

網關:spring-cloud-netflix-zuulspring-cloud-gateway。這裏推薦使用spring-cloud-gateway

zuul採用阻塞API實現,spring官方認爲其存在性能問題,遂放棄維護zuul,啓用新項目spring-cloud-gateway,採用非阻塞API實現。

https://stackoverflow.com/questions/47092048/how-is-spring-cloud-gateway-different-from-zuul

服務註冊中心:spring-cloud-netflix-eureka

又是netflix家的,我看慕課網的實戰課用的基本上都是eureka

image.png

可是我看新聞好像是因爲netflix公司的閉源,eureka項目中止維護,替代方案:spring-cloud-consul

知識都學會了,換個組件還不是垂手可得?

服務雪崩

微服務帶來便利的同時,也爲咱們帶來了服務雪崩問題。

服務雪崩.png

本圖片摘抄自博客,感謝原做者的分享:http://www.javashuo.com/article/p-augpkylg-kt.html

就像這個圖同樣,由於服務之間相互依賴,若是A服務宕機了,那依賴它的B服務也不可用,同理,依賴BCD服務都不可用。

一個服務的崩潰,致使了整個系統的癱瘓,這就是服務雪崩。

咱們發現雪崩的緣由是雖然B可用,可是由於A的癱瘓,致使了B不可用。因此問題出在服務調用上,咱們須要在服務調用時進行錯誤處理。

咱們可使用這種策略:當檢測到A崩潰時,B就不去請求A(反正請求也是失敗),使用本地的降級策略。這個過程稱爲熔斷降級。

降級能夠理解爲一種兜底策略,差強人意的意思。

好比查詢用戶數據,用戶服務又去調用朋友圈服務的接口。假設朋友圈的接口宕機了,沒法獲取最新的數據,咱們可使用緩存策略返回上一次緩存的數據。

保證了後臺出錯,可是給用戶的體驗也不會不好。

熔斷器組件:spring-cloud-hystrix

微服務認證

這個是從我剛開始學微服務就一直帶着的一個問題。這麼多服務,不可能每個都搭一個spring-security吧?

直到上次計量項目中學習了潘老師對用戶認證的實現,才解決這個問題。

image.png

全部用戶認證放在網關,網關對前臺的COOKIE / X-AUTH-TOKEN進行用戶信息的認證,查詢出用戶後,根據用戶信息簽發一個JWT Token

微服務之間的認證,使用網關簽發的JWT Token

在《從新定義Spring Cloud實戰》一書中,也是推薦網關結合jwt的認證方式。

image.png

通訊成本

微服務架構還須要考慮的一個就是微服務之間的通訊成本。

@Autowired
private CourseService courseService;
/**
 * fallback 兜底策略
 */
@FeignClient(value = "course",
        fallback = CourseClientHystrix.class)
public interface CourseClient {

    @GetMapping(value = "{id}")
    CourseInfo getCourseInfo(@PathVariable Long id);
}

看看代碼就是成本的區別,過去就是@Autowired直接調,如今得用feign經過網絡調,網絡通訊確定比本地慢。

因此服務拆分要合理,若是一個服務要求高可用,而且能夠接受通訊成本的話,就能夠單獨拆分微服務。

服務拆分對架構師要求極高,從實現到性能,須要考慮周全。我這種小菜雞隻能寫寫博客吹吹牛了,如今我還不敢服務拆分呢(就怕拆的很差,把性能拆壞了)。

總結

吹了一篇理論,讓你們先了解了解微服務架構,到了本身學的時候也少走些彎路。

看着挺簡單的,真正搭spring-cloud的時候沒有看上去那麼簡單。照着慕課網搭過一個小的,花了好幾天時間。

書到用時方恨少,事非通過不知難。
相關文章
相關標籤/搜索