從單體架構(gòu)向微服務(wù)架構(gòu)轉(zhuǎn)型,這9個問題需要搞明白

twt企業(yè)IT社區(qū)
twt社區(qū)
當(dāng)準(zhǔn)備要實施微服務(wù)的時候首要條件就是獲得高層的認(rèn)可,因為涉及到組織結(jié)構(gòu)的調(diào)整以及后續(xù)人力資源的增補,比如在單體應(yīng)用中其組織機構(gòu)包括開發(fā)部、測試部、運維部、DBA部,每個部門各司其職由高層統(tǒng)一指揮,看似很非常合理的組織結(jié)構(gòu),但是在項目或者迭代實際過程中會花費大量的時間去跨部門溝通,形成了孤島式功能團(tuán)隊。

使用微服務(wù)架構(gòu)方案能解決企業(yè)面臨的很多挑戰(zhàn),而且目前微服務(wù)架構(gòu)的框架都比較成熟,例如Spring cloud或者dubbo在各大互聯(lián)網(wǎng)平臺都有成功案例,但看似簡單的框架在實際開發(fā)過程中會面臨很多問題。本文整理了企業(yè)從單體架構(gòu)向微服務(wù)架構(gòu)轉(zhuǎn)型的中的設(shè)計難點問題。來自專家分享及社區(qū)交流。

整理者:潘志偉,某金融企業(yè),擁有十多年從業(yè)經(jīng)驗,精通微服務(wù)架構(gòu),精通大數(shù)據(jù),擁有億級用戶平臺架構(gòu)經(jīng)驗,萬級并發(fā)的API網(wǎng)關(guān)經(jīng)驗。還有以下專家分享:顧黃亮 蘇寧消費金融有限公司 技術(shù)總監(jiān)、zhuqibs Mcd 軟件開發(fā)工程師 等。

問題一:企業(yè)從單體架構(gòu)往微服務(wù)架構(gòu)轉(zhuǎn)型怎么啟動?

這是大家比較關(guān)注的問題,企業(yè)打算轉(zhuǎn)型微服務(wù),但是真正的實施后發(fā)現(xiàn)又很難。其實微服務(wù)架構(gòu)轉(zhuǎn)型不僅僅是一門技術(shù)活,更主要的的是組織結(jié)構(gòu)和技術(shù)轉(zhuǎn)型的結(jié)合,其中組織機構(gòu)轉(zhuǎn)型是起步的首要條件,包括統(tǒng)一思路和充分培訓(xùn)。

(1) 思想統(tǒng)一

當(dāng)準(zhǔn)備要實施微服務(wù)的時候首要條件就是獲得高層的認(rèn)可,因為涉及到組織結(jié)構(gòu)的調(diào)整以及后續(xù)人力資源的增補,比如在單體應(yīng)用中其組織機構(gòu)包括開發(fā)部、測試部、運維部、DBA部,每個部門各司其職由高層統(tǒng)一指揮,看似很非常合理的組織結(jié)構(gòu),但是在項目或者迭代實際過程中會花費大量的時間去跨部門溝通,形成了孤島式功能團(tuán)隊。

但是在實施微服務(wù)的時候,希望能協(xié)同配合快速交付,如果還是需要多次跨部門協(xié)調(diào)處理問題的話,那么“微”很難實現(xiàn)“微”的好處,微服務(wù)的團(tuán)隊?wèi)?yīng)該是如下所示,所以如果沒有高層參與那么組織架構(gòu)就不會調(diào)整。

(2) 充分培訓(xùn)

微服務(wù)開發(fā)關(guān)注點:微服務(wù)架構(gòu)的開發(fā)人員具備“精”、“氣”、“神”的特質(zhì),否則在后續(xù)發(fā)展階段一定會出現(xiàn)各種難題。“精”是指熟悉業(yè)務(wù),熟悉選型的開發(fā)框架,“氣”是指大家的思想認(rèn)知一致,能夠在一個頻道上對話,“神”是指需要了解其理論知識,明白為什么需要這樣而不是那樣。微服務(wù)在開發(fā)設(shè)計過程中需要關(guān)注以下點:

