微服務(wù)是一個這些年才流行起來的軟件架構(gòu),這篇文章主要是基于Martin Fowler的那篇文章的學習筆記以及一些心得办素。然后嘗試用于工作中的軟件架構(gòu)演進。
1. 基于服務(wù)的組件化: 模塊的劃分
- 首先這里定義一下組件(component)
- 定義:是一個軟件單元祸穷,可以獨立替換性穿,也可以獨立升級;
- 微服務(wù)和LIB的區(qū)別雷滚,
- 首先微服務(wù)也會使用LIB
- LIB庫(libraries)都會被link到程序中需曾,并且在進行內(nèi)存中的函數(shù)調(diào)用;
- 而服務(wù)(services)是一個進程外的概念祈远,通過web服務(wù)請求或者遠端調(diào)用來訪問呆万;
- 我們這里把服務(wù)(services)當作一個組件(component),是因為服務(wù)是可以獨立部署的车份,而library庫則不可以谋减。
- 如果一個應(yīng)用程序是由多個LIB庫組成的,那么任何一個LIB庫的修改都會導致整個app重新部署扫沼;
- 如果一個應(yīng)用程序是有多個服務(wù)構(gòu)成的出爹,那么任意一個服務(wù)的更新,只要重新部署這個服務(wù)就好(僅限于服務(wù)間的接口不發(fā)生變更)缎除;
- 微服務(wù)的缺陷
- 遠程調(diào)用更加消耗資源严就;
- 遠程API的顆粒度更粗,更不友好器罐;
2. 圍繞業(yè)務(wù)能力(Business Capability)進行組織: 開發(fā)團隊的組織模式
舉個例子梢为,我們考慮實現(xiàn)一個應(yīng)用程序(或者網(wǎng)站),通常我們會從技術(shù)層面進行拆分
- 用戶界面 -> 好的轰坊,交給UI 團隊了铸董;
- 業(yè)務(wù)邏輯 -> 交給邏輯團隊
-
數(shù)據(jù)庫 -> 交給數(shù)據(jù)庫團隊
這個時候就會出現(xiàn)一個現(xiàn)象,任何一個小的改動(feature)都會涉及所有的團隊衰倦;需要把這個功能再分解到各個團隊袒炉,團隊之間在進行溝通旁理,討論接口方案樊零,而后各自實現(xiàn),最終一致提交測試,最終交付驻襟。
微服務(wù)則不一樣:基于業(yè)務(wù)能力(business capacity)來對服務(wù)進行劃分和組織
每一個服務(wù)都可以使用不同的技術(shù)棧來實現(xiàn)
- UI
- 持久存儲
-
以及對外協(xié)作
這種情況下對于團隊來說是跨職能的夺艰,需要各種各樣的技術(shù)(Feature Team)
- 用戶體驗
- 數(shù)據(jù)庫
- 項目管理
3. 是產(chǎn)品(Product)不是項目(Program):項目管理的模式
傳統(tǒng)的項目模式是,我們的目標是完成一個軟件的開發(fā)沉衣,然后就提交給維護的組郁副;項目結(jié)束,項目組解散豌习。
微服務(wù)的目標是避免這種模式
- 每個team應(yīng)該負責整個產(chǎn)品的生命周期
- 開發(fā)者需要接觸他們軟件的生產(chǎn)環(huán)境存谎,增加與用戶的聯(lián)系
同樣的方法也能用在單體應(yīng)用程序上,但是服務(wù)的顆粒度更小肥隆,使得它更容易在開發(fā)者和用戶之間建立個人關(guān)系既荚。
4. 智能端點和啞管道:服務(wù)之間的交互原則
當我們在不同的進程間構(gòu)建通信體系的時候,我們通常會把智能強壓進通信機制本身栋艳。
微服務(wù)則主張另一種方法恰聘,智能端點(端點負責更多的處理)和啞管道(管道功能單一通用)
基于微服務(wù)而構(gòu)建的應(yīng)用程序會盡可能的解耦和內(nèi)聚。
- Endpoint要是智能的吸占,可以處理和過濾消息
- 管道是簡單晴叨,只是負責轉(zhuǎn)發(fā)消息
微服務(wù)團隊使用的規(guī)則和協(xié)議正好就是設(shè)計萬維網(wǎng)的規(guī)則(更擴展一步說,就是Unix的設(shè)計規(guī)則)矾屯。
第二種方法是基于輕量的消息總線兼蕊,比如說RabbitMQ或者ZeroMQ
- 只是提供一個可靠的異步通信結(jié)構(gòu)(只做消息路由,所以稱為啞的)
- 只能依舊存在于Endpoint中件蚕,負責消息的生成和消費
單體應(yīng)用程序遍略,不同的組件都運行在同一個進程中;他們之間的通信都是通過函數(shù)調(diào)用的方式進行骤坐;
拆解成微服務(wù)后绪杏,最大的一個變化是通信方式的變化
- 最簡單的方法是,從內(nèi)存函數(shù)調(diào)用轉(zhuǎn)變成RPC纽绍;但是會導致通信頻繁性能不佳蕾久;
- 所以,你需要變更這種細顆粒度的通信到更粗顆粒度的通信方式
5. 去中心化治理:更高的自由度
5.1. 你可以使用各種你喜歡的技術(shù)棧來實現(xiàn)新功能了
集中治理的一個后果就是單一的技術(shù)平臺標準化發(fā)展趨勢拌夏。
你可能只會用一種語言去實現(xiàn)這種單一的應(yīng)用程序僧著。
單體的組件分裂成服務(wù)之后
- 你可以用node.js去實現(xiàn)一個簡單的報告頁面
- 也可以用C++去實現(xiàn)一個接近實時處理的組件
- 等等
5.2 去中心化的數(shù)據(jù)管理
去中心化的數(shù)據(jù)管理表現(xiàn)在很多不同方面。
最抽象的來說的話障簿,就是不同的系統(tǒng)里面對于世界的概念模型也是完全不一致的盹愚。比如說一個大公司里面,銷售眼里的客戶和技術(shù)支持里面客戶就是不一樣的站故。
這個問題(差異的世界觀皆怕?)也常見于應(yīng)用程序之間毅舆,但是它也會出現(xiàn)在應(yīng)用程序內(nèi),尤其是一個應(yīng)用程序被分割成了多個單獨的組件愈腾。
一種非常有用的思維方式是領(lǐng)域卻動的設(shè)計(Domain-Driven Design)憋活。DDD這種設(shè)計方式會把一個復(fù)雜的領(lǐng)域劃分成多個有界的上下文,并且建立出他們之間的映射關(guān)系虱黄。這種流程對于單體應(yīng)用以及微服務(wù)都是有效的悦即。
和概念模型的去中心化決策一樣,微服務(wù)也會使用去中心化數(shù)據(jù)存儲決策橱乱。單體應(yīng)用更喜歡單一的邏輯數(shù)據(jù)庫做數(shù)據(jù)存儲辜梳,而企業(yè)也更傾向于多個應(yīng)用程序共用一個數(shù)據(jù)庫(有時候也是由于license所決定的)。
微服務(wù)則允許每個服務(wù)管理自己的數(shù)據(jù)庫泳叠,可以使用相同的數(shù)據(jù)庫技術(shù)的不同實體冗美,也可以使用不同的數(shù)據(jù)庫技術(shù)。
這就是所謂的混合持久化(Polyglot Persistence)
對于微服務(wù)之間的數(shù)據(jù)析二,去中心化的責任(會有不同的服務(wù)組件影響這些數(shù)據(jù))對于管理升級是有影響的粉洼。處理更新最常用的方法是用事物來保證一致性。
NOTE: 使用事務(wù)有助于一致性叶摄,但是會帶來明顯的臨時耦合属韧。而分布式事務(wù)是非常難以實現(xiàn)的,所以微服務(wù)架構(gòu)強調(diào)服務(wù)間的無事務(wù)協(xié)作蛤吓。 這里需要有個明確的認知宵喂,就是所謂的一致性只是在最終達到一致,或者是通過一些補償?shù)牟僮鱽磉M行處理.
5.3 允許試錯
對于很多個開發(fā)團隊來說会傲,這樣的非一致性管理的方法是一種新的挑戰(zhàn)锅棕,然而這又是一種匹配日常業(yè)務(wù)(business)時間的處理方式。日常的業(yè)務(wù)會處理很多的不一致性以達到快速響應(yīng)的目的淌山。我們允許試錯裸燎,允許返工,并以此為代價(犧牲一致性)來保證生意不會丟泼疑。
6. 基礎(chǔ)設(shè)施的自動化:讓你的生活更加簡單
其實微服務(wù)的自動化是在先前的持續(xù)集成以及持續(xù)交付的基礎(chǔ)上發(fā)展而來的德绿。
自動化的編譯,集成測試退渗,性能測試移稳,以及生產(chǎn)環(huán)境的部署。
幾個關(guān)鍵點
- 自動化測試
- 自動化部署
自動化的引入讓“做正確的事情”這件事兒變得更加容易了会油。
7. 為失敗設(shè)計: 設(shè)計模塊的前提就是要容忍各種失敗
7.1 任何時候都有可能失敗
使用服務(wù)作為組件的一個后果就是个粱,應(yīng)用程序需要設(shè)計成他們能容忍某些服務(wù)的失敗,任何服務(wù)的調(diào)用都可能由于提供服務(wù)方的不工作而失敗翻翩,調(diào)用端需要能容忍這些失敗都许。
這個是相對于單體應(yīng)用的一個劣勢稻薇,你需要考慮各種可能失敗的場景以及對于用戶體驗的影響。
由于服務(wù)會在任何時候都會失敗梭稚,所以需要盡快的檢測到失敗,并且如果可能的話絮吵,要能自動恢復(fù)服務(wù)弧烤。
7.2. 所以我們需要實時監(jiān)控
微服務(wù)應(yīng)用程序增強了應(yīng)用程序的實時監(jiān)控,不僅檢查軟件架構(gòu)相關(guān)的元素(比如說一秒鐘多少次數(shù)據(jù)庫查詢請求)蹬敲,還要業(yè)務(wù)相關(guān)的指標(比如說每分鐘收到的訂單次數(shù))
這種監(jiān)控對于微服務(wù)架構(gòu)尤為重要暇昂,因為微服務(wù)偏好編排和時間協(xié)作,但是這個會導致突發(fā)行為的發(fā)生伴嗡。監(jiān)測對于快速發(fā)現(xiàn)不良的突發(fā)行為至關(guān)重要
NOTE: 同步調(diào)用被認為是有害的
8. 進化式設(shè)計:讓重構(gòu)變得更加簡單
8.1. 學會控制變化
微服務(wù)的從業(yè)者急波,通常有進化式設(shè)計的背景,并且把服務(wù)的分解看成是一個進一步的工具來保證開發(fā)者可以控制應(yīng)用程序的變化但是卻又并不會減緩應(yīng)用程序的變化瘪校。
控制變化并不意味著就是減少變化澄暮。使用正確的態(tài)度和工具,你可以迅速頻繁的并且可控的去修改軟件阱扬。 (持續(xù)的重構(gòu)泣懊,模塊越小,重構(gòu)的負擔就越輕麻惶,就越加可控)
不管什么時候你去嘗試把一個系統(tǒng)變成多個組件车伞,你都會面臨這樣的決策砂碉,怎么切分。這個時候切分的原則是什么呢?
- 組件的關(guān)鍵特性是要糊,獨立的替換,獨立的升級刑然;這就意味著如果我們重寫了一個組件缔刹,那么我們不會影響它的協(xié)作方。
8.2. 記住杀迹,任何一個服務(wù)都是有可能會被廢棄的
很多微服務(wù)組織會明確的表明這里面的一些組件有可能被廢棄梅誓,以這個為前提來進行劃分組件
Guardian這個網(wǎng)站就是一個最初設(shè)計成單體應(yīng)用,但是最終演進到微服務(wù)架構(gòu)的一個很好的例子佛南。這個網(wǎng)站的核心依舊是個單體應(yīng)用梗掰,但是他們非常樂于通過添加微服務(wù)組件的方式來添加新的功能,而這些微服務(wù)組件使用的還是單體應(yīng)用的API嗅回。這種方法對于天然臨時的特性特別方便及穗,比如說處理體育賽事的專題頁面,網(wǎng)站的這一部分可以使用快速開發(fā)語言去構(gòu)建绵载,賽事結(jié)束后立即丟棄埂陆。 --> 模塊的可丟棄性
8.3. 更一般的原則苛白,服務(wù)是可替代的
模塊設(shè)計過程中,強調(diào)可替代性是一個更加一般的原則焚虱。
- 你應(yīng)該要想辦法把會同一時間發(fā)生變更的內(nèi)容(功能)放到同一個模塊中去
- 而這個時候不怎么變化的那些內(nèi)容(功能)购裙,我們應(yīng)該放到別的組件中去
- 如果你發(fā)現(xiàn)你重復(fù)的在一起修改兩個服務(wù),那你就有可能要把他們合并到一起去了