Go Micro(5)——架構與微服務的設計模式

weixin_34007291發表於2017-12-19

Go Micro(5)——架構與微服務的設計模式

有很多關於 micro 架構的疑問和微服務的設計模式的問題,今天我們討論一下這兩個話題。


關於Micro

Micro 是一個微服務工具箱,它有自己固有的設計模式,但外掛化的架構可以讓底層的實現很輕易的被替換。

micro 專注於定位微服務構建過程中的最基本的需求,並通過精密的設計來滿足這些需求。

檢視過往的文章可以瞭解微服務的理念和 Micro 的特性。

關於工具箱

Go Micro 是一個用 golang 編寫的,外掛化的 RPC 框架。它提供了基礎的庫,比如服務發現、客戶端負載均衡、編解碼、同步非同步通訊等。

Micro API 是一個 API 閘道器,用於將外部的 HTTP 請求路由到內部的 micro 服務上。它有單一的接入點,可以通過反向代理或者 http 轉換成 RPC 來訪問。

Micro Web 是一個 web 儀表盤,也是作為 micro web 應用的反向代理。我們相信 web 應用也應該是一個微服務,在微服務世界裡也應該是第一等公民。它表現的很像 Micro API 但也有單獨的特性比如 websocket

Micro Sidecar 使用 http 服務,提供了 go-micro 的所有特性。雖然我們喜歡 golang 來構建微服務,但你也許想使用其他語言。所以 Sidecar 提供了一種其他語言的應用接入 Micro 世界的方式。

Micro CLI 是一個簡單直接的命令列介面,用於與你的服務互動。他也可以使用你的 Sidecar 作為代理來連線服務。

上面是很簡單的介紹,下面我們更加深入一些。

RPC,REST,Proto…

第一件你想到的事情是,為什麼是 RPC,而不是 REST? 在內部服務間的通訊上,我們相信 RPC 是更合適的。或者更明確一點,RPC 使用 protobuf 做編碼,通過 protobuf 定義 API。這種方式把兩個需求結合起來了:一個需求是需要明確定義的 API 介面,另一個需求是高效能的訊息編解碼。RPC 是非常直接的通訊方式。

我們在這個選擇上並不孤獨。

Googleprotobuf 的創造者,在內部通過 gRPC 這個框架,大量的使用 RPC 呼叫。Hailo 也從 RPC/protobuf 的組合中收益很多,不僅是系統效能,開發速度也提高很多。Uber 選擇開發自己的RPC框架,名字叫 TChannel

個人而言我認為未來的 API 將會使用 RPC 進行構建,因為它們結構化的格式、高效的編解碼提供了定義良好的 API 和高效能的通訊。

HTTP to RPC,API…

事實上,我們在 webRPC 還有很長的路要走。在內部 RPC 的表現是完美的,但在面對外部請求比如網站、手機 app 的介面等等,就是另外一回事了。我們需要面對這個,這就是為什麼 Micro 需要一個 API 閘道器,用來接受並轉換 http 請求。

API 閘道器在微服務架構中是一個常見的模式。它作為一個單一的接入點,外部世界的請求,通過它進行路由分發。它讓 HTTP API 可以由背後的很多服務所組成。

microAPI 閘道器使用路徑到服務的解決方案,因此不同的請求路徑,對應了不同的服務。比如 /user => user api,/order => order api

這裡有一個例子。一個請求的路徑是 /comstomer/orders,這個請求會被轉發到 go.micro.api.customer 這個服務,會使用 Customer.Orders 這個方法進行處理。

6479455-d7ab42c49a1c47d8.png
image.png

你也許會問,API 服務到底是怎樣的?我們下面來討論一下不同型別的服務。

服務的型別

微服務的關鍵理念就是業務的拆解,這是從 unix 的設計哲學中得到的啟示:『doing one thing and doing it well』,因為這個原因,我們認為不同的服務需要有邏輯上和架構上的區別,以實現自己不同的任務。

我們知道這些理念並沒有什麼太大的新意,但在一些非常大而且成功的公司,它們的實踐取得了成功。我們的目標是傳播這些開發理念,並通過工具來進行指導。

