Micro 架構與設計


Micro 架構與設計

翻譯自 Micro architecture & design patterns for microservices

注: 原文作者即 Micro 框架的開發者。

過去幾個月中,我們收到了很多關於 micro 的微服務架構和設計模式的問題。所以今天我們試着解釋一下這兩方面的問題。

關於 Micro

Micro 是一個微服務工具集。它被用來實現它的特性和接口,同時提供強大的可插拔的架構來保證基礎組件可以被替換掉。

Micro 專注於解決構建微服務系統的基礎需求。它采用了深思熟慮地富有預見性的方式來實現它的設計。

如果你想深入研究 Micro 工具集請點這里查看上一篇博客,或者如果你想學習微服務的基本概念請查看這里

在我們開始討論 Micro 的架構之前,我們將快速的介紹一下 Micro 的特性.

工具集

Go Micro

Go Micro是一個用 GO 來寫微服務的、可插拔的 RPC 框架。它提供了服務發現,客戶端負載均衡,編碼,同步異步通訊等功能的庫。

Micro API

Micro API 是為訪問微服務提供了 HTTP 服務和路由功能的 API 網管。在 Micro 中,它提供一個單一的入口,它可以被用作反向代理,或者將 HTTP 請求轉換成 RPC.

Micro Web

Micro Web 是微型網絡應用(micro web application)的儀表盤和反向代理。我們相信 web 應用應該被構建成微服務因此應被看做微服務世界的一等公民。它像一個 API 的反向代理但它同時提供對 web socket 的支持。

Micro Sidecar

Micro Sidecar 提供將 go-micro 用作 HTTP 服務的所有功能。Sidecar 提供使用其他語言寫微服務應用的途徑。

Micro CLI

Micro CLI 是和你的微服務們交互的命令行接口。它還可以讓你在不想直接連接服務的時候使用 Sidecar 作為一個代理。

下面讓我們更深入的了解。

RPC, REST, Proto...

你的第一個疑問可能就是,為什么是 RPC 而不是 REST? 我們認為 RPC 更適合內部服務通信的場景。或者更具體的, 使用 protobuf 編碼並且用 protobuf IDL 定義 API 的 RPC。聯合使用這些技術能夠很方便的創建強定義的 API 接口和有效的消息編碼。RPC 是非常直觀的通信協議。

我們並不是這一信條的獨立擁護者。

Google 是 protobuf 的創造者,在內部使用 RPC 並且最近開源的 RPC 框架 gRPC. Hailo 同樣也是 RPC/Protobuf 的強烈倡導者,並從中受益匪淺,更有趣的是在跨團隊協助方面獲得的收益比系統性能上的收益更多。Uber 正則開發資金的 PRC 框架協議 TChannel

我個人認為未來的 API 應該是使用 RPC 構建的,因為它有諸如 protobuf 這類的有良好的結構化的格式,有易用高效的編碼方法的協議,從而能構建強定義的 API 和高效的通訊。

HTTP 到 RPC, API...

然而在現實中,在 web 上使用 RPC 還有很長的路要走。盡管在數據中心內部使用 RPC 很完美,但是支撐高並發的網站和移動 API 又是另一回事。好吧,完全從 HTTP 切換到 RPC 來由很長的路要走。這也是為什么 micro 提供了 API 網關組件,來支撐和轉換 HTTP 請求。

API gateway 是微服務架構中使用的一種模式。它是微服務和外界溝通的唯一入口,它根據 HTTP 請求調用對應的服務。API gateway 使一個 HTTP API 能夠組合調用多個不同的微服務。

這是一個很強大的模式。因 API 一部分的更改導致整個單一部署的服務掛掉的日子將一去不復返。

微服務 API 使用 路徑-服務 的解決方案,因此每個請求路徑能夠調用不同的微服務 API,例如 /user => user api, /order => order api

舉個例子,到 /customer/orders 的請求將被帶着方法名 Customer.Orders 轉發到 API go.micro.api.customer

image

你可能好奇, API 服務到底是什么。現在我們來討論不同類型的服務。

微服務的類型

微服務的概念主要是按關注點分離 -- 從著名的 unix 哲學 doing one thing and doing it well 中借鑒了很多。出於這個原因,我們認為有必要從邏輯上和架構上將擁有不同任務的服務分離。

這些概念並不是什么新的概念,最近變得很引人注目是因為它被一些非常成功的技術公司證明是可行的。我們的目標是推廣這些開發哲學並通過構建工具鏈來指導設計決策。

以下是我們定義的服務的類型。