一份基準(zhǔn)代碼多份部署(deploy):程序部署需要做到和環(huán)境無關(guān),不需要改動任何一行代碼,如圖2-3

顯式聲明依賴關(guān)系:通過依賴清單 ,確切地聲明所有依賴項(例如MAVEN 依賴),新進(jìn)開發(fā)者簡化了環(huán)境配置流程“做產(chǎn)品”而不是“做項目”

在環(huán)境中存儲配置:所要求的代碼和配置嚴(yán)格分離,配置可以完全不一樣,但是代碼必須是一樣的,配置和代碼無關(guān)“去中心化”地治理技術(shù)

把后端服務(wù)當(dāng)作資源:后端服務(wù)是指程序運行所需要的通過網(wǎng)絡(luò)調(diào)用的各種服務(wù)如數(shù)據(jù)庫,MQ,緩存等。例如在不進(jìn)行任何代碼改動的情況下,將MySQL 數(shù)據(jù)庫換成第三方服務(wù)

嚴(yán)格分離構(gòu)建和運行:構(gòu)建階段是指將代碼倉庫轉(zhuǎn)化為可執(zhí)行包的過程,發(fā)布階段會將構(gòu)建的結(jié)果和當(dāng)前部署所需配置相結(jié)合,并能夠立刻在運行環(huán)境中投入使用,如回滾,運行階段是指針對選定的發(fā)布版本,在執(zhí)行環(huán)境中啟動一系列應(yīng)用程序進(jìn)程

無狀態(tài)進(jìn)程運行應(yīng)用:運行環(huán)境中,應(yīng)用程序通常是以一個和多個 進(jìn)程 運行的,任何需要持久化的數(shù)據(jù)都要存儲在 后端服務(wù)內(nèi),比如數(shù)據(jù)庫

問題二:微服務(wù)中所謂的服務(wù)到底如何拆分,服務(wù)拆分到什么粒度算好的服務(wù)?

在談服務(wù)拆分之前首先給服務(wù)做個定義:服務(wù)是分布式架構(gòu)下的基礎(chǔ)單元,包含了一組特定的功能。微服務(wù)拆分的方式?jīng)]有明確標(biāo)準(zhǔn),可謂說是千人千面,每個人對于服務(wù)拆分理解程度和拆分尺度都不一樣,有的團(tuán)隊按每個接口一個服務(wù)。一般來說我們在拆分的時候會結(jié)合理論知識和拆分原則來綜合考慮:

1) 微服務(wù)拆分的理論指導(dǎo)

- 團(tuán)隊規(guī)模大小

一般來說5-7個人一個小組比較合適,因為溝通效率和團(tuán)隊可擴展性都能得到保障。如果一個團(tuán)隊人數(shù)過少的話,本來應(yīng)該是多人開發(fā)的服務(wù)最后由1-2人來開發(fā),會導(dǎo)致本來設(shè)計好的服務(wù)拆分邏輯最后卻都合并在一個工程上做開發(fā)了,失去了微服務(wù)的意義。

- 項目交付周期

盡可能縮短項目交付周期短,把頻繁需求變更的功能盡量獨立成單獨的服務(wù),保證快速的迭代,還能滿足快速上線的需求,縮短了項目交付周期,同時還能做到隨時回滾,風(fēng)險變小,從而提高系統(tǒng)穩(wěn)定性。

- 變更影響范圍

一個業(yè)務(wù)迭代功能點,盡量不要分布到多個微服務(wù)中,盡量將關(guān)聯(lián)的實體對象存于一個微服務(wù),避免分布式事務(wù),比如把20%經(jīng)常變動的部分進(jìn)行抽離,80%不經(jīng)常變動的單獨部署和管理。

- 吞吐量大小

頻繁訪問,吞吐量大的服務(wù),盡量獨立微服務(wù),方便擴容, 能夠有效地提高資源利用率。

2) 服務(wù)拆分原則

- 高內(nèi)聚低耦合

