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