API - 基於 micro api,API 服務在設施的最頂端,一般直接支撐你的移動或 web 應用。你可以使用 HTTP handler 建造它然后使用反向代理模式啟動 micro api,或者,默認情況下處理這種專門格式的 RPC API 請求和響應。

Web - 基於 micro web, 專門用來提供 html 內容和管理面板訪問的 Web 服務。micro web 為 HTTP 和 WebSockets 提供反向代理。目前,僅支持這兩周格式,未來可能會支持更多的格式。就像之前提到過的那樣,我們相信 “web 應用即微服務”。

SRV - 基於 RPC 的后端服務。它們主要關注於為你的系統提供核心功能並且大多數情況下不會對外開放。如果你願意,你仍可以使用 micro api 或 micro web 使用 /rpc 路徑來訪問它,但一般使用 go-micro 客戶端來直接調用它們。

image

基於以往的經驗,我們發現這種架構模式及其強大並且見到過使用它支撐數百個微服務的系統。

Namespacing(命名空間)
你可能會好奇,如何隔斷 micro api 和 micro web 之間的通信?我們使用邏輯命名空間里做分離。通過給服務名加前綴(prefix)我們清晰的確定它的意圖以及它在系統中的位置。這個簡單但有效的模式讓我們受益良多。
micro api 和 micro web 將組成由命名空間和請求路徑的第一個路徑組成的服務名稱。例如,訪問 api/customer 的請求變為 go.micro.api.customer。

默認的命名空間為:

  • API - go.micro.api
  • Web - go.micro.web
  • SRV - go.micro.srv
    你應該為你自己的域名設定這些命名空間: com.example.{api, web, srv}。micro api 和 micro web 能夠配置成在運行時路由到你的命名空間。

同步和異步

我們經常聽到微服務和響應式模式一同出現。對於大多數來說,微服務是創建事件驅動的架構,並且主要通過異步通信的服務。

Micro 將異步通信作為一等公民對待並且將其構建成為微服務的基礎組成部分之一。通過與事件異步通信的方式允許任何人消費這些事件,並針對這些事件執行自己的任務。可以在此基礎上新的單獨部署的服務而不需要需改他們的其他任何方面。這是一個強大的設計模式並且正由於此我們在 go-micro 中實現了一個異步的 broker 接口。

image

在 Micro 中,同步和異步通信被放到隔離的需求中。Transport 接口用來創建服務間點對點的連接。構建在 transport 基礎上的 go-micro 客戶端和服務器能夠提供請求-響應模式的 RPC 調用,也可以提供雙向流模式下的調用。

image

在構建系統時兩種通信模型都應該被使用,但關鍵是要理解什么時候,在哪兒用哪種方式更合適。很多情況下,沒有對錯,但是我們還是要權衡兩種的利弊。
舉個例子,在制作用來保存跟蹤用戶操作歷史的審計系統時,broker 和異步通信可能更合適。

image

在這個例子中,每個 AI 或者說服務,當一些動作發生(客戶登錄,更新簡介或下訂單)時都會肺部一個事件。審計服務將會訂閱這些事件並將它們存儲到按時間序列存儲的數據庫中。管理員或其他任何用戶都能看到任何用戶產生的任何事件發生的歷史。

如果這個系統被設計成同步的,當流量高或服務數量增加時,審計系統很容易被壓垮。如果審計系統宕機或者請求失敗我們可能會丟失這條歷史記錄。通過將這些事件發布給 broker 我們能保持他們異步。這是事件驅動型架構構建的微服務的一種通用模式。

咳咳,暫停一下,微服務的定義是什么呢?

我們講了很多 Micro toolkit 提供的功能,也定義了很多類型的服務(API, WEB, SRV)但是並沒怎么講微服務到底是什么。

關於微服務的定義和解釋有很多,但這組是最合適的。

基於有限上下文的架構的低耦合的服務
--Adrian Cockcroft

將單個應用開發為一組跑在獨立進程上並且互相之間使用輕量級方法進行通信的微小的服務
--Martin Fowler

就像 unix 哲學說的那樣 Do one thing and do it well
--Doug McIlroy

我們認為一個微服務就是一個專注於一個實體(或領域)的應用 -- 並且通過強定義的 API 訪問它。
讓我們拿社交網絡來舉個現實中的例子。

image

有一個軟件架構模式隨着 Ruby On Rails 的崛起而變得流行 -- 那就是 MVC(模型 -- 視圖 -- 控制)。
在 MVC 的世界里,每個實體,或者說,域,都被表示為一個從數據庫中抽象而來的模型。模型可能和其他模型之間有相互關系,比如說一對多,多對多。控制層處理收到的請求,從 model 中查詢數據,然后把它傳遞給用戶,從而展現給用戶。