高內(nèi)聚低耦合是軟件工程中的概念,在軟件設(shè)計中通常用耦合度和內(nèi)聚度作為衡量模塊獨立程度的標(biāo)準(zhǔn)。但是在微服務(wù)拆分中同樣適用,服務(wù)拆分的一個準(zhǔn)則是高內(nèi)聚低耦合。從功能粒度來看,高內(nèi)聚即每個服務(wù)盡可能只完成一件事(最大限度的聚合);低耦合即減少外部服務(wù)依賴,盡量避免服務(wù)再調(diào)用服務(wù)。從數(shù)據(jù)庫角度來看每個服務(wù)單獨使用獨立的數(shù)據(jù)庫,外部如果需要使用數(shù)據(jù)必須通過接口調(diào)用。

- 以業(yè)務(wù)模型切入

有了高內(nèi)聚低耦合的前提,那么可以通過業(yè)務(wù)線來做拆分,比如用戶、商品、訂單、評論都拆分為獨立的服務(wù)。把相關(guān)的業(yè)務(wù)都聚合在同一個服務(wù)中,這樣也避免了跨庫所帶來數(shù)據(jù)一致性的問題。有可能以業(yè)務(wù)模型切入的方式初期階段會比較粗,但是可以通過后續(xù)的迭代頻率和吞吐量大小的指標(biāo)再來衡量是否需要繼續(xù)拆分。

問題三:分布式事務(wù)怎么解決?

一旦完成服務(wù)拆分,就會涉及到分布式事務(wù),在談數(shù)據(jù)一致性要求的時候有2個非常重要的理論即CAP定理和Base理論:

CAP定理:C表示一致性,也就是所有用戶看到的數(shù)據(jù)是一樣的,A表示可用性,是指總能找到一個可用的數(shù)據(jù)副本,P表示分區(qū)容錯性,能夠容忍網(wǎng)絡(luò)中斷等故障。

BASE理論:BA指的是基本業(yè)務(wù)可用性,支持分區(qū)失敗,當(dāng)分布式系統(tǒng)出現(xiàn)故障的時候,允許損失一部分可用性,例如在電商大促的時候,對一些非核心鏈路的功能進(jìn)行降級處理來提高系統(tǒng)的可用性,S表示柔性狀態(tài),允許系統(tǒng)存在中間狀態(tài),這個中間狀態(tài)不會影響系統(tǒng)整體可用性。比如,數(shù)據(jù)庫讀寫分離,寫庫同步到讀庫(主庫同步到從庫)會有一個延時,E表示最終一致性,數(shù)據(jù)最終是一致的,例如主從同步雖然有短暫的數(shù)據(jù)不一致情況,但是最終數(shù)據(jù)還是一致的。

在實際中可以通過本地事務(wù)和發(fā)送MQ消息這種柔性事務(wù)方式來解決分布式事物所面臨的問題,既能保障服務(wù)的穩(wěn)定性又能保障調(diào)用效率的高效性,針對MQ可以使用Apache的RocketMQ所提供的事物消息和本地事物表結(jié)合。

問題四:微服務(wù)框架選型?

在選擇微服務(wù)架構(gòu)框架的時候,都在討論目前主流的微服務(wù)框架Dubbo以及Spring Cloud。Dubbo出生于阿里系,是阿里巴巴服務(wù)化治理的核心框架,并被廣泛應(yīng)用于中國各互聯(lián)網(wǎng)公司,只需要通過spring配置的方式即可完成服務(wù)化,對于應(yīng)用無入侵。設(shè)計的目的還是服務(wù)于自身的業(yè)務(wù)為主。Spring Cloud 是大名鼎鼎的 Spring 家族的產(chǎn)品, 專注于企業(yè)級開源框架的研發(fā)。Spring Cloud 自從發(fā)展到現(xiàn)在,仍然在不斷的高速發(fā)展,幾乎考慮了服務(wù)治理的方方面面,開發(fā)起來非常的便利和簡單。

