跳到主要內容
黯羽輕揚每天積累一點點

微服務架構(Microservices)

免費2019-08-11#Front-End#前端微服务#微服务与微前端#微服务架构的优缺点#Microservices vs SOA#Microservices Pros Cons

微服務架構(Microservices)究竟是什麼?

零.從 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 Architecture

把軟件應用的不同組件都放到一個程序中,就叫 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.

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

微服務與 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)

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

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.

參考資料

評論

暫無評論,快來發表你的看法吧

提交評論