微服務架(Microservices)構到底是什麼?

關注「前端向後」微信公衆號,你將收穫一系列「用心原創」的高質量技術文章,主題包括但不限於前端、Node.js以及服務端技術html

本文首發於 ayqy.net ,原文連接:http://www.ayqy.net/blog/%E5%...前端

零.從 Monolithic application 提及

Monolith means composed all in one piece. The Monolithic application describes a single-tiered software application in which different components combined into a single program from a single platform.

(摘自Introduction to Monolithic Architecture and MicroServices Architecturejava

把軟件應用的不一樣組件都放到一個程序中,就叫 Monolithic application。例如,經過編程語言的基本特性將應用劃分紅類、函數和命名空間,用部署流水線來保證變動都通過測試後才部署到生產環境,並經過負載均衡機制運行多個實例,將其進行橫向擴展:數據庫

All your logic for handling a request runs in a single process, allowing you to use the basic features of your language to divide up the application into classes, functions, and namespaces. With some care, you can run and test the application on a developer's laptop, and use a deployment pipeline to ensure that changes are properly tested and deployed into production. You can horizontally scale the monolith by running many instances behind a load-balancer.

在這種架構模式下,應用程序也能很好地工做,但存在 2 個問題:編程

  • 變動受限制:很小的一處變動也須要對整個應用進行從新構建和部署,並且難以控制變動的影響範圍
  • 不利於擴展:沒法僅擴展應用中須要更多資源的那些部分,只能擴展整個應用

這些限制在雲環境下尤爲突出。因而,微服務架構登上了舞臺微信

一.微服務架構是什麼?

Microservices are a software development technique—a variant of the service-oriented architecture (SOA) architectural style that structures an application as a collection of loosely coupled services. In a microservices architecture, services are fine-grained and the protocols are lightweight.

(摘自Microservices網絡

面向服務架構(SOA)的一種變體,把應用程序設計成一系列鬆耦合的細粒度服務,並經過輕量級的通訊協議組織起來架構

Building applications as suites of services. As well as the fact that services are independently deployable and scalable, each service also provides a firm module boundary, even allowing for different services to be written in different programming languages. They can also be managed by different teams.

具體地,將應用構建成一組小型服務。這些服務都可以獨立部署、獨立擴展,每一個服務都具備穩固的模塊邊界,甚至容許使用不一樣的編程語言來編寫不一樣服務,也能夠由不一樣的團隊來管理app

微服務與 SOA

Service-oriented architecture (SOA) is a style of software design where services are provided to the other components by application components, through a communication protocol over a network.

(摘自Service-oriented architecture負載均衡

SOA 中,服務由應用程序組件經過網絡通訊協議提供給其它組件。所以,微服務架構算是 SOA 的一種變體,或者說是特例,特指知足某些特徵的 SOA 設計

二.微服務架構的 9 大特徵

經過服務進行組件化(Componentization via Services)

組件能夠理解爲可以獨立更換升級的軟件單元,一系列組件插在一塊兒構成軟件系統,就像物理世界中咱們所見到的那樣:

Our definition is that a component is a unit of software that is independently replaceable and upgradeable. There's been a desire to build systems by plugging together components, much in the way we see things are made in the physical world.

在微服務架構中,組件就是服務,經過 Web 服務請求或 RPC 之類的機制通訊。這種服務粒度的組件化方式有 2 點優點:

獨立部署,意味着對一個服務的內部改動只須要從新部署該服務,涉及服務接口改動時才須要協同修改多個服務。另外一方面,還能夠經過服務邊界和服務協議方面的演進來儘量減小這樣的關聯

顯式的對外接口則是一種強約束,可以保證組件的封裝性,避免組件間出現過分的緊耦合

但比起進程內調用,RPC 的性能成本更高,所以 RPC 接口大可能是粗粒度的,也每每更難使用。另外一方面,若是想要調整組件職責的話,重構成本也更高

圍繞業務功能來組織團隊(Organized around Business Capabilities)

微服務容許將系統根據業務功能分解成一系列服務,所以能夠圍繞業務功能來組織跨職能的團隊。而且,這種組織結構還有利於強化服務邊界

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-8rxLM9xU-1577238129023)(https://martinfowler.com/arti...]

P.S.康威定律,設計結構最終都會與該組織的溝通結構相一致:

Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure. -- Melvyn Conway, 1967

溝通結構改變設計結構的一個頗有意思的例子是,一些團隊會把邏輯塞到本身可以掌控的應用中,以免跨團隊協做的溝通成本:

A smart team will optimise around this and plump for the lesser of two evils - just force the logic into whichever application they have access to.

比起在 Monolithic application 中按業務線劃分團隊,以服務爲邊界更清晰、約束力也更強。由於很容易出現跨越模塊邊界的業務功能,而服務邊界相對穩固一些

作產品而不是作項目(Products not Projects)

微服務架構傾向於一個產品由所屬開發團隊長期維護/演進,而不是項目交付後轉由另外一個維護團隊負責:

Microservice proponents tend to avoid this model, preferring instead the notion that a team should own a product over its full lifetime.

這種產品理念可以在開發團隊與用戶之間創建持續的關聯,讓開發團隊關注到軟件如何幫助用戶增進業務功能:

There is an on-going relationship where the question is how can software assist its users to enhance the business capability.

智能端點和傻瓜式管道(Smart endpoints and dumb pipes)

通訊機制上,一個典型的例子是企業服務總線(Enterprise Service Bus),消息都流經 ESB,由 ESB 負責消息路由、編排、轉換以及業務規則的應用,隨後到達端點(endpoints)進行處理。這種模式下,端點能夠保持傻瓜式,由於不少邏輯都在 ESB 消息管道里處理了。所以,稱之爲智能管道和傻瓜式端點(smart pipes and dumb endpoints)

而微服務傾向於相反的作法,智能端點和傻瓜式管道(smart endpoints and dumb pipes):

That the lanes of communication should be stripped of business processing and logic and should literally only distribute messages between components. It's then the components themselves that do processing / logic / validation etc... on those messages.

即,管道只負責在組件之間分發消息,由服務自己針對消息作相應處理

去中心化技術治理(Decentralized Governance)

中心化技術治理最大的問題在於其侷限性,統一的技術棧並不必定適用於全部場景:

Experience shows that this approach is constricting - not every problem is a nail and not every solution a hammer, we prefer using the right tool for the job.

而在微服務背景下,每一個服務單獨構建,就有了選擇不一樣技術棧的機會,容許用更合適的工具去作不一樣的事情。這種技術棧上的自由有助於服務獨立演進,天然選擇出更好的模式

固然,「之前沒得選,如今能選了」並不意味着百花齊放就是好的,由於維護不一樣技術生態的成本可能高過其收益:

We don’t end up with 20 different languages in the same system because each of them is opinionated and brings their own vision inside the system, maintaining different ecosystem is very expensive and potentially confusing without providing too many benefits.

權衡之下,咱們能夠將選擇範圍限制到某幾種技術棧,而再也不與一種技術棧強綁定:

But a trade-off could help out, having a limited list of languages or frameworks we can pick from can really help. Suddenly, we are not tightly coupled with one stack only.

去中心化數據管理(Decentralized Data Management)

從最抽象的層面看,去中心化地管理數據,意味着各個系統對客觀世界所造成的概念模型各不相同。好比銷售人員眼中的客戶與開發人員所理解的不一樣,相同的概念在兩個視角中可能也存在微妙的差別

應對這種狀況的有效措施是領域驅動設計(Domain-Driven Design)中的界限上下文(Bounded Context):

應該顯式地定義某個模型所應用的上下文。還應該在團隊組織、應用中特定部分的使用以及像代碼庫和數據庫模式等物理表現等方面顯式地設定邊界。要保持邊界中模型的嚴格一致,而不要受外界問題的影響與干擾。

(摘自初窺 Bounded Context

即,給模型概念限定一個上下文,在該上下文中保證概念嚴格一致。把一個複雜領域劃分紅多個界限上下文,再將其間關聯勾畫出來,就是概念模型層面的去中心化

DDD divides a complex domain up into multiple bounded contexts and maps out the relationships between them.

具體到數據存儲上,微服務也進行相似的去中心化策略,讓每個服務管理本身的數據庫。這些數據庫能夠是相同數據庫的不一樣實例,也能夠是徹底不一樣的數據庫系統,稱之爲混合持久化

Microservices prefer letting each service manage its own database, either different instances of the same database technology, or entirely different database systems - an approach called Polyglot Persistence.

P.S.對於去中心化數據存儲帶來的數據一致性問題,能夠考慮經過一些補償操做來讓數據最終達到一致,具體見Starbucks Does Not Use Two-Phase Commit

基礎設施自動化(Infrastructure Automation)

與 Monolithic application 相比,微服務的部署要更復雜一些。由於在複雜的網絡環境中,部署多個服務比部署一個獨立應用更困難:

但云計算的發展讓基礎設施自動化成爲可能,大大下降了服務構建、部署、運維的複雜性,讓咱們能夠利用基礎設施自動化實現生產環境中的微服務管理

容錯設計(Design for failure)

在微服務背景下,客戶端的容錯設計更爲重要:

A consequence of using services as components, is that applications need to be designed so that they can tolerate the failure of services. Any service call could fail due to unavailability of the supplier, the client has to respond to this as gracefully as possible.

比起 Monolithic application,這種容錯設計帶來的額外複雜性算是一種劣勢

另外一方面,爲了快速檢測到故障點,甚至儘量自動恢復服務,實時監控在微服務架構中也格外重要

P.S.關於容錯設計的更多信息,見Fault Tolerance in a High Volume, Distributed System

演進式設計(Evolutionary Design)

組件的劃分在微服務架構中很關鍵,關係到可否減小變化。通常原則是該組件可否獨立更換和升級:

The key property of a component is the notion of independent replacement and upgradeability.

然而,從另外一個角度看,_控制變化並不必定非要減小變化_,若是確保這些變化可以如預期地快速進行,也是一種極好的控制

Change control doesn't necessarily mean change reduction - with the right attitudes and tools you can make frequent, fast, and well-controlled changes to software.

把微服務架構提供的服務分解能力當作一種工具來使用,以此實現服務粒度的變化控制:

  • 預期一些服務未來會做廢,沒必要長期演進
  • 把那些會同時變化的東西放到同一個服務中,把不多發生變化的部分放到單獨服務中,與常常發生變化的部分區分開

三.微服務架構的關鍵問題

首先,準肯定義組件邊界不是件容易的事情

It's hard to figure out exactly where the component boundaries should lie.

所以,演進式設計退而求其次,讓邊界更容易重構(下降試錯成本):

Evolutionary design recognizes the difficulties of getting boundaries right and thus the importance of it being easy to refactor them. But when your components are services with remote communications, then refactoring is much harder than with in-process libraries.

另外一方面,若是設計很差的話,這樣作只是把組件內的複雜度轉移到了組件之間的鏈接上,變得更難控制

Another issue is If the components do not compose cleanly, then all you are doing is shifting complexity from inside a component to the connections between components. Not just does this just move complexity around, it moves it to a place that's less explicit and harder to control.

極可能出現這樣的局面,單個簡單服務內部看起來變好了,服務之間雜亂的鏈接卻被忽略了:

It's easy to think things are better when you are looking at the inside of a small, simple component, while missing messy connections between services.

參考資料

相關文章
相關標籤/搜索