這2種開發(fā)框架各巨頭互聯(lián)網(wǎng)公司都有深度使用,所以選擇任何一套框架都不會成為技術(shù)的瓶頸,關(guān)鍵還是看團(tuán)隊熟悉哪種框架,選擇最擅長的,而不是去跟風(fēng)。

問題五:微服務(wù)架構(gòu)下網(wǎng)關(guān)的必要性以及在網(wǎng)關(guān)下做限流、熔斷、降級等操作

在談到網(wǎng)關(guān)的時候,首先需要確認(rèn)下目前微服務(wù)的業(yè)務(wù)線有幾條,如果只有單一的業(yè)務(wù)線,那么有沒有網(wǎng)關(guān)意義不大。其實網(wǎng)關(guān)可以理解為一個反向路由,它屏蔽內(nèi)部細(xì)節(jié),為調(diào)用者提供統(tǒng)一入口,接收所有調(diào)用者請求,通過路由機制轉(zhuǎn)發(fā)到服務(wù)實例,同時網(wǎng)關(guān)也是“過濾器”集合,可以實現(xiàn)一系列與業(yè)務(wù)無關(guān)的橫切面功能,如安全認(rèn)證、限流熔斷、日志監(jiān)控。

- 網(wǎng)關(guān)工作原理

協(xié)議轉(zhuǎn)換 :將不同的協(xié)議轉(zhuǎn)換成“通用協(xié)議”,然后再將通用協(xié)議轉(zhuǎn)化成本地系統(tǒng)能夠識別的協(xié)議 ,例如把 http 協(xié)議統(tǒng)一轉(zhuǎn)換為 dubbo 協(xié)議。

鏈?zhǔn)教幚恚合牡谝粋€插件流入,從最后一個插件流出,每個步驟的插件對經(jīng)過的消息進(jìn)行處理,整個過程形成了一個鏈條。優(yōu)勢在于它將處理請求和處理步驟分開,每個處理的插件,只關(guān)心這個插件上需要做的處理操作,處理步驟和邏輯順序由“鏈”來完成。

異步請求:所有的請求都會通過 API 網(wǎng)關(guān)訪問應(yīng)用服務(wù),無論業(yè)務(wù)量如何變化,網(wǎng)關(guān)的吞吐量要保持穩(wěn)定狀態(tài)。假如把網(wǎng)關(guān)的請求看成一次 IO 操作的話,處理請求的線程,從接受請求開始直到服務(wù)端返回響應(yīng),都是阻塞狀態(tài)。操作系統(tǒng)所能承載的線程數(shù)是有限的,如果多個線程都處在這種狀態(tài),會導(dǎo)致系統(tǒng)緩慢。異步請求是指每個請求訪問網(wǎng)關(guān)的時候,會被包裝成一個事件, CPU 內(nèi)核會維持一個監(jiān)聽器,不斷輪詢請求事件,請求的線程不用一直等待數(shù)據(jù)的返回。它在請求完畢以后,就直接返回了。

- 網(wǎng)關(guān)限流、降級

網(wǎng)關(guān)的熔斷、降級是針對接口而言,可以選擇hystrix或者sentinel來做服務(wù)包括,一般來說需要具備以下設(shè)置:

設(shè)置錯誤率:可以設(shè)置每個服務(wù)錯誤率到達(dá)制定范圍后開始熔斷或降級;

具備人工干預(yù):可以人工手動干預(yù),主動觸發(fā)降級服務(wù);

設(shè)置時間窗口:可配置化來設(shè)置熔斷或者降級觸發(fā)的統(tǒng)計時間窗口;

具備主動告警:當(dāng)接口熔斷之后,需要主動觸發(fā)短信告知當(dāng)前熔斷的接口信息;

問題六:超時時間如何設(shè)置?