目前我們定義了下面的幾種服務。

API

通過 micro api 執行,API 服務在你的架構中處於關鍵位置,大部分作用是接受外部世界的請求並分發到內部的服務上。你可以通過 micro api 提供的反向代理 REST 模式進行訪問,也可以通過 RPC 介面進行訪問。

WEB

通過 micro web 執行,web 服務專注於服務 html 請求,構建儀表盤。micro web 反向代理 httpwebsocket,目前只有這兩種協議支援,未來也許會增加。

SRV

這是後臺的 RPC 服務,他們的目標是為你的系統提供核心的功能,大部分並不是公開的介面。你仍然可以通過 micro apimicro web,使用 /rpc 接入點進行訪問。這種接入方式直接使用 go-microclient 進行呼叫。

6479455-7f24a040058b5167.png
image.png

按照過去的經驗,我們發現這樣的架構設計非常強大。可以被擴充套件到數以百計的服務。通過把它整合到 Micro 架構中,我們發現它為微服務的開發提供了非常好的基礎。

Namespacing

你也許會想,怎樣區分 micro api 或者 micro web 以及服務呢。我們通過名稱空間進行拆分。通過命名的字首,我們可以很清晰的看到,某個服務是哪種型別的。這很簡單但很高效。

micro api 會把 /customer 這樣的請求路徑定位到 go.micro.api.customer 服務。

預設的名稱空間是:

  • API - go.micro.api
  • WEB - go.micro.web
  • SRV - go.micro.srv

你應該把它設定成你的域名,比如 com.example.api。這些都可以進行配置。


同步和非同步

你經常聽說微服務是很靈活的模式。大多數來說,微服務是關於創造事件驅動的架構,以及設計通過非同步通訊的方式響應的服務。

Micro 把非同步通訊作為微服務構建中的第一等公民。事件通過非同步訊息,可以被任何人消費並作出反應,搭建一個新服務不需要對系統的其他部分作出任何更改。這是一種強大的設計模式,因為這個原因,我們在 go-micro 中定義了 Broker 介面。

6479455-2ab53b8794550c9a.png
image.png

非同步和同步通訊在Micro中是分離開的。Transport 介面用於構建服務之間的點對點的通訊。go-micro 中的 clientserver 基於 transport 來進行請求和返回RPC呼叫,提供了雙向的通訊流。

6479455-18d4832973113a6b.png
image.png

在構建系統時,兩種通訊方式都應該使用,但關鍵是理解在什麼場景下應該用什麼型別的通訊方式。在大部分情況下並沒有好壞之分,我們需要權衡處理。

一個 broker 和非同步通訊的典型使用方式是這樣:監聽系統通過 broker 對服務的事件歷史進行記錄。

6479455-465fc9c1cee3a2fc.png
image.png

在這個例子中,每個服務的每個 API 在被呼叫時,都會把事件上報到監聽 topic,監聽系統會訂閱這個 topic,並把他們儲存到時間序列的資料庫中。在 admin 管理平臺可以看到任何使用者的操作歷史。

如果我們通過同步通訊做,監聽系統直接面對巨大的請求數。如果監聽系統當機了,我們就丟失了這些資料。通過把這些事件釋出到 broker,我們可以非同步的持久化這些資料。這是一種微服務中常見的事件驅動設計模型。

我們怎樣定義微服務?

我們已經討論了很多 Micro 能為微服務提供的工具箱,也定義了服務的型別。但還沒有真正討論,到底什麼是微服務。

微服務與其他應用的區別到底在哪裡,微服務為什麼叫微服務。

現在有很多不同的定義,但有兩條適合大部分微服務系統。

Loosely coupled service oriented architecture with a bounded context

An approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms

微服務的哲學與 unix 也類似

Do one thing and do it well

我們認為微服務是這樣一種應用程式:專注於單一的業務,並通過明確定義的API對外提供服務。

看看我們在社交網路中怎樣使用微服務:

6479455-f8c27ad362269232.png
image.png

其中一種是流行的 MVC 架構,在 MVC 世界中,每個實體代表了一個模型,模型又是作為資料庫的抽象。模型之間也許有一對多或者多對多的關係。controller 模組負責處理請求,接受 model 模組返回的資料,並把資料傳輸到 view 層,進行渲染,最後輸出給使用者。

