Go Micro(5)——架構(gòu)與微服務(wù)的設(shè)計模式

Go Micro(5)——架構(gòu)與微服務(wù)的設(shè)計模式

有很多關(guān)于 micro 架構(gòu)的疑問和微服務(wù)的設(shè)計模式的問題,今天我們討論一下這兩個話題。


關(guān)于Micro

Micro 是一個微服務(wù)工具箱,它有自己固有的設(shè)計模式,但插件化的架構(gòu)可以讓底層的實現(xiàn)很輕易的被替換。

micro 專注于定位微服務(wù)構(gòu)建過程中的最基本的需求,并通過精密的設(shè)計來滿足這些需求。

查看過往的文章可以了解微服務(wù)的理念和 Micro 的特性。

關(guān)于工具箱

Go Micro 是一個用 golang 編寫的,插件化的 RPC 框架。它提供了基礎(chǔ)的庫,比如服務(wù)發(fā)現(xiàn)、客戶端負(fù)載均衡、編解碼、同步異步通信等。

Micro API 是一個 API 網(wǎng)關(guān),用于將外部的 HTTP 請求路由到內(nèi)部的 micro 服務(wù)上。它有單一的接入點,可以通過反向代理或者 http 轉(zhuǎn)換成 RPC 來訪問。

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

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

Micro CLI 是一個簡單直接的命令行接口,用于與你的服務(wù)交互。他也可以使用你的 Sidecar 作為代理來連接服務(wù)。

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

RPC,REST,Proto…

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

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

Googleprotobuf 的創(chuàng)造者,在內(nèi)部通過 gRPC 這個框架,大量的使用 RPC 調(diào)用。Hailo 也從 RPC/protobuf 的組合中收益很多,不僅是系統(tǒng)性能,開發(fā)速度也提高很多。Uber 選擇開發(fā)自己的RPC框架,名字叫 TChannel

個人而言我認(rèn)為未來的 API 將會使用 RPC 進(jìn)行構(gòu)建,因為它們結(jié)構(gòu)化的格式、高效的編解碼提供了定義良好的 API 和高性能的通信。

HTTP to RPC,API…

事實上,我們在 webRPC 還有很長的路要走。在內(nèi)部 RPC 的表現(xiàn)是完美的,但在面對外部請求比如網(wǎng)站、手機(jī) app 的接口等等,就是另外一回事了。我們需要面對這個,這就是為什么 Micro 需要一個 API 網(wǎng)關(guān),用來接受并轉(zhuǎn)換 http 請求。

API 網(wǎng)關(guān)在微服務(wù)架構(gòu)中是一個常見的模式。它作為一個單一的接入點,外部世界的請求,通過它進(jìn)行路由分發(fā)。它讓 HTTP API 可以由背后的很多服務(wù)所組成。

microAPI 網(wǎng)關(guān)使用路徑到服務(wù)的解決方案,因此不同的請求路徑,對應(yīng)了不同的服務(wù)。比如 /user => user api,/order => order api

這里有一個例子。一個請求的路徑是 /comstomer/orders,這個請求會被轉(zhuǎn)發(fā)到 go.micro.api.customer 這個服務(wù),會使用 Customer.Orders 這個方法進(jìn)行處理。

image.png

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

服務(wù)的類型

微服務(wù)的關(guān)鍵理念就是業(yè)務(wù)的拆解,這是從 unix 的設(shè)計哲學(xué)中得到的啟示:『doing one thing and doing it well』,因為這個原因,我們認(rèn)為不同的服務(wù)需要有邏輯上和架構(gòu)上的區(qū)別,以實現(xiàn)自己不同的任務(wù)。

我們知道這些理念并沒有什么太大的新意,但在一些非常大而且成功的公司,它們的實踐取得了成功。我們的目標(biāo)是傳播這些開發(fā)理念,并通過工具來進(jìn)行指導(dǎo)。

目前我們定義了下面的幾種服務(wù)。

API

通過 micro api 運行,API 服務(wù)在你的架構(gòu)中處于關(guān)鍵位置,大部分作用是接受外部世界的請求并分發(fā)到內(nèi)部的服務(wù)上。你可以通過 micro api 提供的反向代理 REST 模式進(jìn)行訪問,也可以通過 RPC 接口進(jìn)行訪問。

WEB

通過 micro web 運行,web 服務(wù)專注于服務(wù) html 請求,構(gòu)建儀表盤。micro web 反向代理 httpwebsocket,目前只有這兩種協(xié)議支持,未來也許會增加。

SRV