現在舉一個微服務架構中同樣的例子。模型被服務取而代之,它通過 API 傳遞數據。用戶請求,數據收集和數據呈現由多個 web service 處理。
每個服務都有一個單一的關注點。當我們想添加一個新功能或新的實體時,我們可以簡單的修改關注於那個功能的服務或者直接寫一個新的服務。這種分離的方式提供了能夠很好 scale 的軟件開發方式。

接下來我們回歸正題。

版本管理

image

版本管理是現實軟件開發中重要的一部分。在微服務的世界中很重要的一點是 API 和業務邏輯是被分成很多不同的服務的。正由於此,服務的版本控制很重要,被放到核心工具庫中,提供更好的細粒度的控制和升級過程中的流量遷移。

在 go-micro 中服務有一個名字和版本號定義。倉庫(Registry)返回一個 list 表示一個服務 -- 通過節點
注冊時的版本號來區分這些節點。
這是我們用於構建基於版本的路由功能的構建模塊的一段代碼

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

它和 Selector -- 一個客戶端的負載均衡 -- 結合起來使用,從而在 go-micro 內部保證請求分發到不同的版本上去。

Selector 是一個強大的接口。我們在它之上提供不同類型的路由算法:隨機(默認),round robin(環形隊列?),基於標簽,基於延遲,等等。
通過默認的基於隨機哈希的負載均衡算法,並逐步將新版本的服務實例加入,你可以執行藍綠發布(link)並實行金絲雀測試。

未來我們會實現一個內嵌 selector 的面向全球服務的負載均衡服務來提供為既存的系統做路由決策。它還能勝任在運行時為不同版本的服務分配不同的負載的職能,並且能動態地為服務添加原信息或標簽,從而在此之上可以做動態的路由決策。

伸縮

上文關於版本控制的說明經已提及了伸縮一個服務使用的基礎模型。倉庫(registry)用來存儲服務的相關信息,selector 用來控制路由和負載均衡。

我們再一次實踐了關注點分離(separation of concoerns)和做一件事並把它做好(dooing one thing well)的哲學。伸縮基礎設施、代碼很依賴於簡化、強定義的 API 以及分層的架構。通過編寫上面那些構建模塊,我們能夠開發伸縮性更強的軟件系統,並專注於更高層面的東西。

這是 Micro 的基礎,也是在微服務世界里我們希望引領的軟件開發的方式。

在之前的文章 Micro on NATS 中我們簡要討論了關於雲端架構模型的問題。現在我們簡單回顧下其中的一些觀點。
當在生產環境部署服務時,你希望你的系統是可伸縮的、能容錯的、以及性能優異的。雲計算使我們能構建有很強伸縮性能的服務,但很難不受錯誤影響。事實上容錯性是構建分布式系統時最關鍵的考察點之一。所以在構建基礎設施時,我們應該充分考慮容錯性。
在雲的世界里,我們希望能容忍可用區的錯誤,甚至是整個區域中斷。過去,我們嘗試通過熱備份,冷備份或者災難恢復計划來應對。現在,技術最先進的公司們有一個國際慣例,那就是把每個應用制作多個副本跑在世界各地的多個數據中心上。

我們需要向 Google, Facebook, Netflix 和 Twitter 學習。我們必須保證我們構建的系統能在可用區失敗時不影響用戶而且在大多數情況下在數分鍾內解決可用區失敗。

通過提供可插拔的接口, Micro 可以構建這樣的架構。我們能為 micro toolkit 中的每個需求選用最合適的分布式系統。

服務發現和倉庫(registry)是 Micro 的構建模塊。他能用來在可用區,區域或其他配置范圍內隔離和發現服務。
然后 Micro API 能夠在這個拓補結構中路由以及負責均衡一系列的服務。

image

Microservices is first and foremost about software design patterns. We can enable certain foundational patterns through tooling while providing flexibility for other patterns to emerge or be used.

Because Micro is a pluggable architecture it’s a powerful enabler of a variety of design patterns and can be appropriately used in many scenarios. For example if you’re building video streaming infrastructure you may opt for the HTTP transport for point to point communication. If you are not latency sensitive then you may choose a transport plugin such as NATS or RabbitMQ instead.

The future of software development with a tool such as Micro is very exciting.

If you want to learn more about the services we offer or microservices, check out the blog, the website micro.mu or the github repo.

總結

希望這篇文章講清了 Micro 的架構和它如何使用可伸縮的設計模式來開發微服務應用。
微服務首先是一種軟件設計模式。
.... 感覺后面沒啥用,就略了...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM