|
由于疫情的原因,我被分配的任務(wù)不是很多,所以就會空出一點時間,一般這個時候我都會做自己的事情,比如看看源碼、翻翻博客、然后就是寫寫博客。 圖片來自 Pexels 正當我沉迷在源碼中不能自拔的時候,總監(jiān)突然來到我旁邊輕聲的對我說道:最近這段時間大家的任務(wù)也不是特別多,空閑時間比較足,你這邊能不能做點技術(shù)分享什么的,一來可以聯(lián)絡(luò)一下同事之間的感情,二來也可以增加同事之間的學習氛圍。  寶寶心里難受,一直在想我要講一個什么樣的話題才能讓大部分的人都能聽得懂并且感興趣呢?這里面肯定不時出現(xiàn)太多的代碼,既然這樣,那我就講一講分布式的架構(gòu)演進吧,這個話題既高端,也能讓大部分的人聽懂,我就是個天才。  好了,不廢話了,開始這次的主題,分布式架構(gòu)的演變。我記得在我實習的時候用的就是單體的服務(wù),那個時候的架構(gòu)很簡單,前后端分離都還沒有,直接 JSP+Java 實現(xiàn)一套項目,整個流程相當簡單,就連 Nginx 都沒有用到。我們一起來看看當時的架構(gòu)是什么樣的: 
①引入 Nginx沒錯,就是這么簡單,瀏覽器通過接口訪問服務(wù)器,服務(wù)器通過用戶的請求操作數(shù)據(jù)庫,然后再相應(yīng)給瀏覽器,這就是一個最簡單的單體服務(wù)的流程。后來領(lǐng)導覺得直接將端口暴露出去相當危險,我們需要做一層代理,讓用戶直接通過域名訪問。然后流程就被設(shè)計成了這樣:  這是引入 Nginx 之后的架構(gòu)圖,在這樣運行了一段時間之后,突然有一天,領(lǐng)導找到我并說到:你寫的代碼是不是有問題,為什么一個普通的查詢需要很長的時間?基本操作都卡的要死,給你一周時間,趕緊給我解決!②引入 Redis 單體經(jīng)過我的排查之后發(fā)現(xiàn)導致程序變卡的原因是數(shù)據(jù)庫受到了瓶頸,壓力太大,承受不住那么大的請求,既然問題找到了,那解決就很簡單了。我在程序和數(shù)據(jù)庫之間增加一個中間件:Redis,使用它來降低數(shù)據(jù)庫的訪問,這樣性能自然會得到提升。  舒服,引入 Redis,并且對代碼做了一些優(yōu)化之后,發(fā)現(xiàn)速度上來了,我有可以快樂的寫 Bug 了。就這樣過去了大概一個月左右,這天我正在和同事討論一些八卦,突然感覺背后一陣陰風 ,我知道,出事了。沒想到是領(lǐng)導又來找我麻煩了,他說由于我們的產(chǎn)品太火了,下載注冊人數(shù)都幾十萬了,日活躍人數(shù)也是上萬,我們現(xiàn)在的這套架構(gòu)撐不住了,你有沒有什么好的建議?我驚訝了一下,我們的產(chǎn)品這么受歡迎嗎?于是我和領(lǐng)導說,我們可以將數(shù)據(jù)做一下讀寫分離,這樣也可以提升一下程序的性能,但是對于現(xiàn)在的情況,就算加了讀寫分離,作用應(yīng)該也不大,我們應(yīng)該將單體多部署幾臺,提升程序的吞吐量。③引入 MySQL 讀寫分離 這就是將數(shù)據(jù)庫改造成讀寫分離之后的架構(gòu),讀操作和寫操作分別在不同的庫中,這樣,查詢和寫入就不會那么長的時間了,因為在讀庫中沒有寫操作,寫庫中沒有讀操作。由于我們一般是讀的操作比較多,所以這個時候我們我們可以將讀庫的配置設(shè)置的好一點,寫庫的設(shè)置的差一點,均衡分配。但僅僅這樣是也是不能支撐那么大流量的,所以這個時候我們還需要將服務(wù)器做集群。④引入服務(wù)器集群 這就是我們單體的最終架構(gòu),改造完成之后性能確實得到了很大的提升,因為服務(wù)做了集群之后,分散了很多的請求。比如一個 Tomcat 能支持的最高并發(fā)是 200,那現(xiàn)在三個服務(wù)就能支持 600 的并發(fā),性能提升了 3 倍,最終擴充了多少臺服務(wù)器我也不清楚,因為這個是運維做的。集群算是做完了,總算可以滿足領(lǐng)導的要求了,為了搞定這一套一套的升級,不知道熬了多少夜,看到電腦旁邊掉落的那幾根頭發(fā),我滿意的點了點頭。 在后面的兩個月的時間里,我們在不停的做迭代更新,幾乎每周都會有版本上線,兩個月過后版本終于穩(wěn)定下來了,不怎么有更新了,所以又來到了程序猿的空閑時間。同事們每天上班都做著自己的事情,有學習的,有逛淘寶的,有玩游戲的,更夸張的是居然有個同事閑著沒事居然去撩產(chǎn)品小姐姐,握草,這是想要自掘墳?zāi)箚幔?/span>大概空閑了一周的時間左右,我們的技術(shù)總監(jiān)說話了,今天下午 3 點,所有后端開發(fā)人員會議室開會,聽到這個消息,我就知道,有活干了,難道是接了新的項目?到了下午 3 點,我們來到會議室,只見技術(shù)總監(jiān)已經(jīng)提前到了,并且屏幕上寫著五個大字,看到這五個字,我心里想,該來的還是會來,躲不過去的,那就是:分布式架構(gòu)。因為我知道,我們產(chǎn)品注冊人數(shù)已經(jīng)高達幾十萬,以我們現(xiàn)在的架構(gòu)肯定會有撐不住的一天,這個產(chǎn)品肯定會被重構(gòu),并且是以分布式的架構(gòu)進行重構(gòu),果然,今天技術(shù)總監(jiān)就召開了這個會議。技術(shù)總監(jiān):我們的產(chǎn)品現(xiàn)在比較火熱,不管是注冊人數(shù)還是日活躍人數(shù)都是比較高的,為了讓程序能有更好的健壯性,我希望我們可以對這個項目進行重構(gòu),以分布式的架構(gòu),今天開會就是我們一起來做個技術(shù)選型,你們對分布式熟悉嗎?同事 A:分布式系統(tǒng)(distributed system)是建立在網(wǎng)絡(luò)之上的軟件系統(tǒng)。正是因為軟件的特性,所以分布式系統(tǒng)具有高度的內(nèi)聚性和透明性。因此,網(wǎng)絡(luò)和分布式系統(tǒng)之間的區(qū)別更多的在于高層軟件(特別是操作系統(tǒng)),而不是硬件。技術(shù)總監(jiān):嗯,不錯,不過這個解釋比較官方,還有沒有比較通俗易懂的解釋?同事 B:分布式將一個大的系統(tǒng)拆分成無數(shù)個細微的子系統(tǒng),讓每一個系統(tǒng)都負責一定的職責,他們相互獨立,但是又相互聯(lián)系。技術(shù)總監(jiān):喲,不錯哦,這個同事可以,晚上加雞腿,那有人可以舉個例子嗎?Me:從前有一個有一個飯店,里面只有老板和一個員工,這個員工負責飯店所有的事情,包括但不限于:廚師、服務(wù)員、收銀員、清潔工等,在炒菜的時候就不能去收錢,在打掃衛(wèi)生的時候就不能炒菜,這個員工干了一個月之后,突然有一天,他病倒了,餐廳的生意就停滯了,這個時候老板就想到了一個人不行,那我多招幾個人,一個人負責一個職位,這樣即使某個人請假或者離職了,對我的生意影響不是很大,比如:清潔工離職了,雖然沒有人打掃衛(wèi)生,但是這并不影響我開門做生意,分布式就是這個道理。技術(shù)總監(jiān):這個例子講的不錯,你晚上不用加班了,如果你要是能畫一個分布式的基礎(chǔ)圖出來,我今晚請大家擼串。Me:我專治各種不服,于是我就給技術(shù)總監(jiān)'上了一課',請看圖:  技術(shù)總監(jiān):不錯,畫的很好,但是你們知道我們?yōu)槭裁匆獙误w的服務(wù)重構(gòu)為分布式嗎?答對有雞腿。這是分布式的優(yōu)點,這樣看起來可能比較抽象,舉個例子來說,對于單體服務(wù)來說,如果我想更新訂單中的某個功能,我是不是需要重啟整個服務(wù)。這個時候就會導致整個項目都處于不可用狀態(tài),或者在處理訂單的時候由于程序代碼寫的有問題,導致死鎖了,這個時候也會導致整個服務(wù)處于宕機專改,容錯率很差。但是分布式不同,如上圖所示,訂單服務(wù)、售后服務(wù)、用戶服務(wù)都是獨立的服務(wù),如果需要更新訂單服務(wù)或者訂單服務(wù)發(fā)生死鎖,受影響的只會是訂單服務(wù),售后服務(wù)與用戶服務(wù)還是可以正常工作的,這就是分布式相對單體來說最大的優(yōu)勢之一。技術(shù)總監(jiān):想不到我們這個團隊人才輩出啊,不錯不錯,看來我都沒有講下去的必要了啊,大家對分布式都相當熟悉了啊,那分布式架構(gòu)存在缺點或者不足嗎?同事 D: 這是我平時刷博客的時候看到的,覺得總結(jié)的不錯!技術(shù)總監(jiān):既然大家對分布式都這么熟悉了,那我也就不在多說了,我們接下來直接來說說關(guān)于分布式組件的選型吧,大家有什么意見都可以提出來,首先誰來說一下分布式組件都有哪些?請開始你們的表演。  同事 E:那我就不客氣了,由于我們都是對 Spring Cloud 比較熟悉,現(xiàn)在他也是比較主流,那我介紹一下 Spring Cloud 的基礎(chǔ)組件吧。Spring Cloud Config:配置管理工具包,讓你可以把配置放到遠程服務(wù)器,集中化管理集群配置,目前支持本地存儲、Git 以及 Subversion。 Spring Cloud Bus:事件、消息總線,用于在集群(例如,配置變化事件)中傳播狀態(tài)變化,可與 Spring Cloud Config 聯(lián)合實現(xiàn)熱部署。 Eureka:云端服務(wù)發(fā)現(xiàn),一個基于 REST 的服務(wù),用于定位服務(wù),以實現(xiàn)云端中間層服務(wù)發(fā)現(xiàn)和故障轉(zhuǎn)移。 Hystrix:熔斷器,容錯管理工具,旨在通過熔斷機制控制服務(wù)和第三方庫的節(jié)點,從而對延遲和故障提供更強大的容錯能力。 Zuul:Zuul 是在云平臺上提供動態(tài)路由,監(jiān)控,彈性,安全等邊緣服務(wù)的框架。Zuul 相當于是設(shè)備和 Netflix 流應(yīng)用的 Web 網(wǎng)站后端所有請求的前門。 Archaius:配置管理 API,包含一系列配置管理 API,提供動態(tài)類型化屬性、線程安全配置操作、輪詢框架、回調(diào)機制等功能。 Consul:封裝了 Consul 操作,Consul 是一個服務(wù)發(fā)現(xiàn)與配置工具,與 Docker 容器可以無縫集成。 Spring Cloud for Cloud Foundry:通過 Oauth2 協(xié)議綁定服務(wù)到 CloudFoundry,CloudFoundry 是 VMware 推出的開源 PaaS 云平臺。 Spring Cloud Sleuth:日志收集工具包,封裝了 Dapper 和 log-based 追蹤以及 Zipkin 和 HTrace 操作,為 Spring Cloud 應(yīng)用實現(xiàn)了一種分布式追蹤解決方案。 Spring Cloud Data Flow:大數(shù)據(jù)操作工具,作為 Spring XD 的替代產(chǎn)品,它是一個混合計算模型,結(jié)合了流數(shù)據(jù)與批量數(shù)據(jù)的處理方式。 Spring Cloud Security:基于 Spring Security 的安全工具包,為你的應(yīng)用程序添加安全控制。 Spring Cloud Zookeeper:操作 Zookeeper 的工具包,用于使用 Zookeeper 方式的服務(wù)發(fā)現(xiàn)和配置管理。 Spring Cloud Stream:數(shù)據(jù)流操作開發(fā)包,封裝了與 Redis、Rabbit、Kafka 等發(fā)送接收消息。 Spring Cloud CLI:基于 Spring Boot CLI,可以讓你以命令行方式快速建立云組件。 Ribbon:提供云端負載均衡,有多種負載均衡策略可供選擇,可配合服務(wù)發(fā)現(xiàn)和斷路器使用。 Turbine:Turbine 是聚合服務(wù)器發(fā)送事件流數(shù)據(jù)的一個工具,用來監(jiān)控集群下 Hystrix 的 Metrics 情況。 Feign:Feign 是一種聲明式、模板化的 HTTP 客戶端。 Spring Cloud Task:提供云端計劃任務(wù)管理、任務(wù)調(diào)度。 Spring Cloud Connectors:便于云端應(yīng)用程序在各種 PaaS 平臺連接到后端,如:數(shù)據(jù)庫和消息代理服務(wù)。 Spring Cloud Cluster:提供 Leadership 選舉,如:Zookeeper,Redis,Hazelcast,Consul 等常見狀態(tài)模式的抽象和實現(xiàn)。 Spring Cloud Starters:Spring Boot 式的啟動項目,為 Spring Cloud 提供開箱即用的依賴管理。 Spring Cloud Config Spring Cloud Bus Hystrix Zuul Ribbon
技術(shù)總監(jiān):不錯,組件分析的不錯,但是你的講解比較官方,下面我們來一個一個的講解一下我們經(jīng)常使用的這些組件。 ①Eureka Eureka 屬于 Spring Cloud Netflix 下的組件之一,主要負責服務(wù)的注冊與發(fā)現(xiàn),何為注冊與發(fā)現(xiàn)?在剛剛我們分析的分布式中存在這一個問題,那就是訂單服務(wù)與用戶服務(wù)被獨立了,那么他們怎么進行通信呢?比如在訂單服務(wù)中獲取用戶的基礎(chǔ)信息,這個時候我們需要怎么辦?如果按照上面的架構(gòu)圖,直接去數(shù)據(jù)庫獲取就可以了,因為服務(wù)雖然獨立了,但是數(shù)據(jù)庫還是共享的,所以直接查詢數(shù)據(jù)庫就能得到結(jié)果,如果我們將數(shù)據(jù)庫也拆分了呢?這個時候我們該怎么辦呢?有人想到了,服務(wù)調(diào)用,服務(wù)調(diào)用是不是需要 IP 和端口才可以,那問題來了,對于訂單服務(wù)來說,我怎么知道用戶服務(wù)的 IP 和端口呢?在訂單服務(wù)中寫死嗎?如果用戶服務(wù)的端口發(fā)生改變了呢?這個時候 Eureka 就出來了,他就是為了解決服務(wù)的通信問題,每個服務(wù)都可以將自己的信息注冊到 Eureka 中,比如 IP、端口、服務(wù)名等信息,這個時候如果訂單服務(wù)想要獲取用戶服務(wù)的信息,只需要去 Eureka 中獲取即可。請看下圖:  這就是 Eureka 的主要功能,也是我們使用中的最值得注意的,他讓服務(wù)之間的通信變得更加的簡單靈活。②Spring Cloud ConfigSpring Cloud Config 為分布式系統(tǒng)中的外部配置提供服務(wù)器和客戶端支持。使用 Config Server,您可以在所有環(huán)境中管理應(yīng)用程序的外部屬性。客戶端和服務(wù)器上的概念映射與 Spring Environment 和 PropertySource 抽象相同,因此它們與 Spring 應(yīng)用程序非常契合,但可以與任何以任何語言運行的應(yīng)用程序一起使用。隨著應(yīng)用程序通過從開發(fā)人員到測試和生產(chǎn)的部署流程,您可以管理這些環(huán)境之間的配置,并確定應(yīng)用程序具有遷移時需要運行的一切。服務(wù)器存儲后端的默認實現(xiàn)使用 Git,因此它輕松支持標簽版本的配置環(huán)境,以及可以訪問用于管理內(nèi)容的各種工具。可以輕松添加替代實現(xiàn),并使用 Spring 配置將其插入。簡單點來說集中來管理每個服務(wù)的配置文件,將配置文件與服務(wù)分離,這么多的目的是什么?舉個簡單的栗子,我們配置文件中肯定會存在數(shù)據(jù)庫的連接信息,Redis 的連接信息,我們的環(huán)境是多樣的,有開發(fā)環(huán)境、測試環(huán)境、預(yù)發(fā)布環(huán)境、生產(chǎn)環(huán)境。每個環(huán)境對應(yīng)的連接信息肯定是不相同的,難道每次發(fā)布的時候都要去修改一下服務(wù)中的配置文件?我能不能將這些變動較大的配置集中管理,不同環(huán)境的管理者分別對他們進行修改,就不需要再服務(wù)中做改動了,Config 就做到了。  這就是 Config 的大致架構(gòu),所有的配置文件都集中交給 Config 管理,拿 Config 怎么管理這些配置文件呢?你可以將每個環(huán)境的配置文件存放再一個位置,比如 Lgitlab、SVN、本地等等,Config 會根據(jù)根據(jù)你設(shè)置的位置讀取配置文件進行管理,然后其他服務(wù)啟動的時候直接到 Config 配置中心獲取對應(yīng)的配置文件即可。這樣開發(fā)人員只需要關(guān)注 -dev 的配置文件,測試人員只需要關(guān)注 -test 的配置文件,完全和服務(wù)解耦,你值得擁有。③Netflix Zuul(網(wǎng)關(guān))這個時候技術(shù)總監(jiān)突然提了一個問題,他說:既然我們將一個服務(wù)拆分成了很多微服務(wù),那豈不是要暴漏很多接口給瀏覽器?這樣會不會造成安全隱患呢?有誰可以來說說這個問題。同事 A:我們可以通過 Nginx 反向代理,開放二級域名,然后將域名映射到微服務(wù)中。技術(shù)總監(jiān):這個方案也可以,也是不需要使用的,但不是最完善的,還有沒有更好的方案?Nginx 雖然把端口隱藏了,如果我們的服務(wù)都是需要一些權(quán)限的校驗,Nginx 是無法替我們完成的,這個時候我們難道要在每個服務(wù)中都添加一套權(quán)限校驗的邏輯嗎?同事 B:我覺得我們可以使用網(wǎng)關(guān),它既可以做分流轉(zhuǎn)發(fā),也可以做權(quán)限控制,使用 Nginx+網(wǎng)關(guān),我覺得是比較好的一種方案,以下是網(wǎng)關(guān) Zuul 的介紹。路由在微服務(wù)體系結(jié)構(gòu)的一個組成部分。例如,/可以映射到您的 Web 應(yīng)用程序,/api/users 映射到用戶服務(wù),并將 /api/shop 映射到商店服務(wù)。Zuul 是 Netflix 的基于 JVM 的路由器和服務(wù)器端負載均衡器。認證 -洞察 壓力測試 金絲雀測試 動態(tài)路由 服務(wù)遷移 負載脫落 安全 靜態(tài)響應(yīng)處理 主動/主動流量管理
我們在日常開發(fā)過程中并不會使用那么多,基本上就是認證、動態(tài)路由、安全等等,我畫了一張關(guān)于網(wǎng)關(guān)的架構(gòu)圖,請看:  技術(shù)總監(jiān):你們真的太優(yōu)秀了,沒錯,Nginx 只能為我們做反向代理,不能做到權(quán)限認證,網(wǎng)關(guān)不但可以做到代理,也能做到權(quán)限認證、甚至還能做限流,所以我們要做分布式項目,少了他可不行。④Spring Cloud Busapplication.yml spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/test driver-class-name: com.mysql.cj.jdbc.Driver
技術(shù)總監(jiān):比如上面這行配置大家都應(yīng)該很熟悉,這是數(shù)據(jù)庫的連接信息,如果它發(fā)生改變了怎么辦呢?我們都知道,服務(wù)啟動的時候會去 Config 配置中心拉取配置信息,但是啟動完成之后修改了配置文件我們應(yīng)該怎么辦呢,重啟服務(wù)器嗎?同事 C:我們可以通過 Spring Cloud Bus 來解決這個問題,Spring Cloud Bus 將輕量級消息代理鏈接到分布式系統(tǒng)的節(jié)點。然后可以將其用于廣播狀態(tài)更改(例如,配置更改)或其他管理指令。該項目包括 AMQP 和 Kafka 經(jīng)紀人實施。另外,在類路徑上找到的任何 Spring Cloud Stream 綁定程序都可以作為傳輸工具使用。這個需要我們有一點的 MQ 基礎(chǔ),不管是 RabbitMQ 還是 Kafka,都可以。Bus 的基本原理就是:配置文件發(fā)生改變時,Config 會發(fā)出一個 MQ,告訴服務(wù),配置文件發(fā)生改變了,并且還發(fā)出了改變的哪些信息,這個時候服務(wù)只需要根據(jù) MQ 的信息做實時修改即可。這是一個很簡單的原理,理解起來可能也不會怎么難,畫個圖來理解一下:  大致流程就是這樣,核心就是通過 MQ 機制實現(xiàn)不重啟服務(wù)也能做到配置文件的改動,這方便了運維工程師,不用每次修改配置文件的時候都要去重啟一遍服務(wù)的煩惱。⑤Feign技術(shù)總監(jiān):漂亮,和你們講技術(shù)就是省事,剛才我們說到了注冊中心可以方便服務(wù)于服務(wù)之間的通信,但是他們具體是怎么通信的你們有誰知道嗎?同事 D:由于我們剛剛講的分布式架構(gòu)是 Spring Cloud,所以這里推薦使用:Feign。Feign 是一個聲明式的 Web 服務(wù)客戶端。這使得 Web 服務(wù)客戶端的寫入更加方便 要使用 Feign 創(chuàng)建一個界面并對其進行注釋。它具有可插入注釋支持,包括 Feign 注釋和 JAX-RS 注釋。Feign 還支持可插拔編碼器和解碼器。Spring Cloud 增加了對 Spring MVC 注釋的支持,并使用 Spring Web 中默認使用的 HttpMessageConverters。Spring Cloud 集成 Ribbon 和 Eureka 以在使用 Feign 時提供負載均衡的 HTTP 客戶端。  Feign 基于 Rest 風格,簡單易懂,他的底層是對 HttpClient 進行了一層封裝,使用十分方便。技術(shù)總監(jiān):不錯,那如果服務(wù)的調(diào)用出現(xiàn)問題怎么辦?比如調(diào)用超時,這個時候后我們?nèi)绾翁幚恚?/span>⑥Netflix Hystrix(熔斷)同事 E:這個 Cloud 也給我們考慮到了,我們只需要引入熔斷即可。Hystrix 支持回退的概念:當電路斷開或出現(xiàn)錯誤時執(zhí)行的默認代碼路徑。要為給定的 @FeignClient 啟用回退,請將 Fallback 屬性設(shè)置為實現(xiàn)回退的類名。我們可以改造一下剛剛的調(diào)用架構(gòu):  在這里我部署了一臺備用服務(wù)器,當用戶服務(wù)宕機了之后,訂單服務(wù)進行遠程調(diào)用的時候可以進入備用服務(wù),這樣就不會導致系統(tǒng)崩潰。技術(shù)總監(jiān):分布式大致架構(gòu)差不多了,還有一些組件這里也不做做介紹了,使用的時候可以自己了解一下,不是很難。我們接著往下說,我現(xiàn)在這里有一個需求,修改密碼,修改密碼需要發(fā)送短信驗證碼,發(fā)送短信在短信服務(wù)中,修改密碼在用戶服務(wù)中,這個時候就會出現(xiàn)服務(wù)調(diào)用。而且我們知道,發(fā)送短信一般都是調(diào)用第三方的接口,那比如阿里的,既然牽扯到調(diào)用,那么就會存在很多不確定因素,比如網(wǎng)絡(luò)問題。假如,用戶再點擊發(fā)送短信驗證碼到時候用戶服務(wù)調(diào)用短信服務(wù),但是在短信服務(wù)中執(zhí)行調(diào)用阿里的接口花費了很長的時間。這個時候就會導致用戶服務(wù)調(diào)短信服務(wù)超時,會返回給用戶失敗,但是,短信最后又發(fā)出去了,這種問題怎么解決呢?同事 B:我們可以通過消息中間件來實現(xiàn),使用異步講給用戶的反饋和發(fā)送短信分離,只要用戶點了發(fā)送短信,直接返回成功,然后再啟動發(fā)送驗證碼,60 秒重發(fā)一下,就算發(fā)送失敗,用戶還可以選擇重新發(fā)送。  技術(shù)總監(jiān):漂亮,MQ 不但可以解耦服務(wù),它還可以用來削峰,提高系統(tǒng)的性能,是一個不錯的選擇。既然我們使用了分布式架構(gòu),那么有一點是我們必須要注意的,那就是事務(wù)問題。如果一個服務(wù)的修改依賴另外一個服務(wù)的操作,這個時候如果操作不慎,就會導致可怕的后果。舉個例子,兩個服務(wù):錢包服務(wù)(用于充值提現(xiàn))、交易錢包服務(wù)(用于交易),我現(xiàn)在想從錢包服務(wù)中轉(zhuǎn) 1000 元到交易錢包服務(wù)中,我們應(yīng)該如何保證他們數(shù)據(jù)的一致性呢?同事 C:我這里有兩種方案,第一種是通過 MQ 來保證一致性,另外一種就是通過分布式事務(wù)來確保一致性。①MQ 確保一致性交易錢包服務(wù):接收 MQ 的消息,進行轉(zhuǎn)入操作(此操作需要 Ack 確認機制的支持)。系統(tǒng)中會一直定時掃描訂單中狀態(tài),沒有成功的就做補償機制或者重試機制,這個不是唯一要求。  以上就是 MQ 確保分布式事務(wù)的大致思路,不是唯一,僅供參考。②Seata(分布式事務(wù))事務(wù)協(xié)調(diào)器(TC):維護全局事務(wù)和分支事務(wù)的狀態(tài),驅(qū)動全局提交或回滾。 事務(wù)管理器 TM:定義全局事務(wù)的范圍:開始全局事務(wù),提交或回滾全局事務(wù)。 資源管理器(RM):管理分支事務(wù)正在處理的資源,與 TC 進行對話以注冊分支事務(wù)并報告分支事務(wù)的狀態(tài),并驅(qū)動分支事務(wù)的提交或回滾。 Seata 管理的分布式事務(wù)的典型生命周期:TM 要求 TC 開始一項新的全球交易。TC 生成代表全局事務(wù)的 XID。 XID 通過微服務(wù)的調(diào)用鏈傳播。 RM 將本地事務(wù)注冊為 XID 到 TC 的相應(yīng)全局事務(wù)的分支。 TM 要求 TC 提交或回滾 XID 的相應(yīng)全局事務(wù)。 TC 驅(qū)動 XID 對應(yīng)的全局事務(wù)下的所有分支事務(wù)以完成分支提交或回滾。
完整的分布式架構(gòu)如下圖: 這就是一套分布式基本的架構(gòu),請求從瀏覽器發(fā)出,經(jīng)過 Nginx 反向代理到 Zuul 網(wǎng)關(guān)。網(wǎng)關(guān)經(jīng)過權(quán)限校驗、然后分別轉(zhuǎn)發(fā)到對應(yīng)的服務(wù)中,每個服務(wù)都有自己獨立的數(shù)據(jù)庫,如果需要跨庫查詢的時候就需要用到分布式的遠程調(diào)用(Feign)。雖然這里我將服務(wù)拆分了,但是有一點需要注意的是網(wǎng)關(guān),網(wǎng)關(guān)承載著所有的請求,如果請求過大會發(fā)生什么呢?服務(wù)宕機,所以一般情況下,網(wǎng)關(guān)都是集群部署,不止網(wǎng)關(guān)可以集群,其他的服務(wù)都可以做集群配置,比如:注冊中心、Redis、MQ 等等都可以。 現(xiàn)在這套架構(gòu)就是比較程數(shù)的一套了,不管是性能還是穩(wěn)定能,都是杠杠的,技術(shù)選擇性的會也開得差不多了,最后技術(shù)總監(jiān)做了一個總結(jié)。①單體服務(wù)與分布式服務(wù)區(qū)別 單體服務(wù)與分布式服務(wù)對比如下圖:②什么時候使用分布式/集群?單機無法支持的時候。 想要更好的隔離性(功能與功能)。 想要更好用戶體驗的時候。 想要更好的擴展性。 想要更快的響應(yīng),更搞得吞吐量。
③使用分布式注意事項雖然現(xiàn)在分布式技術(shù)已經(jīng)十分成熟,但是里面的坑不是一點兩點,比如:==如何保證分布式事務(wù)的一致性、如何保證服務(wù)調(diào)用的冪等性、如何保證消息的冪等性、如何設(shè)置熔斷(服務(wù)的降級),如何保證服務(wù)的健壯性等等,==這些都是一直需要關(guān)注的問題,只有解決了這些問題,你的分布式架構(gòu)才能真正的立于不敗之地。④關(guān)于組件停更消息目前注冊中心 Eureka、網(wǎng)關(guān) Zuul,F(xiàn)eign 都相繼停更了,停更不代表不能使用,只是除了 Bug 可能不會主動修復(fù),所以這個時候我們可能就需要選擇另外的組件了。注冊中心可以使用 Consul、Nacos,Zookeeper,網(wǎng)關(guān)則可以通過 Gateway 替換,OpenFeign 替換 Fiegn。所以也沒必要聽到組件停更的消息就擔心 Cloud 會不會涼,放心,它至少最近幾年是不會涼的。  技術(shù)總監(jiān)總結(jié)完之后,就離開了會議室,也到了下班時間,由于我在會上出色的表現(xiàn),今天晚上不用加班了,終于可讓我的頭發(fā)掉的慢一點了。編輯:陶家龍
出處:https:///post/5ea6acb8e51d454ddf2346ee#heading-18
|