這是后臺的 RPC 服務(wù),他們的目標(biāo)是為你的系統(tǒng)提供核心的功能,大部分并不是公開的接口。你仍然可以通過 micro apimicro web,使用 /rpc 接入點進(jìn)行訪問。這種接入方式直接使用 go-microclient 進(jìn)行調(diào)用。

image.png

按照過去的經(jīng)驗,我們發(fā)現(xiàn)這樣的架構(gòu)設(shè)計非常強大。可以被擴(kuò)展到數(shù)以百計的服務(wù)。通過把它整合到 Micro 架構(gòu)中,我們發(fā)現(xiàn)它為微服務(wù)的開發(fā)提供了非常好的基礎(chǔ)。

Namespacing

你也許會想,怎樣區(qū)分 micro api 或者 micro web 以及服務(wù)呢。我們通過命名空間進(jìn)行拆分。通過命名的前綴,我們可以很清晰的看到,某個服務(wù)是哪種類型的。這很簡單但很高效。

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

默認(rèn)的命名空間是:

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

你應(yīng)該把它設(shè)置成你的域名,比如 com.example.api。這些都可以進(jìn)行配置。


同步和異步

你經(jīng)常聽說微服務(wù)是很靈活的模式。大多數(shù)來說,微服務(wù)是關(guān)于創(chuàng)造事件驅(qū)動的架構(gòu),以及設(shè)計通過異步通信的方式響應(yīng)的服務(wù)。

Micro 把異步通信作為微服務(wù)構(gòu)建中的第一等公民。事件通過異步消息,可以被任何人消費并作出反應(yīng),搭建一個新服務(wù)不需要對系統(tǒng)的其他部分作出任何更改。這是一種強大的設(shè)計模式,因為這個原因,我們在 go-micro 中定義了 Broker 接口。

image.png

異步和同步通信在Micro中是分離開的。Transport 接口用于構(gòu)建服務(wù)之間的點對點的通信。go-micro 中的 clientserver 基于 transport 來進(jìn)行請求和返回RPC調(diào)用,提供了雙向的通信流。

image.png

在構(gòu)建系統(tǒng)時,兩種通信方式都應(yīng)該使用,但關(guān)鍵是理解在什么場景下應(yīng)該用什么類型的通信方式。在大部分情況下并沒有好壞之分,我們需要權(quán)衡處理。

一個 broker 和異步通信的典型使用方式是這樣:監(jiān)聽系統(tǒng)通過 broker 對服務(wù)的事件歷史進(jìn)行記錄。

image.png

在這個例子中,每個服務(wù)的每個 API 在被調(diào)用時,都會把事件上報到監(jiān)聽 topic,監(jiān)聽系統(tǒng)會訂閱這個 topic,并把他們存儲到時間序列的數(shù)據(jù)庫中。在 admin 管理平臺可以看到任何用戶的操作歷史。

如果我們通過同步通信做,監(jiān)聽系統(tǒng)直接面對巨大的請求數(shù)。如果監(jiān)聽系統(tǒng)宕機(jī)了,我們就丟失了這些數(shù)據(jù)。通過把這些事件發(fā)布到 broker,我們可以異步的持久化這些數(shù)據(jù)。這是一種微服務(wù)中常見的事件驅(qū)動設(shè)計模型。

我們怎樣定義微服務(wù)?

我們已經(jīng)討論了很多 Micro 能為微服務(wù)提供的工具箱,也定義了服務(wù)的類型。但還沒有真正討論,到底什么是微服務(wù)。

微服務(wù)與其他應(yīng)用的區(qū)別到底在哪里,微服務(wù)為什么叫微服務(wù)。

現(xiàn)在有很多不同的定義,但有兩條適合大部分微服務(wù)系統(tǒng)。

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

微服務(wù)的哲學(xué)與 unix 也類似

Do one thing and do it well

我們認(rèn)為微服務(wù)是這樣一種應(yīng)用程序:專注于單一的業(yè)務(wù),并通過明確定義的API對外提供服務(wù)。

看看我們在社交網(wǎng)絡(luò)中怎樣使用微服務(wù):

image.png

其中一種是流行的 MVC 架構(gòu),在 MVC 世界中,每個實體代表了一個模型,模型又是作為數(shù)據(jù)庫的抽象。模型之間也許有一對多或者多對多的關(guān)系。controller 模塊負(fù)責(zé)處理請求,接受 model 模塊返回的數(shù)據(jù),并把數(shù)據(jù)傳輸?shù)?view 層,進(jìn)行渲染,最后輸出給用戶。

