大家好,今天分享的是我最近在公司剛實現的一套微服務架構,用作於公司基礎性服務(例如搜尋,Passport Server,分散式任務排程系統等)

以下是整體架構

架構圖

可以看出,可以分為7個模組,整體是分層架構

  1. 反向代理層
  2. 閘道器層
  3. 服務層
  4. 儲存層
  5. 服務治理中心
  6. 配置中心
  7. 訊息匯流排

下面簡單的介紹下這7個模組

1反向代理層:

         首先這個模組的的主要作用是為了對外遮蔽內部叢集,常見實現有很多比如我用的最多的Nginx就是其中之一,但是這裡我選擇Zuul。

優勢:

  1. SpringCloud對Zuul做了很全的整合,搭建各方面都很方便。
  2. Zuul在微服務架構中本身也屬於一個微服務,好處就很明顯了,我們可以通過治理中心全方位的監控服務狀態
  3. 雖然效能方面Zuul需要一定的預熱但是短時間預熱後效能和Nginx基本相當

但是有些問題,我們都知道在微服務架構中所有服務均依賴於閘道器,而且整個架構中可能會有多個系統或者專案,那麼閘道器的重要性就顯而易見了,一旦閘道器掛了,那麼整個叢集對外就處於癱瘓狀態了,這個問題我們稱為單點故障,這是很恐怖的。

因為一個域名只能對應一個IP,一個IP可以對應多個域名的特性,我們不能通過單一的多開例項來解決這個問題了,因為最終域名特性決定了最終只能有一個出口。那麼該怎麼解決這個問題呢?

這裡就要說到VRRP協議了,大致介紹一下,這是一個虛擬IP輕量級服務(虛擬路由器冗餘協議),解決這個問題就是在傳統服務主從的基礎上,在每個服務例項所在的服務上建立虛擬IP並連線到Internet上,並對服務進行心跳檢測。當服務出現問題後,它會將IP從當前服務中移到備份伺服器上。這樣就實現了代理層的高可用。由於VRRP實現本身是一個非常輕量的服務幾乎可以不用擔他會掛掉,而且用到他的時候一般是服務掛了。某種程度上可以說是一種解耦,將兩種問題全部發生的概率降到了最低。

2 閘道器層:

這層的主要作用是為了解決跨域,業務複雜度等問題,就打個比方說登入認證,因為微服務架構下,所有一個服務所負責的功能很少,很多時候使用者一個請求會同時呼叫多個服務,而這多個服務都需要在使用者登入後才能操作,那麼問題就很明顯了,登入認證冗餘了除了請求校驗,當然還有其他的一些功能比如說請求過濾的等,這些閘道器都可以來處理。這裡可能有人會問,請求過濾反向代理也可以做啊。這個問題問的好,從兩個角度出發,一個是程式設計原則中有一個叫單一職責制。意思就是說一個例項只負責一個抽象上的功能,那麼服務將閘道器一定業務相關的操作和反代結合到一起明顯是不合適的。另外從流量上說,反代那層本身壓力就很大了,我們要做的肯定是將他的實則單一化,效能最大化,這樣就算出現了問題影響範圍也會更小一些。

3 微服務層:

這層可以說是整個架構下業務最核心的地方了,以我的經驗來看,在設計初期微服務的業務範圍設定較考驗開發人員的經驗以及抽象能力。合理的規劃微服務,也是微服務架構一大重點。

另外一點是這層中也一定要注意服務間的依賴關係,服務之間要有層次關係,下層服務不能呼叫上層服務,減少業務規模化後程序擴充套件,重構時的複雜度。已經迴圈依賴可能會導致的服務啟動時的無限迴圈,導致服務無法啟動等問題。

4 儲存層:

這層就是資料儲存了,在網際網路環境下使用的種類也比較多。值得注意的是,在微服務下每個微服務只對應一個數據庫。絕對不允許出現多個微服務使用同一個資料庫,這樣會增加服務間的耦合。

5 服務治理中心:

服務治理比較重要,可以說是整個微服務架構中最核心的部分了,主要是解決專案規模化後的一些靜態配置難以維度等問題(例如 高可用的服務呼叫,負載均衡,服務降級等操作)

服務治理這裡使用的是Eureka,為什麼不用zookeeper呢?這裡主要原因是因為他們兩個的服務發現的機制不一樣,這裡就要說到著名的C(一致性)A(可用性)P(分割槽容錯性)定理了。當資料同步時在相對時間刻度下服務間資料未達到一致,即為發生了分割槽情況,這時就要在一致性和可用性之間進行選取。可以看出來P是不可避免的。所以CAP定理中就說到分散式系統最多滿足兩個。

其中Eureka遵從的是AP原則,zookeeper是CP原則。之所以zookeeper不適用與服務發現功能主要原因就是因為zookeeper叢集當leader發生故障後會進行leader競選而這個時候,服務發現功能為了保證服務消費者獲取到的服務列表是完全正確的,這時就會暫停服務發現,等選舉完成後恢復正常,而選舉往往會進行30s~120s很明顯這對服務發現來說幾乎是不能忍受的。一個是服務發現就性質來說本身變動性就相對較低,我們可以容忍註冊中心返回的是幾分鐘以前的註冊資訊,但不能接受服務直接掛掉不可用。所以就服務發現來說zookeeper是不適用的。

相反Eureka遵從的是CP原則,更強調可用性。Eureka各個節點都是平等的,幾個節點掛掉不會影響正常節點的工作,剩餘的節點依然可以提供註冊和查詢服務。而Eureka的客戶端在向某個Eureka註冊或時如果發現連線失敗,則會自動切換至其它節點,只要有一臺Eureka還在,就能保證註冊服務可用(保證可用性),只不過查到的資訊可能不是最新的(不保證強一致性)。除此之外,Eureka還有一種自我保護機制,如果在15分鐘內超過85%的節點都沒有正常的心跳,那麼Eureka就認為客戶端與註冊中心出現了網路故障,此時會出現以下幾種情況: 
        1. Eureka不再從註冊列表中移除因為長時間沒收到心跳而應該過期的服務 
        2. Eureka仍然能夠接受新服務的註冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用) 
        3. 當網路穩定時,當前例項新的註冊資訊會被同步到其它節點中

6 配置中心:

在服務規模化後,每個服務的配置不經相同,配置中心主要起到分環境配置以及配置中心化等功能

7訊息匯流排:

構建一個所有服務共用的訊息將所有微服務例項都連線起來,來做服務間溝通的一些功能,減少業務複雜度降低耦合。結合配置中心還能達到動態重新整理配置等效果Spring Cloud中提供了Spring Cloud Bus實現訊息匯流排。

總結:

微服務的興起的確是順應了發展,快速迭代,擁抱變化,輕量,成型後便於維護和擴充套件等優勢。但也有些弊端,例如運維成本較高,服務劃分對開發人員經驗要求較高。由於彼此間服務溝通是通過RestFul協議進行的,網路消耗相對也會更高一些。所以在架構選型上還是需要一定的前瞻性的調研的。切記不要盲目的跟從潮流。

由於是剛完成還需要進一步測試和完善有些細節還未想好,所以還請大家多多提出自己的看法共同進步。本文章也會持續迭代