微服務(wù)中存在一次接口調(diào)用涉及到多個依賴服務(wù),每個依賴服務(wù)的耗時又不一樣,所以設(shè)置怎么樣的超時時間非常有講究,首先必須要有一刀切的態(tài)度,即每個接口的響應(yīng)時間不能超過閥值(比如1秒或者2秒),一方面提升用戶體驗,另外一方面也是增加系統(tǒng)的穩(wěn)定性。如果調(diào)用鏈路比較深的,則需要把非必要鏈路通過發(fā)送MQ消息的方式解耦,其次通過并行調(diào)用的方式來降低系統(tǒng)的響應(yīng)時間??偟膩碚f超時時間一般不會超過1秒,如何優(yōu)化到一秒,需要從系統(tǒng)的全局考慮,而不是只關(guān)注某一個點。

問題七:熔斷設(shè)計需要考慮哪些點?

在進(jìn)行服務(wù)化拆分之后,系統(tǒng)中原有的本地調(diào)用就會變成遠(yuǎn)程調(diào)用,這樣就引入了更多的復(fù)雜性。比如說服務(wù)A依賴于服務(wù)B,這個過程中可能會出現(xiàn)網(wǎng)絡(luò)抖動、網(wǎng)絡(luò)異常,服務(wù)B變得不可用或者響應(yīng)慢時,也會影響到A的服務(wù)性能,甚至可能會使得服務(wù)A占滿整個線程池,導(dǎo)致這個應(yīng)用上其它的服務(wù)也受影響,從而引發(fā)更嚴(yán)重的雪崩效應(yīng)。需要針對如下幾項做了個性化配置:

錯誤率:可以設(shè)置每個服務(wù)錯誤率到達(dá)制定范圍后開始熔斷或降級;

人工干預(yù):可以人工手動干預(yù),主動觸發(fā)降級服務(wù);

時間窗口:可配置化來設(shè)置熔斷或者降級觸發(fā)的統(tǒng)計時間窗口;

主動告警:當(dāng)接口熔斷之后,需要主動觸發(fā)短信告知當(dāng)前熔斷的接口信息;

目前市場上可選擇的產(chǎn)品例如:Hystrix或者Sentinel做服務(wù)熔斷和降級,這里推薦下 Sentinel ,不管是Dubbo還是SpringCloud 只要使用官方給定的依賴即可快速接入。

問題八:微服務(wù)架構(gòu)的業(yè)務(wù)系統(tǒng)眾多,那么數(shù)據(jù)的一致性怎么保障,數(shù)據(jù)的隔離機制如何實現(xiàn)等等?

當(dāng)前微服務(wù)架構(gòu)的業(yè)務(wù)系統(tǒng)越來越多,無論是做緩存場景,還是內(nèi)存數(shù)據(jù)庫場景,redis的使用非常普遍,但是每套業(yè)務(wù)系統(tǒng)都部署一套redis集群,相當(dāng)浪費資源,而且,考慮到同城和異地的信息系統(tǒng)建設(shè),費用也相當(dāng)之高,是否有機制可以類似中臺一樣,建立一個統(tǒng)一的redis平臺,提供各種場景的服務(wù)?那么數(shù)據(jù)的一致性怎么保障,數(shù)據(jù)的隔離機制如何實現(xiàn),性能如何評估等等?

答1:

(1)首先統(tǒng)一的redis中心是很“技術(shù)”, 因為你要一個強大的技術(shù)人員或團(tuán)隊;

(2)為了保證一致性,redis cluster讀取數(shù)據(jù)是從master上讀取數(shù)據(jù)的,這樣可以保證數(shù)據(jù)的一致性,當(dāng)然,性能也就差了;redis 主從模式,寫master節(jié)點,異步同步slave節(jié)點,讀從slave上讀取數(shù)據(jù),讀性能提高了,但一致性難以保證。這也就是門德爾不可能三角中的CAP原則中,保證P的同時,CA不可能同時滿足。

(3)當(dāng)然,也不是沒有解決方案,但redis作為一個緩存數(shù)據(jù)庫,并沒有做的這么復(fù)雜。現(xiàn)代分布式數(shù)據(jù)庫中,使用multi raft架構(gòu),最大限度的解決了這個問題----master是變化的,根據(jù)應(yīng)用的不同不斷的變化,同時讀永遠(yuǎn)從變化的master上寫入和讀取。