在微服務(wù)架構(gòu)中,面對同樣的例子。每個模型實際上是一個服務(wù),通過 API 進(jìn)行服務(wù)間通信。用戶請求,數(shù)據(jù)的集合以及渲染是通過一系列不同的 web 服務(wù)進(jìn)行處理的。每個服務(wù)有自身的專注點,當(dāng)我們需要增加一個新特性時,我們只需要把關(guān)聯(lián)的服務(wù)進(jìn)行修改,或者直接寫一個新的服務(wù)。分離的理念提供了大規(guī)模開發(fā)的模式。

版本

image.png

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

go-micro 中,服務(wù)定義了名字和版本,Registry 模塊返回服務(wù)的列表,根據(jù)版本把節(jié)點進(jìn)行了區(qū)分。這里是 service 的接口定義。

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

版本控制需要與 Selector 結(jié)合起來,selector 是客戶端的負(fù)載均衡機(jī)制,通過 selector 的策略實現(xiàn)請求根據(jù)版本進(jìn)行分發(fā)。

selector 是非常強大的接口,我們根據(jù)不同的路由算法,比如隨機(jī)、輪詢、根據(jù)標(biāo)簽、響應(yīng)時間等等。

通過使用默認(rèn)的隨機(jī)負(fù)載算法,再加上版本控制算法,我們就可以進(jìn)行灰度發(fā)布。

image.png

在未來,我們會嘗試實現(xiàn)一個全局的負(fù)載策略,根據(jù)歷史的趨勢進(jìn)行選擇,可以根據(jù)版本,設(shè)置不同的百分比,并動態(tài)的為服務(wù)增加標(biāo)簽。

大規(guī)模擴(kuò)展

上面的介紹的版本系統(tǒng),是大規(guī)模擴(kuò)展服務(wù)時的基本模式。register 存儲了服務(wù)的注冊信息,我們通過 selector 實現(xiàn)了路由和負(fù)載均衡。

按照 doing one thing well 的理念,擴(kuò)展架構(gòu)也應(yīng)該是簡單、明確定義的 API、分層次的架構(gòu)。通過創(chuàng)造這些工具,我們可以構(gòu)建更加可靠的系統(tǒng),專注于更高級別的業(yè)務(wù)需求。

這是 Micro 編寫的基礎(chǔ)理念,也是我們希望微服務(wù)開發(fā)者遵循的理念。

當(dāng)我們在生產(chǎn)環(huán)境部署應(yīng)用時,我們就需要構(gòu)建可擴(kuò)展、高容錯、高性能的應(yīng)用。云計算讓我們可以進(jìn)行不受限制的擴(kuò)展,但是沒有任何東西會一直正常運行。事實上,在構(gòu)建分布式系統(tǒng)中,怎樣對待運行失敗的服務(wù)是非常重要的一方面,你在構(gòu)建你的系統(tǒng)時,需要好好考慮。

在云計算的世界,我們想要在數(shù)據(jù)中運行錯誤,甚至多個數(shù)據(jù)中心運行錯誤的情況下,也能正常提供服務(wù)。在過去我們討論的是冷熱備份,或者是災(zāi)難恢復(fù)計劃。在今天,最先進(jìn)的技術(shù)公司,在全世界不停歇的運作,每個程序都會有多個備份,運行在世界上不同的數(shù)據(jù)中心。

我們需要向 google,facebook,netflix 和 Twitter 學(xué)習(xí),即使在數(shù)據(jù)中心運行失敗時,也要對用戶提供服務(wù),在多個數(shù)據(jù)中心運行失敗時,也需要盡快恢復(fù)。

Micro 可以讓你構(gòu)建這樣的應(yīng)用,通過插件化的架構(gòu),我們可以為不同的分布式系統(tǒng),實現(xiàn)不同的工具箱。

服務(wù)發(fā)現(xiàn)和注冊器是 Micro 的關(guān)鍵模塊,它們可以用于發(fā)現(xiàn)在數(shù)據(jù)中心中的一系列服務(wù),Micro API 可以用于路由和負(fù)載一系列的服務(wù)。

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


總結(jié)

希望這篇文章清晰的講解了Micro的架構(gòu),以及怎樣實現(xiàn)可擴(kuò)展的微服務(wù)設(shè)計模式。微服務(wù)首先是一種軟件設(shè)計模式,我們可以通過工具實現(xiàn)基礎(chǔ)、核心的功能,同時也能靈活組合其他設(shè)計模式。

因為 Micro 是一個插件化的架構(gòu),它強大的能力,可以實現(xiàn)不同的設(shè)計模式,在不同的場景中都能使用。比如你構(gòu)建一個視頻流的服務(wù),你也許需要基于 http 的點對點服務(wù)。如果你對性能不敏感,你也許需要使用消息隊列比如 NATSRabbitMQ

使用Micro這樣的工具進(jìn)行開發(fā)是非常讓人興奮的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容