在微服務架構中,面對同樣的例子。每個模型實際上是一個服務,通過 API 進行服務間通訊。使用者請求,資料的集合以及渲染是通過一系列不同的 web 服務進行處理的。每個服務有自身的專注點,當我們需要增加一個新特性時,我們只需要把關聯的服務進行修改,或者直接寫一個新的服務。分離的理念提供了大規模開發的模式。

版本

6479455-b92b56d04e4b4555.png
image.png

開發真實世界的軟體時,版本是非常重要的。在微服務世界裡,嚴格的把 API 和業務邏輯分離到許多不同的服務上,因為這個原因,服務的版本控制是核心的工具的很重要的一部分。可以讓我們在流量很大時也能進行升級。

go-micro 中,服務定義了名字和版本,Registry 模組返回服務的列表,根據版本把節點進行了區分。這裡是 service 的介面定義。

type Service struct {
    Name      string
    Version   string
    Metadata  map[string]string
    Endpoints []*Endpoint
    Nodes     []*Node
}

版本控制需要與 Selector 結合起來,selector 是客戶端的負載均衡機制,通過 selector 的策略實現請求根據版本進行分發。

selector 是非常強大的介面,我們根據不同的路由演算法,比如隨機、輪詢、根據標籤、響應時間等等。

通過使用預設的隨機負載演算法,再加上版本控制演算法,我們就可以進行灰度釋出。

6479455-535e5bedc510b109.png
image.png

在未來,我們會嘗試實現一個全域性的負載策略,根據歷史的趨勢進行選擇,可以根據版本,設定不同的百分比,並動態的為服務增加標籤。

大規模擴充套件

上面的介紹的版本系統,是大規模擴充套件服務時的基本模式。register 儲存了服務的註冊資訊,我們通過 selector 實現了路由和負載均衡。

按照 doing one thing well 的理念,擴充套件架構也應該是簡單、明確定義的 API、分層次的架構。通過創造這些工具,我們可以構建更加可靠的系統,專注於更高階別的業務需求。

這是 Micro 編寫的基礎理念,也是我們希望微服務開發者遵循的理念。

當我們在生產環境部署應用時,我們就需要構建可擴充套件、高容錯、高效能的應用。雲端計算讓我們可以進行不受限制的擴充套件,但是沒有任何東西會一直正常執行。事實上,在構建分散式系統中,怎樣對待執行失敗的服務是非常重要的一方面,你在構建你的系統時,需要好好考慮。

在雲端計算的世界,我們想要在資料中執行錯誤,甚至多個資料中心執行錯誤的情況下,也能正常提供服務。在過去我們討論的是冷熱備份,或者是災難恢復計劃。在今天,最先進的技術公司,在全世界不停歇的運作,每個程式都會有多個備份,執行在世界上不同的資料中心。

我們需要向 google,facebook,netflix 和 Twitter 學習,即使在資料中心執行失敗時,也要對使用者提供服務,在多個資料中心執行失敗時,也需要儘快恢復。

Micro 可以讓你構建這樣的應用,通過外掛化的架構,我們可以為不同的分散式系統,實現不同的工具箱。

服務發現和註冊器是 Micro 的關鍵模組,它們可以用於發現在資料中心中的一系列服務,Micro API 可以用於路由和負載一系列的服務。

[圖片上傳中...(image.png-ffb75d-1513663516734-0)]


總結

希望這篇文章清晰的講解了Micro的架構,以及怎樣實現可擴充套件的微服務設計模式。微服務首先是一種軟體設計模式,我們可以通過工具實現基礎、核心的功能,同時也能靈活組合其他設計模式。

因為 Micro 是一個外掛化的架構,它強大的能力,可以實現不同的設計模式,在不同的場景中都能使用。比如你構建一個視訊流的服務,你也許需要基於 http 的點對點服務。如果你對效能不敏感,你也許需要使用訊息佇列比如 NATSRabbitMQ

使用Micro這樣的工具進行開發是非常讓人興奮的。

相關文章