(4)redis也是有事物的,但只保證了一致性和隔離性,沒有原子性,一致性上面說過了。因為redis本質(zhì)上是單線程的,一個一個的去執(zhí)行命令。這種順序執(zhí)行,隔離性是有保證的。

答2:

首選糾正下你對微服務(wù)架構(gòu)的理解,在微服務(wù)架構(gòu)下,要求每個原子服務(wù)的數(shù)據(jù)庫、緩存都是相互獨立的,原因是當(dāng)服務(wù)所依賴的數(shù)據(jù)庫或者緩存有問題只影響它本身的服務(wù),不影響其他服務(wù),避免級聯(lián)問題。

其次關(guān)于你所擔(dān)心的資源浪費問題,可以考慮每個服務(wù)的調(diào)用量來設(shè)置不同的服務(wù)資源配置,目前不管是虛擬化使用docker還是云平臺所提供的redis服務(wù),都可以做到非常低的費用。

所以,想微服務(wù)穩(wěn)定,按標(biāo)準(zhǔn)的模式來,每種資源做隔離,而不是聚集在一起。

答3:

這個架構(gòu)有問題,統(tǒng)一的redis平臺或者是集群提供服務(wù),因此這個集群肯定是橫向擴容的,只能是cluster集群架構(gòu),所以從一致性、數(shù)據(jù)隔離、性能評估三個方面來分析:

1、一致性可以做到,cluster的特性可以保證數(shù)據(jù)一致性

2、數(shù)據(jù)隔離做不到, 單機支持多個數(shù)據(jù)庫,并且每個數(shù)據(jù)庫的數(shù)據(jù)是隔離的不能共享。cluster就沒有數(shù)據(jù)庫的概念,不支持多數(shù)據(jù)庫。

3、性能評估取決于承載業(yè)務(wù)的訪問量。

問題九:接口拆分多個微服務(wù)后帶來的接口響應(yīng)慢,怎么辦?

答1:

理論上不會有慢的現(xiàn)象,可從以下方面查 :

(1)使用skywalking或其他APM監(jiān)控軟件,定位問題,哪種服務(wù)慢;

(2)查看慢的服務(wù)所屬容器的cpu和內(nèi)存配置,以及在運行時的cpu和內(nèi)存負(fù)載;

(3)如果cpu和內(nèi)存占用很大,需要進(jìn)一步拆分應(yīng)用;

(4)檢查是否有串行的微服務(wù),此類微服務(wù)不適合拆分 。

答2:

這個問題應(yīng)該是拆分之前沒有做好規(guī)劃

1、拆分以后鏈路會變長,服務(wù)之間的通信、交互、處理會耗時間,這是正常的現(xiàn)象,但不至于造成性能陡降 ;

2、拆分原則有幾個,輕重、快慢、讀寫、多少 ;

3、如果慢,通過鏈路監(jiān)控看慢在哪里,然后進(jìn)行擴容、包括微服務(wù)組件擴容,優(yōu)化 。

答3:

一個應(yīng)用功能被拆分成多個服務(wù)之后,原本調(diào)用一個接口就能完成的功能如今變成需要調(diào)用多個服務(wù),如果按順序逐個調(diào)用的話,使用微服務(wù)改造后的接口會比原始接口響應(yīng)時間更長,因此要把原本串行調(diào)用的服務(wù)修改為并行調(diào)用。例如接口 A ,需要調(diào)用 S1 (耗時 200 毫秒), S2 (耗時 180 毫秒), S3 (耗時 320 毫秒)這 3 個接口,使用串行調(diào)用方式,那么接口 A 累計耗時 =SUM(S1+S2+S3)=700 毫秒。為了讓響應(yīng)時間更短,就需要把這些串行調(diào)用的方式更改為并行調(diào)用的方式,并行調(diào)用方式調(diào)用接口 A 累計耗時為 MAX(S1 , S2 , S3)=320 毫秒。可以使用 jdk8 提供的 CompletableFuture 方法來并行執(zhí)行。

THEEND

最新評論(評論僅代表用戶觀點)

更多
暫無評論