文獻地址:https://www.nginx.com/blog/introduction-to-microservices/
01 Introduce to Microservices
Monolithic Application vs Microservices
微服務(wù)可以從三個維度看:X維度-橫向復(fù)制擴展成多實例亭引,Y維度-按照業(yè)務(wù)功能切分成不同的微服務(wù)铣缠,Z維度-數(shù)據(jù)存儲分庫分表擴展(這個表述可能不大準確)
微服務(wù)的優(yōu)勢:主要從開發(fā)棒仍、部署舱痘、擴展派殷、運維的角度分析
1)把一個很大的應(yīng)用拆分成多個微服務(wù),微服務(wù)之間通過RPC或者消息隊列相互通信坚踩。這樣微服務(wù)更容易開發(fā)和維護
2)一個大的應(yīng)用基本只能使用一套技術(shù)框架荡灾,拆分成微服務(wù)后,不同的微服務(wù)之間有了可以自由選擇技術(shù)框架的可能性
3)微服務(wù)之間相互獨立部署
4)單個微服務(wù)可以獨立的擴展
微服務(wù)的缺點:
1)微服務(wù)瞬铸,那一個應(yīng)用到底拆分成幾個微服務(wù)合適呢批幌,這是值得深思的一個問題
2)微服務(wù)之間通過RPC或者消息隊列通信,通信的可靠性和消耗是一個值得思考的問題
3)微服務(wù)將數(shù)據(jù)庫拆分嗓节,那么跨微服務(wù)跨庫操作時就很難保證事務(wù)的強一致性荧缘,只能追求最終一致性了
4)測試會更加復(fù)雜一點,當測試涉及微服務(wù)之間的調(diào)用時拦宣,相互依賴的微服務(wù)都必須啟動起來
5)當?shù)枨笊婕暗蕉鄠€微服務(wù)時截粗,每個微服務(wù)都要更新,重新部署啟動
6)部署微服務(wù)也變得更加復(fù)雜鸵隧,包括監(jiān)控绸罗、部署、擴展豆瘫、拆分等等
總結(jié):當業(yè)務(wù)很簡單的時候珊蟀,微服務(wù)的必要性沒有那么大;當業(yè)務(wù)復(fù)雜的時候外驱,微服務(wù)就顯得很有必要了育灸;所以隨著業(yè)務(wù)的發(fā)展系統(tǒng)越來越復(fù)雜腻窒,需要提前考量引入微服務(wù)
02 Building Microservices:Using an API Gateway
當外部http請求微服務(wù)時,如何訪問到對應(yīng)的微服務(wù)系統(tǒng)磅崭?有以下兩種方式:
1)每個微服務(wù)都暴露一個域名訪問地址給外部定页,調(diào)用時采用:http://serviceName.api.company.name
這種方式顯然不大合理。第一绽诚,每次新增一個微服務(wù)都要新增一個域名訪問地址典徊;第二,當將一個微服務(wù)拆分或者多個微服務(wù)合并的時候恩够,都需要更改或者新增域名卒落,相應(yīng)的客戶端調(diào)用的代碼也需要修改
2)采用api網(wǎng)關(guān),統(tǒng)一一個入口蜂桶,由api根據(jù)前端訪問地址決定訪問哪個微服務(wù)儡毕,以及如何實現(xiàn)同一個微服務(wù)之間的負載均衡,還有根據(jù)規(guī)則如何路由到同一個微服務(wù)的不同環(huán)境中扑媚。
采用api gateway的優(yōu)缺點:
優(yōu)點:統(tǒng)一入口腰湾,方便管理,客戶端只直接跟api網(wǎng)關(guān)通信
缺點:引入api網(wǎng)關(guān)疆股,就多了一個服務(wù)费坊,api網(wǎng)關(guān)服務(wù)的流量將是巨大的,對于api網(wǎng)關(guān)服務(wù)自身的性能和穩(wěn)定性要求是很高的旬痹,一旦網(wǎng)關(guān)出問題附井,會導(dǎo)致同一個大系統(tǒng)下面的微服務(wù)都不可訪問。
實現(xiàn)一個api網(wǎng)關(guān)的要素:
1)性能和擴展性
2)采用reactor設(shè)計模式两残,比如java nio的selector(reactor模式還要好好理解理解)
service invocation(服務(wù)調(diào)用)
微服務(wù)之間通信:異步:消息隊列永毅,如kafka;同步:rpc/http
service discovery(服務(wù)發(fā)現(xiàn))
查詢服務(wù)注冊表,得到每個微服務(wù)-版本號-對應(yīng)部署ip機器和端口號列表
handling partial failures(能處理部分失敗)
降級等處理
03 Building Microservices: Inter-Process Communication in a Microservices Architecture
主要講微服務(wù)之間是如何通信的人弓,通信協(xié)議采用什么方式沼死?
同步采用http/rest請求,異步通過消息隊列通信崔赌;如果是一對多則采用消息發(fā)布訂閱模式
04 Service Discovery in a Microservices Architecture
微服務(wù)中的服務(wù)發(fā)現(xiàn)-實際項目中主要用到的是zookeeper
為什么微服務(wù)要使用服務(wù)發(fā)現(xiàn)意蛀?
同一個微服務(wù)的不同實例是動態(tài)注冊的,注冊之后可能因為故障等原因而不可用峰鄙,這就要求服務(wù)發(fā)現(xiàn)及時去發(fā)現(xiàn)并更新最新可用的實例浸间,然后重新去做負載均衡等操作
服務(wù)發(fā)現(xiàn)的兩種模式:Client-Side Discovery vs Server-Side Discovery
Client-Side Discovery
每個微服務(wù)都有一個服務(wù)發(fā)現(xiàn)客戶端,如下圖的Registry Client.
以單個微服務(wù)為例吟榴,微服務(wù)會注冊到服務(wù)注冊中心,服務(wù)注冊中心會記錄該微服務(wù)對應(yīng)實例的ip和端口囊扳,然后通過心跳的機制定期檢測服務(wù)器是否存活并定期更新微服務(wù)對應(yīng)的實例ip列表吩翻。
對應(yīng)的Registry Client只需要去注冊中心讀取實例ip列表即可兜看,然后做負載均衡。
相當于每個微服務(wù)都需要一個前置的Registry Client.
Server-Side Discovery
請求統(tǒng)一通過一個入口狭瞎,由一個load balancer 服務(wù)去統(tǒng)一從注冊中心獲取每個微服務(wù)的實例ip列表细移,然后決定如何負載均衡,nginx+就可以作為Server-Side Discovery(這個就是網(wǎng)關(guān)可以做的事)
The Service Registry-可以理解為一個存儲微服務(wù)實例列表的數(shù)據(jù)庫
服務(wù)注冊中心:微服務(wù)注冊到服務(wù)注冊中心熊锭,由服務(wù)注冊中心保存微服務(wù)的實例ip列表弧轧,通過心跳實時更新微服務(wù)實例ip列表
哪些可以作為服務(wù)注冊中心:
- Netflix Eureka
- etcd:Kubernetes and Cloud Foundry
- consul
- zookeeper
Service Registry Options
-
The Self?Registration Pattern: 微服務(wù)自己注冊到注冊中心,自己取消注冊到注冊中心碗殷;當然如果有必要可以定期發(fā)送心跳給注冊中心精绎,防止過期。有點Client-Side Discovery的意思
The Self?Registration Pattern.png -
The Third?Party Registration Pattern:采用第三方統(tǒng)一注冊锌妻、取消注冊服務(wù)代乃,當某個微服務(wù)有新實例時,這個第三方服務(wù)會自動發(fā)現(xiàn)仿粹,當某個微服務(wù)實例不可用時通過healthcheck檢測到搁吓,然后可以取消該注冊服務(wù)。
The Third?Party Registration Pattern.png
zookeeper是通過心跳來取消注冊的吭历,當心跳停止一段時間后會從列表中自動刪除對應(yīng)的微服務(wù)實例
05 Event-Driven Data Management for Microservices
- 分布式數(shù)據(jù)管理問題:當一個請求跨微服務(wù)訪問多個數(shù)據(jù)庫時堕仔,由于一個微服務(wù)無法直接訪問另外一個微服務(wù)的數(shù)據(jù)庫,只能通過api接口訪問晌区,由于跨數(shù)據(jù)庫操作就不能保證ACID了贮预。
解決辦法:事件驅(qū)動架構(gòu)方式
大致的思想是將存在跨數(shù)據(jù)庫的訪問拆分成一系列事件流,一步一步往下執(zhí)行(一個一個數(shù)據(jù)庫操作往下執(zhí)行)契讲,當某個步驟失敗時仿吞,通過補償?shù)姆绞交貪L之前提交成功的操作(回滾也是可能存在失敗的),這種方式是以最終一致性為目標的捡偏,所謂的BASE而不是ACID
- 事件驅(qū)動如何保證原子性:插入一條數(shù)據(jù)到數(shù)據(jù)庫+發(fā)布一個事件唤冈,可能存在插入數(shù)據(jù)庫成功但是發(fā)布事件失敗,導(dǎo)致不一致银伟。
解決辦法1:新增一張本地事件表你虹,插入一條數(shù)據(jù)+插入一條事件記錄在同一個本地事務(wù)中,然后開啟另外一個線程從事件表中讀取事件記錄并發(fā)布彤避,記得標記為已發(fā)布傅物。當讀取事件發(fā)布失敗可以重試,比之前要改進很多
解決辦法2:通過讀取數(shù)據(jù)庫的transaction log, 根據(jù)插入的數(shù)據(jù)記錄異步發(fā)布對應(yīng)的事件
解決辦法3:采用一個事件保存源琉预,每次都將事件追加董饰,客戶端去訂閱事件源消費即可。
06 Choosing a Microservices Deployment Strategy
微服務(wù)部署方式
方式1:Multiple Service Instances per Host Pattern
不同微服務(wù)部署在同一臺物理機或者虛擬機上,通過不同的端口號區(qū)分卒暂;不同微服務(wù)之間不隔離啄栓,易相互影響產(chǎn)生問題-
方式2:Service Instance per Host Pattern
細分為兩種方式:- Service Instance per Virtual Machine Pattern:每個虛擬機部署一個微服務(wù)
- Service Instance per Container Pattern:每個容器部署一個微服務(wù)
這樣不同微服務(wù)之間資源是隔離的,可以指定每個微服務(wù)可用的CPU也祠、內(nèi)存等資源
方式3:Serverless Deployment
無服務(wù)部署昙楚,如AWS Lambda, 不是太了解。诈嘿。堪旧。
07 Refactoring a Monolith into Microservices
如何將一個大的應(yīng)用拆分成微服務(wù)?
- 第一步:停止繼續(xù)將應(yīng)用代碼變得更多更復(fù)雜
- 第二步:前后端分離
- 第三步:抽取module成獨立的微服務(wù)奖亚,根據(jù)業(yè)務(wù)功能淳梦、資源消耗等方面考慮