Medium 架构实践:避免微服务综合症
生活随笔
收集整理的這篇文章主要介紹了
Medium 架构实践:避免微服务综合症
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
\u003cp\u003e微服務(wù)架構(gòu)的目標(biāo)是幫助工程師團(tuán)隊(duì)更快、更安全、更高質(zhì)量地交付產(chǎn)品。解耦服務(wù)使團(tuán)隊(duì)能夠快速迭代,并盡可能降低對(duì)系統(tǒng)其余部分的影響。\u003c/p\u003e\n\u003cp\u003e在Medium,我們的技術(shù)棧始于2012年的單體Node.js 應(yīng)用程序。我們已經(jīng)構(gòu)建了幾個(gè)衛(wèi)星通訊服務(wù),但還沒(méi)有系統(tǒng)地制定一個(gè)采用微服務(wù)架構(gòu)的策略。隨著系統(tǒng)變得越來(lái)越復(fù)雜并且團(tuán)隊(duì)不斷發(fā)展,我們?cè)?018年初轉(zhuǎn)向了微服務(wù)架構(gòu)。在這篇文章中,我們希望分享關(guān)于如何有效實(shí)現(xiàn)微服務(wù)架構(gòu)并避免微服務(wù)綜合癥的經(jīng)驗(yàn)。\u003c/p\u003e\n\u003ch2\u003e什么是微服務(wù)架構(gòu)?\u003c/h2\u003e\n\u003cp\u003e首先,讓我們花點(diǎn)時(shí)間思考微服務(wù)架構(gòu)是什么,不是什么?!拔⒎?wù)”是那些超負(fù)荷和混亂的軟件工程的趨勢(shì)之一。在Medium 我們認(rèn)為:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e在微服務(wù)架構(gòu)中,多個(gè)松耦合的服務(wù)協(xié)同工作。每項(xiàng)服務(wù)都專注于一個(gè)目的,并對(duì)相關(guān)行為和數(shù)據(jù)高內(nèi)聚。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e該定義包括三個(gè)微服務(wù)設(shè)計(jì)原則:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e單一目的 - 每項(xiàng)服務(wù)應(yīng)專注于一個(gè)目的并做好。\u003c/li\u003e\n\u003cli\u003e松耦合 - 服務(wù)彼此間沒(méi)有太多聯(lián)系。更改一項(xiàng)服務(wù)時(shí)不應(yīng)要求更改其他服務(wù)。應(yīng)僅通過(guò)公共服務(wù)接口進(jìn)行服務(wù)之間的通信。\u003c/li\u003e\n\u003cli\u003e高內(nèi)聚 - 每個(gè)服務(wù)將所有相關(guān)行為和數(shù)據(jù)封裝在一起。如果我們需要構(gòu)建新功能,所有更改僅限于一個(gè)服務(wù)。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg src=\"https://static.geekbang.org/infoq/5c342b69726b6.png?imageView2/0/w/800\" alt=\"image\" /\u003e\u003c/p\u003e\n\u003cp\u003e當(dāng)我們對(duì)微服務(wù)建模時(shí),我們應(yīng)該遵守這三個(gè)設(shè)計(jì)原則。這是實(shí)現(xiàn)微服務(wù)架構(gòu)全部潛力的唯一途徑。缺少任何一個(gè)都會(huì)成為反模式。\u003c/p\u003e\n\u003cp\u003e缺少單一目的,每個(gè)微服務(wù)最終會(huì)做太多事情,成長(zhǎng)為多個(gè)“單體”服務(wù)。我們不會(huì)從微服務(wù)架構(gòu)中獲得全部好處,還要支付運(yùn)營(yíng)成本。\u003c/p\u003e\n\u003cp\u003e缺少松耦合,對(duì)一項(xiàng)服務(wù)的更改會(huì)影響其他服務(wù),因此我們無(wú)法快速安全地發(fā)布更改,這是微服務(wù)架構(gòu)的核心優(yōu)勢(shì)。更重要的是,緊耦合引起的問(wèn)題可能是災(zāi)難性的,例如數(shù)據(jù)不一致甚至數(shù)據(jù)丟失。\u003c/p\u003e\n\u003cp\u003e缺少高內(nèi)聚,我們將最終得到一個(gè)分布式的單體系統(tǒng),一組混亂的服務(wù),必須同時(shí)進(jìn)行更改和部署才能構(gòu)建單一功能。由于多個(gè)服務(wù)協(xié)調(diào)的復(fù)雜性和成本(有時(shí)跨多個(gè)團(tuán)隊(duì)),分布式單體系統(tǒng)通常比集中式單體系統(tǒng)差得多。\u003c/p\u003e\n\u003cp\u003e與此同時(shí),了解微服務(wù)不是什么也很重要:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e微服務(wù)不是代碼行數(shù)少或處理“微”任務(wù)的服務(wù)。這種誤解來(lái)自“ 微服務(wù)” 這個(gè)名稱。微服務(wù)架構(gòu)的目標(biāo)不是擁有盡可能多的小型服務(wù)。只要符合上述三項(xiàng)原則,服務(wù)也能夠是復(fù)雜而重要的。\u003c/li\u003e\n\u003cli\u003e微服務(wù)并不總是由新技術(shù)構(gòu)建。盡管微服務(wù)架構(gòu)能夠讓團(tuán)隊(duì)更輕松地驗(yàn)證新技術(shù),但它并不是微服務(wù)架構(gòu)的主要目標(biāo)。只要團(tuán)隊(duì)從分離的服務(wù)中受益,就可以使用完全相同的技術(shù)棧構(gòu)建新服務(wù)。\u003c/li\u003e\n\u003cli\u003e微服務(wù)不是必須從頭開始構(gòu)建的服務(wù)。如果你已經(jīng)擁有一個(gè)架構(gòu)良好的單體應(yīng)用程序,請(qǐng)避免養(yǎng)成從頭開始構(gòu)建每個(gè)新服務(wù)的習(xí)慣。也可以直接從單體服務(wù)中直接提取邏輯。同樣,應(yīng)該仍然遵循上述三個(gè)原則。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e為什么是現(xiàn)在?\u003c/h2\u003e\n\u003cp\u003e在Medium,在做出重大產(chǎn)品或工程決策時(shí),我們總是會(huì)問(wèn)“為什么是現(xiàn)在?”這個(gè)問(wèn)題?!盀槭裁?#xff1f;”是一個(gè)顯而易見的問(wèn)題,但它假設(shè)我們擁有無(wú)限的人、時(shí)間和資源,這是一個(gè)危險(xiǎn)的假設(shè)。當(dāng)你想到“為什么是現(xiàn)在?”時(shí),就突然有了更多的限制,對(duì)當(dāng)前工作的影響、機(jī)會(huì)成本、分心的開銷等等。這個(gè)問(wèn)題有助于我們更好地考慮優(yōu)先級(jí)。\u003c/p\u003e\n\u003cp\u003e為什么我們需要現(xiàn)在采用微服務(wù),是因?yàn)槲覀兊腘ode.js 單體應(yīng)用在多個(gè)方面成為了瓶頸。\u003c/p\u003e\n\u003cp\u003e首先,最緊迫和最重要的瓶頸是性能。某些計(jì)算繁重且I/O繁重的任務(wù)不適合Node.js。我們一直在逐步改進(jìn)這個(gè)單體應(yīng)用程序,但事實(shí)證明收效甚微。它糟糕的性能使我們無(wú)法提供更好的產(chǎn)品,雖然應(yīng)用程序不會(huì)變得更慢。\u003c/p\u003e\n\u003cp\u003e其次,另一個(gè)重要且有點(diǎn)緊迫的瓶頸是單體應(yīng)用程序會(huì)降低產(chǎn)品開發(fā)速度。由于所有工程師都在單個(gè)應(yīng)用程序中構(gòu)建功能,因此它們通常是緊密耦合的。我們無(wú)法對(duì)系統(tǒng)某部分進(jìn)行靈活地更改,因?yàn)樗部赡苡绊懫渌糠帧N覀円埠ε伦龀鲋卮蟾淖?#xff0c;因?yàn)橛绊懱?#xff0c;有時(shí)難以預(yù)測(cè)。整個(gè)應(yīng)用程序作為一個(gè)整體進(jìn)行部署,如果由于一次錯(cuò)誤提交導(dǎo)致部署停滯,所有其他更改(即使它們完全正常工作)也無(wú)法完成。相比之下,微服務(wù)架構(gòu)可以使團(tuán)隊(duì)更快地交付、學(xué)習(xí)和迭代。他們可以專注于自己正在構(gòu)建的功能,這些功能與復(fù)雜系統(tǒng)的其余部分是分離的。變更可以更快地進(jìn)入生產(chǎn)。他們可以靈活安全地嘗試重大變革。\u003c/p\u003e\n\u003cp\u003e在我們新的微服務(wù)架構(gòu)中,變更會(huì)在一小時(shí)內(nèi)發(fā)布到生產(chǎn)環(huán)境中,工程師不必?fù)?dān)心它會(huì)影響系統(tǒng)的其他部分。團(tuán)隊(duì)還探索了在開發(fā)中安全使用生產(chǎn)數(shù)據(jù)的方法,在這么多年以來(lái)這件事就像是白日夢(mèng)。隨著我們的工程團(tuán)隊(duì)的發(fā)展,所有這些都非常重要。\u003c/p\u003e\n\u003cp\u003e第三,單體應(yīng)用程序很難為特定任務(wù)擴(kuò)展系統(tǒng),也不能為不同類型的任務(wù)進(jìn)行資源隔離。對(duì)于消耗大量資源的任務(wù),單體應(yīng)用程序只能對(duì)整個(gè)系統(tǒng)進(jìn)行伸縮,這意味著對(duì)于其他的簡(jiǎn)單任務(wù)存在超配。為了緩解這些問(wèn)題,我們對(duì)不同類型的請(qǐng)求進(jìn)行分片,以分離Node.js 進(jìn)程。在一定程度上這起到了些作用,但伸縮依然受限,因?yàn)檫@些單體服務(wù)的微型版本是緊耦合的。\u003c/p\u003e\n\u003cp\u003e最后,一個(gè)重要且即將成為緊迫的瓶頸是它阻礙我們嘗試新技術(shù)。微服務(wù)架構(gòu)的一個(gè)主要優(yōu)點(diǎn)是每個(gè)服務(wù)都可以使用不同的技術(shù)棧構(gòu)建,并與不同的技術(shù)集成。這使我們能夠選擇最適合工作的工具,更重要的是,這樣可以快速安全地完成任務(wù)。\u003c/p\u003e\n\u003ch2\u003e微服務(wù)策略\u003c/h2\u003e\n\u003cp\u003e采用微服務(wù)架構(gòu)并非易事。它可能會(huì)出錯(cuò),使得實(shí)際上損害工程生產(chǎn)力。在本節(jié)中,我們將分享早期階段對(duì)我們有益的七個(gè)策略:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e構(gòu)建具有明確價(jià)值的新服務(wù)\u003c/li\u003e\n\u003cli\u003e單一的持久存儲(chǔ)是有害的\u003c/li\u003e\n\u003cli\u003e解耦“構(gòu)建服務(wù)”和“運(yùn)行服務(wù)”\u003c/li\u003e\n\u003cli\u003e詳盡和一致的可觀察性\u003c/li\u003e\n\u003cli\u003e無(wú)需從頭構(gòu)建新服務(wù)\u003c/li\u003e\n\u003cli\u003e重視發(fā)生的故障\u003c/li\u003e\n\u003cli\u003e從一開始就避免“微服務(wù)綜合癥”\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003e構(gòu)建具有明確價(jià)值的新服務(wù)\u003c/h3\u003e\n\u003cp\u003e有人可能會(huì)認(rèn)為,采用新的服務(wù)端架構(gòu)意味著長(zhǎng)時(shí)間暫停產(chǎn)品開發(fā)和對(duì)所有內(nèi)容的大量重寫。這其實(shí)是錯(cuò)誤的做法,我們絕不應(yīng)該為了構(gòu)建新的服務(wù)而構(gòu)建。我們每次構(gòu)建新服務(wù)或采用新技術(shù)時(shí),都必須具有明確的產(chǎn)品價(jià)值或工程價(jià)值。\u003c/p\u003e\n\u003cp\u003e產(chǎn)品價(jià)值就是我們可以帶給用戶的好處。相對(duì)于單體的Node.js 應(yīng)用而言,新服務(wù)需要提供更多的價(jià)值,或者是更快的提供價(jià)值。工程價(jià)值意味著讓工程團(tuán)隊(duì)更快、更好的工作。\u003c/p\u003e\n\u003cp\u003e如果構(gòu)建新服務(wù)既沒(méi)有產(chǎn)品價(jià)值,也沒(méi)有工程價(jià)值,我們將仍然停留在單體應(yīng)用中。如果十年后Medium 仍然有單體Node.js 應(yīng)用在提供服務(wù),那也沒(méi)什么問(wèn)題。實(shí)際上單體應(yīng)用能夠幫助我們更有策略地對(duì)微服務(wù)進(jìn)行建模。\u003c/p\u003e\n\u003ch3\u003e單一的持久存儲(chǔ)是有害的\u003c/h3\u003e\n\u003cp\u003e建模微服務(wù)的很大一部分工作是對(duì)其持久化存儲(chǔ)的數(shù)據(jù)(例如,數(shù)據(jù)庫(kù))進(jìn)行建模??绶?wù)共享持久數(shù)據(jù)存儲(chǔ)似乎是將微服務(wù)集成在一起的最簡(jiǎn)單方法,然而,它實(shí)際上是有害的,我們應(yīng)該不惜一切代價(jià)避免它。下面解釋一下為什么。\u003c/p\u003e\n\u003cp\u003e首先,持久數(shù)據(jù)存儲(chǔ)事關(guān)實(shí)現(xiàn)細(xì)節(jié)??绶?wù)共享數(shù)據(jù)存儲(chǔ)會(huì)將服務(wù)的實(shí)現(xiàn)細(xì)節(jié)暴露給整個(gè)系統(tǒng)。如果服務(wù)更改了數(shù)據(jù)的格式,或者添加了緩存層,或者切換到不同類型的數(shù)據(jù)庫(kù),則還必須相應(yīng)地更改許多其他服務(wù)。這違反了松耦合的原則。\u003c/p\u003e\n\u003cp\u003e其次,持久數(shù)據(jù)存儲(chǔ),即如何修改、描述和使用數(shù)據(jù),不是服務(wù)行為。如果我們跨服務(wù)共享數(shù)據(jù)存儲(chǔ),則意味著其他服務(wù)也必須復(fù)制這些服務(wù)行為。這違反了高內(nèi)聚的原則,給定域中的行為泄露給了多個(gè)服務(wù)。如果我們修改一個(gè)行為,我們將不得不一起修改所有這些服務(wù)。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e在微服務(wù)架構(gòu)中,特定類型的數(shù)據(jù)只應(yīng)該有一個(gè)服務(wù)負(fù)責(zé)。所有其他服務(wù)應(yīng)該通過(guò)該服務(wù)的API 請(qǐng)求數(shù)據(jù),或者保留數(shù)據(jù)的只讀非規(guī)范(可能具體化)副本。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e這聽起來(lái)可能有點(diǎn)抽象,下面是一個(gè)具體的例子。假設(shè)我們正在構(gòu)建一個(gè)新的推薦服務(wù),它需要來(lái)自發(fā)帖數(shù)據(jù)表中的一些數(shù)據(jù),目前存儲(chǔ)在AWS DynamoDB 中。我們可以通過(guò)下面兩種方式為新推薦服務(wù)提供發(fā)布數(shù)據(jù)。\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://static.geekbang.org/infoq/5c342baa10429.png?imageView2/0/w/800\" alt=\"image\" /\u003e\u003c/p\u003e\n\u003cp\u003e在單一存儲(chǔ)模型中,推薦服務(wù)可以直接訪問(wèn)單體應(yīng)用的持久存儲(chǔ)。這是一個(gè)壞主意,因?yàn)?#xff1a;\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e緩存可能很棘手。如果推薦服務(wù)與單體應(yīng)用共享相同的緩存,我們將不得不在推薦服務(wù)中復(fù)制緩存實(shí)現(xiàn)細(xì)節(jié); 如果推薦服務(wù)使用自己的緩存,當(dāng)單體應(yīng)用更新帖子數(shù)據(jù)時(shí),我們不知道什么時(shí)候使其緩存無(wú)效。\u003c/li\u003e\n\u003cli\u003e如果單片應(yīng)用程序決定改為使用RDS 而不是DynamoDB 來(lái)存儲(chǔ)帖子數(shù)據(jù),我們將不得不重新實(shí)現(xiàn)推薦服務(wù)中的邏輯以及訪問(wèn)帖子數(shù)據(jù)的所有其他服務(wù)。\u003c/li\u003e\n\u003cli\u003e單體應(yīng)用具有描述帖子數(shù)據(jù)的復(fù)雜邏輯,例如,如何確定帖子是否對(duì)給定用戶可見。我們必須在推薦服務(wù)中重新實(shí)現(xiàn)這些邏輯。一旦單體應(yīng)用更改或添加新邏輯,我們也需要在所有地方進(jìn)行相同的更改。\u003c/li\u003e\n\u003cli\u003e盡管推薦服務(wù)的數(shù)據(jù)訪問(wèn)模式是錯(cuò)的,它仍然和在DynamoDB 耦合在一起。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e在解耦存儲(chǔ)模型中,推薦服務(wù)不能直接訪問(wèn)發(fā)貼數(shù)據(jù),也不能訪問(wèn)任何其他新服務(wù)。發(fā)貼數(shù)據(jù)的實(shí)??現(xiàn)細(xì)節(jié)僅保留在一個(gè)服務(wù)中。有不同的方法來(lái)實(shí)現(xiàn)這一目標(biāo)。\u003c/p\u003e\n\u003cp\u003e理想情況下,發(fā)帖數(shù)據(jù)應(yīng)該有一個(gè)發(fā)帖服務(wù),其他服務(wù)只能通過(guò)發(fā)帖服務(wù)的API 訪問(wèn)發(fā)帖數(shù)據(jù)。但是,為所有核心數(shù)據(jù)模型構(gòu)建新服務(wù)可能是一項(xiàng)昂貴的前期投資。\u003c/p\u003e\n\u003cp\u003e當(dāng)人員配備有限時(shí),還有一些更實(shí)用的方法。根據(jù)數(shù)據(jù)訪問(wèn)模式,它們實(shí)際上可能是更好的方式。在選項(xiàng)B 中,單體應(yīng)用可以讓推薦服務(wù)知道相關(guān)的發(fā)帖數(shù)據(jù)何時(shí)更新。通常,這種時(shí)效性不高,因此我們可以將其發(fā)送到消息隊(duì)列系統(tǒng)。在選項(xiàng)C 中,ETL 管道為推薦服務(wù)生成一份發(fā)帖數(shù)據(jù)的只讀副本,以及其他可能對(duì)推薦服務(wù)有用的數(shù)據(jù)。在這兩個(gè)選項(xiàng)中,推薦服務(wù)完全擁有數(shù)據(jù),因此它可以靈活地緩存數(shù)據(jù)或使用最合適的數(shù)據(jù)庫(kù)技術(shù)。\u003c/p\u003e\n\u003ch3\u003e解耦“構(gòu)建服務(wù)”和“運(yùn)行服務(wù)”\u003c/h3\u003e\n\u003cp\u003e如果構(gòu)建微服務(wù)很難,那么運(yùn)行服務(wù)往往更難。當(dāng)運(yùn)行服務(wù)需要構(gòu)建每個(gè)服務(wù),并不斷的重復(fù)這件事時(shí),會(huì)拖慢工程團(tuán)隊(duì)的速度。我們希望讓每項(xiàng)服務(wù)都專注于自己的工作而不用擔(dān)心如何運(yùn)行服務(wù)這一復(fù)雜問(wèn)題,包括網(wǎng)絡(luò)、通信協(xié)議、部署、可觀察性等。服務(wù)管理應(yīng)該與每個(gè)服務(wù)的實(shí)現(xiàn)完全分離。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e解耦“構(gòu)建服務(wù)”和“運(yùn)行服務(wù)”的策略是使運(yùn)行服務(wù)任務(wù)與服務(wù)技術(shù)無(wú)關(guān),并且獨(dú)立,以便應(yīng)用工程師可以完全專注于每個(gè)服務(wù)自己的業(yè)務(wù)邏輯。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e感謝近年來(lái)容器化、容器編排、服務(wù)網(wǎng)格、應(yīng)用性能監(jiān)控等方面的技術(shù)進(jìn)步,“運(yùn)行服務(wù)”的解耦變得比以往更容易實(shí)現(xiàn)。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e網(wǎng)絡(luò)\u003c/strong\u003e。網(wǎng)絡(luò)(例如,服務(wù)發(fā)現(xiàn),路由,負(fù)載均衡,流量路由等)是運(yùn)行服務(wù)的關(guān)鍵部分。傳統(tǒng)方法是為每種平臺(tái)/語(yǔ)言提供庫(kù)。它可以正常工作但不夠理想,因?yàn)閼?yīng)用仍然需要非常繁瑣的工作來(lái)集成和維護(hù)庫(kù)。不僅如此,應(yīng)用還需要單獨(dú)實(shí)現(xiàn)某些邏輯。現(xiàn)代解決方案是在服務(wù)網(wǎng)格中運(yùn)行服務(wù)。在Medium,我們使用\u003ca href=\"https://istio.io/\"\u003eIstio\u003c/a\u003e 和\u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy\u003c/a\u003e 作為邊車代理。構(gòu)建服務(wù)的應(yīng)用工程師根本不需要擔(dān)心網(wǎng)絡(luò)問(wèn)題。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e通信協(xié)議\u003c/strong\u003e。無(wú)論選擇哪種技術(shù)棧或語(yǔ)言來(lái)構(gòu)建微服務(wù),選擇一個(gè)高效、典型、跨平臺(tái)且需要最少開發(fā)工作量的成熟RPC 解決方案都是非常重要的。即使它們之間存在依賴關(guān)系,支持向后兼容性的RPC 解決方案也使部署服務(wù)更安全。在Medium,我們選擇了\u003ca href=\"https://grpc.io/\"\u003egRPC\u003c/a\u003e。\u003c/p\u003e\n\u003cp\u003e一種常見的替代方案是基于HTTP 的REST + JSON,這種解決方案長(zhǎng)期以來(lái)一直是服務(wù)器通信的好手段。但是,盡管該技術(shù)棧非常適合瀏覽器與服務(wù)器通信,但它對(duì)于服務(wù)器之間的通信效率很低,尤其是當(dāng)我們需要發(fā)送大量請(qǐng)求時(shí)。如果沒(méi)有自動(dòng)生成的客戶端和模板代碼,我們將不得不手動(dòng)實(shí)現(xiàn)服務(wù)器/客戶端代碼??煽康腞PC 實(shí)現(xiàn)不僅僅包裝網(wǎng)絡(luò)客戶端。另外,REST 是“自描述的”,但它很難讓人對(duì)每個(gè)細(xì)節(jié)都形成共識(shí),例如,這個(gè)調(diào)用真的是REST,還是只是一個(gè)RPC?這是一種資源還是一種操作?等等。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e部署\u003c/strong\u003e。擁有一致的方法來(lái)構(gòu)建、測(cè)試、打包、部署和管理服務(wù)非常重要。Medium 所有的微服務(wù)都在容器中運(yùn)行。目前,我們的編排系統(tǒng)是\u003ca href=\"https://aws.amazon.com/ecs/\"\u003eAWS ECS\u003c/a\u003e 和Kubernetes 的混合體,但正在向全Kubernetes 遷移。\u003c/p\u003e\n\u003cp\u003e我們構(gòu)建了自己的系統(tǒng)來(lái)構(gòu)建、測(cè)試、打包和部署服務(wù),稱為BBFD。它在跨服務(wù)的一致性和為特定服務(wù)提供采用不同技術(shù)棧的靈活性之間取得平衡。它的工作方式是讓每個(gè)服務(wù)提供基本信息,例如,要監(jiān)聽的端口,構(gòu)建/測(cè)試/啟動(dòng)服務(wù)的命令等,BBFD 將負(fù)責(zé)其余的工作。\u003c/p\u003e\n\u003ch3\u003e詳盡和一致的可觀察性\u003c/h3\u003e\n\u003cp\u003e可觀察性包括允許我們了解系統(tǒng)如何工作的過(guò)程,約定和工具,以及在故障時(shí)對(duì)問(wèn)題進(jìn)行鑒定??捎^察性包括日志記錄、性能跟蹤、指標(biāo)、儀表盤、警報(bào),它對(duì)微服務(wù)架構(gòu)成功與否至關(guān)重要。\u003c/p\u003e\n\u003cp\u003e當(dāng)我們從單個(gè)服務(wù)遷移到具有許多服務(wù)的分布式系統(tǒng)時(shí),可能會(huì)發(fā)生兩件事:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e我們失去了可觀察性,因?yàn)樗鼘?shí)現(xiàn)起來(lái)更難,更容易被忽視。\u003c/li\u003e\n\u003cli\u003e不同的團(tuán)隊(duì)重復(fù)造輪子,最終得到了碎片化的可觀察性,這種可觀察性實(shí)際上很低,因?yàn)楹茈y使用碎片數(shù)據(jù)對(duì)問(wèn)題進(jìn)行關(guān)聯(lián)和鑒定。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e從一開始就具有良好且一致的可觀察性非常重要,因此我們的DevOps 團(tuán)隊(duì)提出了一致的可觀察性策略,并構(gòu)建了支持實(shí)現(xiàn)這一目標(biāo)的工具。每個(gè)服務(wù)都會(huì)自動(dòng)獲取詳細(xì)的\u003ca href=\"https://www.datadoghq.com/\"\u003eDataDog\u003c/a\u003e 儀表盤、警報(bào)和日志搜索,這些服務(wù)在所有服務(wù)中是一致的。我們還大量使用\u003ca href=\"https://lightstep.com/\"\u003eLightStep\u003c/a\u003e 來(lái)了解系統(tǒng)的性能。\u003c/p\u003e\n\u003ch3\u003e無(wú)需從頭構(gòu)建新服務(wù)\u003c/h3\u003e\n\u003cp\u003e在微服務(wù)架構(gòu)中,每個(gè)服務(wù)都專注于做好一件事。請(qǐng)注意,它與如何構(gòu)建服務(wù)無(wú)關(guān)。從單體服務(wù)遷移時(shí),如果可以從單體應(yīng)用中剝離,就無(wú)需從頭開始構(gòu)建微服務(wù)。\u003c/p\u003e\n\u003cp\u003e務(wù)實(shí)的說(shuō),是否應(yīng)該從頭開始構(gòu)建服務(wù)取決于兩個(gè)因素:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eNode.js 是否適合新任務(wù);\u003c/li\u003e\n\u003cli\u003e在不同的技術(shù)棧中重新實(shí)現(xiàn)的成本是多少。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e如果Node.js 是一個(gè)不錯(cuò)的技術(shù)選擇,并且現(xiàn)有的實(shí)現(xiàn)方式?jīng)]有問(wèn)題,我們就將代碼從單體應(yīng)用中刪除,并用它創(chuàng)建一個(gè)微服務(wù)。即使采用相同的實(shí)現(xiàn),我們?nèi)詫@得微服務(wù)架構(gòu)的所有好處。\u003c/p\u003e\n\u003cp\u003e我們的Node.js 單體應(yīng)用的架構(gòu)使我們可以相對(duì)輕松地使用現(xiàn)有實(shí)現(xiàn)構(gòu)建單獨(dú)的服務(wù)。我們將在本文稍后討論如何正確構(gòu)建單體。\u003c/p\u003e\n\u003ch3\u003e重視發(fā)生的故障\u003c/h3\u003e\n\u003cp\u003e在分布式環(huán)境中,故障的可能性會(huì)更高。如果處理不當(dāng),關(guān)鍵服務(wù)的故障可能是災(zāi)難性的。我們應(yīng)該始終考慮如何測(cè)試故障并優(yōu)雅地處理故障。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e首先,要明白故障無(wú)處不在。\u003c/li\u003e\n\u003cli\u003e對(duì)于RPC 調(diào)用,需要對(duì)故障進(jìn)行額外處理。\u003c/li\u003e\n\u003cli\u003e確保發(fā)生故障時(shí)具有良好的可觀察性(如上所述)。\u003c/li\u003e\n\u003cli\u003e新服務(wù)上線前必須進(jìn)行故障測(cè)試。它應(yīng)該是新服務(wù)檢查列表的一部分。\u003c/li\u003e\n\u003cli\u003e盡可能自動(dòng)恢復(fù)。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003e從一開始就避免微服務(wù)綜合癥\u003c/h3\u003e\n\u003cp\u003e微服務(wù)不是靈丹妙藥,它解決了一些問(wèn)題,但也創(chuàng)造了一些其他問(wèn)題,我們將其稱為“ 微服務(wù)綜合癥 ”。如果我們一開始就不去考慮它們,那么事情很快會(huì)變得很麻煩,處理起來(lái)也要付出更多代價(jià)。以下是一些常見癥狀。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e建模不良的微服務(wù)弊大于利,特別是在數(shù)量龐大時(shí)。\u003c/li\u003e\n\u003cli\u003e允許選擇太多不同的語(yǔ)言/技術(shù),這會(huì)增加運(yùn)維成本并使工程團(tuán)隊(duì)碎片化。\u003c/li\u003e\n\u003cli\u003e將運(yùn)行服務(wù)與構(gòu)建服務(wù)相結(jié)合,這極大地增加了服務(wù)的復(fù)雜性并拖慢了團(tuán)隊(duì)的速度。\u003c/li\u003e\n\u003cli\u003e忽略數(shù)據(jù)建模,最終得到具有單體數(shù)據(jù)存儲(chǔ)的微服務(wù)。\u003c/li\u003e\n\u003cli\u003e缺乏可觀察性,難以對(duì)性能問(wèn)題和故障進(jìn)行定位。\u003c/li\u003e\n\u003cli\u003e遇到問(wèn)題時(shí),團(tuán)隊(duì)傾向于創(chuàng)建新服務(wù)而不是修復(fù)現(xiàn)有服務(wù),即使后者可能是更好的選擇。\u003c/li\u003e\n\u003cli\u003e即使服務(wù)松耦合,缺乏系統(tǒng)的整體視角也可能存在問(wèn)題。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e我們應(yīng)該停止構(gòu)建單體服務(wù)嗎?\u003c/h2\u003e\n\u003cp\u003e隨著最近的技術(shù)創(chuàng)新,采用微服務(wù)架構(gòu)變得更加容易。這是否意味著我們都應(yīng)該停止構(gòu)建單體服務(wù)?\u003c/p\u003e\n\u003cp\u003e答案是否定的。雖然新技術(shù)可以更好的支持微服務(wù)架構(gòu),但仍然存在較高的復(fù)雜度和難度。對(duì)于小型團(tuán)隊(duì)來(lái)說(shuō),單體應(yīng)用仍然是更好的選擇。但是,可以花時(shí)間對(duì)單體應(yīng)用進(jìn)行更好的架構(gòu)設(shè)計(jì),以便于在系統(tǒng)和團(tuán)隊(duì)成長(zhǎng)后,可以更方便的遷移到微服務(wù)架構(gòu)中。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e從單體結(jié)構(gòu)開始沒(méi)什么問(wèn)題,但確保模塊化并使用上述三種微服務(wù)原則(單一目的、松耦合和高內(nèi)聚)來(lái)構(gòu)建它,除了“服務(wù)”在同一技術(shù)棧中實(shí)現(xiàn),部署在一起并在同一個(gè)進(jìn)程中運(yùn)行。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e在Medium,我們?cè)谠缙诘膯误w應(yīng)用中做出了一些很好的架構(gòu)決策。\u003c/p\u003e\n\u003cp\u003e我們的單體應(yīng)用的組件是高度模塊化的,盡管它已經(jīng)發(fā)展成為一個(gè)非常復(fù)雜的應(yīng)用,包括Web 服務(wù)器、后端服務(wù)和離線事件處理器。離線事件處理器單獨(dú)運(yùn)行,但使用完全相同的代碼。這使得將一大塊業(yè)務(wù)邏輯剝離到單獨(dú)的服務(wù)相對(duì)容易,只要新服務(wù)提供與原始實(shí)現(xiàn)相同(上層)的接口即可。\u003c/p\u003e\n\u003cp\u003e我們的單體應(yīng)用程序在較低級(jí)別封裝了數(shù)據(jù)存儲(chǔ)的細(xì)節(jié)。每種數(shù)據(jù)類型(例如,數(shù)據(jù)庫(kù)表)具有兩層實(shí)現(xiàn):數(shù)據(jù)層和服務(wù)層。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e數(shù)據(jù)層處理一個(gè)特定類型數(shù)據(jù)的CRUD 操作。\u003c/li\u003e\n\u003cli\u003e服務(wù)層處理一個(gè)特定類型數(shù)據(jù)的上層邏輯和為系統(tǒng)的其余部分提供公共API。服務(wù)之間不共享數(shù)據(jù)存儲(chǔ)。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e這有助于我們采用微服務(wù)架構(gòu),因?yàn)閿?shù)據(jù)類型的實(shí)現(xiàn)細(xì)節(jié)對(duì)其他部分代碼完全隱藏。創(chuàng)建新服務(wù)來(lái)處理某一類型的數(shù)據(jù)相對(duì)容易且安全。\u003c/p\u003e\n\u003cp\u003e單體應(yīng)用還可以幫助我們對(duì)微服務(wù)進(jìn)行建模,讓我們能夠靈活地專注于系統(tǒng)中最重要的部分,而不是從頭開始為所有微服務(wù)建模。\u003c/p\u003e\n\u003ch2\u003e結(jié)論\u003c/h2\u003e\n\u003cp\u003e單體Node.js 應(yīng)用已經(jīng)為我們服務(wù)了好幾年,但它開始拖慢我們交付大項(xiàng)目和快速迭代的速度。我們開始系統(tǒng)性和戰(zhàn)略性地采用微服務(wù)架構(gòu)。我們?nèi)匀惶幱谶@一旅程的早期階段,但我們已經(jīng)看到了它的優(yōu)勢(shì)和潛力,它極大的提高了開發(fā)效率,使我們能夠大膽思考并大幅提升產(chǎn)品,同時(shí)解放工程團(tuán)隊(duì),能夠安全地測(cè)試新技術(shù)。\u003c/p\u003e\n\u003cp\u003e查看英文原文:\u003ca href=\"https://medium.engineering/microservice-architecture-at-medium-9c33805eb74f\"\u003eMicroservice Architecture at?Medium\u003c/a\u003e\u003c/p\u003e\n
總結(jié)
以上是生活随笔為你收集整理的Medium 架构实践:避免微服务综合症的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 01-Thinkphp基础配置
- 下一篇: 另类数据Alternative Data