分布式架構(gòu)的演進(jìn)
在軟件行業(yè),一個(gè)應(yīng)用服務(wù)隨著功能越來越復(fù)雜,用戶量越來越大,尤其是互聯(lián)網(wǎng)行業(yè)流量爆發(fā)式的增長,導(dǎo)致我們需要不斷的重構(gòu)應(yīng)用的結(jié)構(gòu)來支撐龐大的用戶量,最終從一個(gè)簡單的系統(tǒng)主鍵演變成了一個(gè)非常復(fù)雜的可以支撐高并發(fā)的高可用的分布式架構(gòu),但是一個(gè)系統(tǒng)再復(fù)雜也是不斷演變來的,所以從另一方面來說,其實(shí)是業(yè)務(wù)(問題)推動(dòng)了技術(shù)的發(fā)展。
傳統(tǒng)的單體應(yīng)用
在早期,我們開發(fā)的都是單體應(yīng)用,也就是一個(gè)系統(tǒng)所有的模塊都在一個(gè)服務(wù)上:
這種傳統(tǒng)的應(yīng)用開發(fā)和運(yùn)維都非常簡單,隨著用戶量的增加,我們發(fā)現(xiàn)應(yīng)用程序的壓力越來越大,于是我們會(huì)選擇對(duì)應(yīng)用進(jìn)行集群部署:
當(dāng)然因?yàn)檫x擇了集群,我們就需要考慮服務(wù)分發(fā)的問題,所以需要有負(fù)載均衡服務(wù)器,比如我們最常用的 nginx,還有 lvs,HaProxy 等,硬件層面也可以選擇 F5 來實(shí)現(xiàn)負(fù)載均衡等等。
當(dāng)然,在使用了集群之后,我們還需要考慮 session 共享的問題,所以相比較單機(jī)架構(gòu)會(huì)稍微復(fù)雜一點(diǎn)點(diǎn),那么到這里我們應(yīng)用進(jìn)行了擴(kuò)展了,這時(shí)候發(fā)現(xiàn)數(shù)據(jù)庫又到瓶頸了,所以數(shù)據(jù)庫又需要進(jìn)行擴(kuò)展。
數(shù)據(jù)庫的擴(kuò)展可以有兩種主流方式:
讀寫分離
通過讀寫分離以及在某些場(chǎng)景用分布式存儲(chǔ)系統(tǒng)替換關(guān)系型數(shù)據(jù)庫的方式,能夠降低主庫的壓力,解決數(shù)據(jù)存儲(chǔ)方面的問題,不過隨著業(yè)務(wù)的發(fā)展,主庫依然會(huì)遇到瓶頸。
分庫分表
當(dāng)采用讀寫分離之后,如果再次遇到瓶頸,那么就可以采用垂直拆分的方式來實(shí)現(xiàn),垂直拆分的意思是把數(shù)據(jù)庫中不同的業(yè)務(wù)數(shù)據(jù)拆分到不同的數(shù)據(jù)庫中。但是這樣有些熱門模塊依然遲早會(huì)遇到瓶頸,于是可以更進(jìn)一步采用水平拆分,水平拆分就是把同一個(gè)表的數(shù)據(jù)拆分到不同的數(shù)據(jù)庫中。
垂直拆分還比較容易處理,畢竟同一個(gè)模塊的數(shù)據(jù)還是在一起,水平拆分就會(huì)比較復(fù)雜了,比如說用戶表拆成了兩張,存在不同的數(shù)據(jù)庫中,那么存的時(shí)候到底該存的哪個(gè)庫,取的時(shí)候又該到哪個(gè)庫去查詢,所以水平拆分需要考慮以下問題:
- 插入和查詢的路由問題,需要根據(jù)某一個(gè)條件來決定當(dāng)前數(shù)據(jù)應(yīng)該分到哪個(gè)庫。
- 主鍵的處理,主鍵不能采用自增主鍵的形式,因?yàn)椴煌膸觳捎米栽鲋麈I會(huì)有沖突。
- 如果某些查詢需要到兩個(gè)庫去查詢,會(huì)比較難處理。
數(shù)據(jù)庫的拆分可以使用當(dāng)前比較流行的 Sharding JDBC 或者 MyCat 來實(shí)現(xiàn),這時(shí)候的架構(gòu)大致就會(huì)如下圖所示:
當(dāng)然,為了進(jìn)一步優(yōu)化,可以視情況加入緩存層,或者使用消息隊(duì)列等技術(shù)來削峰等優(yōu)化措施。
分布式架構(gòu)
分布式架構(gòu)是指位于網(wǎng)絡(luò)計(jì)算機(jī)上的各個(gè)組件(系統(tǒng))僅通過傳遞消息來通信和協(xié)調(diào)目標(biāo)系統(tǒng),分布式系統(tǒng)其實(shí)也可以認(rèn)為是一種去中心化的實(shí)現(xiàn)思路,對(duì)于用戶來說是無感知的。
分布式架構(gòu)的意義
從單機(jī)單用戶到單機(jī)多用戶,再到現(xiàn)在的網(wǎng)絡(luò)時(shí)代,應(yīng)用系統(tǒng)發(fā)生了很多的變化,為什么單體架構(gòu)會(huì)逐漸滿足不了需求轉(zhuǎn)而要采用分布式架構(gòu)呢?
原因主要有以下幾點(diǎn):
- 升級(jí)單機(jī)處理能力的性價(jià)比越來越低。
- 單機(jī)處理能力存在瓶頸,一臺(tái)服務(wù)器的處理能力始終是會(huì)有上限的。
- 對(duì)于穩(wěn)定性和可用性的要求,單機(jī)環(huán)境下無法提供,一旦單機(jī)應(yīng)用掛了,整個(gè)系統(tǒng)就全部掛了,而分布式架構(gòu)則不會(huì)存在這個(gè)問題,某一個(gè)模塊不可用并不會(huì)導(dǎo)致整個(gè)系統(tǒng)的不可用。
SOA 架構(gòu)
SOA 全稱為 Service Oriented Architecture,即面向服務(wù)架構(gòu)。SOA 是一種架構(gòu)理念。它的提出主要是解決服務(wù)之間的耦合問題。
SOA 對(duì)服務(wù)之間的解耦是一種比較粗粒度的劃分,比如我們的電商網(wǎng)站按服務(wù)可以拆分為:用戶模塊,訂單模塊,商品模塊等。SOA 其本質(zhì)上是服務(wù)的集合,然后服務(wù)間一般會(huì)通過 ESB 總線來進(jìn)行通信。比如之前比較常用的 webservice 就是一種 SOA 架構(gòu)的實(shí)現(xiàn)。
微服務(wù)架構(gòu)
微服務(wù)架構(gòu)在 SOA 架構(gòu)的基礎(chǔ)上做了進(jìn)一步的細(xì)化,微服務(wù)架構(gòu)和 SOA 架構(gòu)并沒有本質(zhì)上的區(qū)別,都是為了服務(wù)的解耦,只不過微服務(wù)架構(gòu)更加關(guān)注服務(wù)的粒度,比如上面提到的用戶模塊我們還可以進(jìn)一步拆分成更細(xì)粒度的服務(wù)。
隨著微服務(wù)架構(gòu)的普及,原本一個(gè)單體應(yīng)用可能會(huì)被拆分成幾十個(gè)甚至更多的服務(wù),從應(yīng)用的壓力上來說,我們把壓力進(jìn)行了分流,但是原本一個(gè)服務(wù)變成了多個(gè)服務(wù)對(duì)開發(fā)者和運(yùn)維者來說也帶來了極大的挑戰(zhàn),這也就隨之衍生了一些技術(shù)組件,比如服務(wù)與與服務(wù)之間如何通信?單個(gè)服務(wù)如果是集群如何實(shí)現(xiàn)負(fù)載均衡?配置如何進(jìn)行統(tǒng)一管理?適合實(shí)現(xiàn)分流?如何實(shí)現(xiàn)監(jiān)控等。
注冊(cè)中心
各個(gè)微服務(wù)相互之間需要進(jìn)行調(diào)用,那么服務(wù)與服務(wù)之間又是如何知道對(duì)方的調(diào)用信息(如 ip,端口,路由等),最簡單最直接的辦法就是每個(gè)服務(wù)都維護(hù)一個(gè)其他需要調(diào)用的服務(wù)地址信息,但是這樣會(huì)給開發(fā)和運(yùn)維帶來相當(dāng)大的工作量,當(dāng)我們有某一個(gè)服務(wù) A 的地址信息發(fā)生變更,那么只要調(diào)用了 A 服務(wù)的其他所有服務(wù)都要隨之修改。而且假如 A 服務(wù)宕機(jī)了,其他服務(wù)也無法發(fā)現(xiàn),當(dāng)然,也可以做大發(fā)現(xiàn),但是這會(huì)相當(dāng)麻煩,而且每個(gè)服務(wù)都要重復(fù)實(shí)現(xiàn)這個(gè)功能,這會(huì)導(dǎo)致非常繁瑣和重復(fù)的工作,所以微服務(wù)常用組件中就有了注冊(cè)中心。
注冊(cè)中心是微服務(wù)架構(gòu)中一個(gè)核心的基礎(chǔ)服務(wù),主要用來管理所有的微服務(wù),并且注冊(cè)中心需要實(shí)現(xiàn)服務(wù)上線和下線的感知。
也就是說我們所有的微服務(wù)都將自己的地址信息注冊(cè)到注冊(cè)中心,然后其他調(diào)用者只需要維護(hù)注冊(cè)中心的地址即可,當(dāng)一個(gè)服務(wù)下線的時(shí)候,注冊(cè)中心也會(huì)及時(shí)將該服務(wù)剔除。
常用的注冊(cè)中心有:Eureka,consul,Nacos,其他的還有 Zookeeper,Redis 等也可以實(shí)現(xiàn)注冊(cè)中心。
遠(yuǎn)程通信協(xié)議
微服務(wù)之間各個(gè)服務(wù)可能會(huì)非常頻繁的調(diào)用,所以我們一定需要一款高效便捷的通訊協(xié)議來完成遠(yuǎn)程通信。
為什么使用 rpc 而不直接使用 http
回答這個(gè)問題之前我們先來回答另一個(gè)問題,微服務(wù)之間能不能直接使用 http 來進(jìn)行通信?答案是肯定的,但是直接使用 http 來作為遠(yuǎn)程通信會(huì)有以下問題:
- 請(qǐng)求和返回參數(shù)需要自己封裝,過程比較繁瑣。
- http 協(xié)議是基于 tcp 協(xié)議實(shí)現(xiàn)的,每次連接和斷開需要三次握手和四次揮手,這過程會(huì)帶來一定的網(wǎng)絡(luò)開銷。
基于上面兩個(gè)問題,我們需要另一種更加高效便捷的通信方式來完成微服務(wù)之間的通信,這就是 rpc 通信。
RPC(Remote Procedure Call)遠(yuǎn)程過程調(diào)用,它是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議,達(dá)到調(diào)用遠(yuǎn)程服務(wù)就像調(diào)用本地方法一樣,也就是調(diào)用者并不知道這個(gè)方法會(huì)具體去調(diào)用哪個(gè)服務(wù)。
不過需要強(qiáng)調(diào)的是 RPC 并不是一種協(xié)議,這一點(diǎn)和 http 是有本質(zhì)區(qū)別的,rpc 只是一種技術(shù)名詞,其底層實(shí)現(xiàn)也可以使用 http 協(xié)議,也可以基于 tcp 協(xié)議自己去進(jìn)行改造。
RPC 主要是用來解決兩個(gè)問題:
- 處理分布式架構(gòu)中各個(gè)微服務(wù)之間的通訊問題。
- 遠(yuǎn)程調(diào)用時(shí),調(diào)用者就像調(diào)用本地方法一樣方便。
常用的分布式服務(wù)之間遠(yuǎn)程通訊組件有:feign,openfeign,dubbo 等。
負(fù)載均衡
提到負(fù)載均衡大家的第一反應(yīng)就是 nginx,一般我們使用 http 通訊時(shí)大部分都會(huì)使用 nginx 作為負(fù)載均衡來處理,那么我們的微服務(wù)能否直接使用 nginx 來進(jìn)行負(fù)載呢?
答案是可以的,但是我們?yōu)槭裁床恢苯邮褂?nginx 作為服務(wù)轉(zhuǎn)發(fā)呢?我個(gè)人覺得主要有以下三個(gè)考慮:
- nginx 主要是一款基于 http 來進(jìn)行的 七層負(fù)載(當(dāng)然其也能實(shí)現(xiàn)四層負(fù)載),而我們的微服務(wù)通信之間不一定會(huì)基于 http 協(xié)議。
- 如果使用了 nginx,等于是微服務(wù)之間又多引入了一個(gè)單點(diǎn),我們還需要考慮 nginx 轉(zhuǎn)發(fā)的問題,還需要對(duì)其進(jìn)行配置調(diào)優(yōu)等。
- 微服務(wù)使用了注冊(cè)中心來進(jìn)行統(tǒng)一管理服務(wù)的上線和下線,而如果使用 nginx 那么就需要使用 openresty 結(jié)合 lua 腳本才能實(shí)現(xiàn)從注冊(cè)中心獲取服務(wù)。
也就是說直接使用 nginx 來進(jìn)行負(fù)載的話,技術(shù)上是可行的,但是卻可能會(huì)引入一些新的問題,所以微服務(wù)之間的負(fù)載均衡并沒有直接選擇使用 nginx,而是重新開發(fā)了負(fù)載均衡組件。
常用的分布式服務(wù)之間負(fù)載均衡組件有:ribbon 等。
配置中心
假如我們某一個(gè)模塊部署了幾十甚至上百個(gè)集群部署,那么如果每個(gè)服務(wù)都單獨(dú)使用自己的配置文件的話,一旦修改某一個(gè)配置,那么我們需要同時(shí)修改即使甚至上百個(gè)服務(wù)的配置,這是一個(gè)苦力活,所以我們就需要考慮讓這些服務(wù)共用同一套配置,這樣只要修改這一套配置,所有服務(wù)都能能生效。
配置中心主要就是用來解決這個(gè)問題,為了解決這個(gè)問題,配置中心需要具備以下能力:
- 提供配置文件的管理界面(dashboard),這樣使用者可以直接通過訪問 dashboard 來實(shí)現(xiàn)可視化配置。
- 配置中心配置修改之后,需要能及時(shí)通知到對(duì)應(yīng)服務(wù),讓對(duì)應(yīng)服務(wù)修改最新配置。
常用的分布式服務(wù)之間負(fù)載均衡組件有:apollo,nacos,Spring Cloud config,disconf,diamond,Zookeeper 等。
服務(wù)降級(jí)/熔斷
引入微服務(wù)我們的目的就是為了讓每一個(gè)微服務(wù)都成為一個(gè)獨(dú)立的單元,我們可以對(duì)每一個(gè)服務(wù)進(jìn)行獨(dú)立擴(kuò)展,實(shí)現(xiàn)高可用,假如現(xiàn)在有一個(gè)服務(wù) A 因?yàn)橐幌伦硬l(fā)量過高導(dǎo)致請(qǐng)求堆積,那么就會(huì)造成越來越多的請(qǐng)求阻塞,最終造成雪崩效應(yīng)導(dǎo)致服務(wù) A 宕機(jī),最終可能會(huì)導(dǎo)致整個(gè)微服務(wù)架構(gòu)不可用,所以為了保證高可用用,微服務(wù)需要提供一種降級(jí)和熔斷措施。
降級(jí)也可以分為主動(dòng)降級(jí)和被動(dòng)降級(jí),主動(dòng)降級(jí)就是在高峰期比如我關(guān)閉一些非核心功能,如:評(píng)論,留言等功能。
而熔斷一般指的是某一個(gè)方法或者接口負(fù)載過高,或者說因?yàn)榫W(wǎng)絡(luò)都動(dòng)等原因造成響應(yīng)超時(shí)或者失敗等,那么這時(shí)候應(yīng)該主動(dòng)觸發(fā)熔斷,也就是對(duì)后續(xù)請(qǐng)求不再處理而是直接返回,當(dāng)然這也要視具體業(yè)務(wù)來決定采用何種熔斷措施。
常用的分布式服務(wù)之間降級(jí)/熔斷組件有:Hystrix 和 Sentinel 等。
服務(wù)網(wǎng)關(guān)
微服務(wù)架構(gòu)是由單體服務(wù)架構(gòu)發(fā)展而來,一般我們一個(gè)一個(gè)微服務(wù)架構(gòu)其實(shí)是一個(gè)大的應(yīng)用系統(tǒng),那么必然這一個(gè)大的系統(tǒng)有公共部分,比如:統(tǒng)一授權(quán),統(tǒng)一路由,統(tǒng)一記錄日志,也可以進(jìn)行全局的限流措施等。
不過微服務(wù)網(wǎng)關(guān)并不是必須的,這些工作也可以放到每個(gè)服務(wù)中進(jìn)行處理。
常用的微服務(wù)網(wǎng)關(guān)組件有:Zuul,Spring Cloud GatWay。
這么多分布式組件該如何選擇
分布式架構(gòu)中主要有六大組件,而每個(gè)組件又有不同的實(shí)現(xiàn),看起來技術(shù)五花八門,感覺需要學(xué)的東西非常多,但是上面介紹了這么多分布式組件。
其實(shí)其主要就是三大類型:Spring Cloud Netflix
,Spring Cloud 官方
,Spring Cloud Alibaba
,下面我們對(duì)這些分布式組件進(jìn)行歸納分類,這樣大家在學(xué)習(xí)的時(shí)候就可以進(jìn)行有目的的針對(duì)性學(xué)習(xí):
Spring Cloud Netflix 是由 Netflix(美國奈飛)公司開源的一套分布式組件,這套組件應(yīng)該也是大家比較熟悉的一套分布式組件,不過其只有 1.0 版本開源,2.0 之后就不再開源了,Spring Cloud 官方自己也提供了部分組件,而且基于 Feign 的基礎(chǔ)上改造成了 Open Feign。
另外一套比較完整的分布式組件就是 Spring Cloud Alibaba,這是由阿里巴巴開源的的一套分布式組件,這套組件中的 dubbo 大家應(yīng)該也是比較熟悉的,除了這兩套組件外,其他的也有一些可以用來作為分布式組件,比如 Zookeeper,Consul 等,配置中心像 apollo 是攜程開源的,用的也比較多,所以大家學(xué)習(xí)的時(shí)候可以對(duì)同類組件進(jìn)行了解,并對(duì)比其特性,然后選擇一套適合自己系統(tǒng)的組件使用。
除了上面的六大分布式組件外,分布式架構(gòu)中還會(huì)涉及到另外兩個(gè)比較大的問題:
分布式消息
分布式消息一般就使用消息隊(duì)列,比如 Rabbit MQ,Rocket MQ(阿里巴巴體系),kafka 等。
分布式事務(wù)
分布式事務(wù)的話,Spring Cloud Alibaba 也提供了一個(gè)組件 seata 來實(shí)現(xiàn)。
另外分布式系統(tǒng)當(dāng)中還涉及到鏈路監(jiān)控相關(guān)問題,這方面可以選擇 sleuth + zipkin,pinponit,skywalking等等。所以說分布式架構(gòu)解決了單體架構(gòu)一些問題的同時(shí),也帶來了一些問題,但是技術(shù)總是在向前發(fā)展的,比如現(xiàn)在號(hào)稱為了微服務(wù)而生的 Kubernetes(k8s),又有號(hào)稱是下一代微服務(wù)架構(gòu)的 Service Mesh等。
一門技術(shù)的誕生總是為了解決一些問題,所以還是那句話:業(yè)務(wù)才是推動(dòng)技術(shù)發(fā)展的根本原因。 只有隨著業(yè)務(wù)的發(fā)展出現(xiàn)了問題,才會(huì)去解決問題,才有更好的促進(jìn)新技術(shù)的誕生。
比如現(xiàn)在流行的 docker,也是為了解決微服務(wù)過多導(dǎo)致部署困難問題,任何一門技術(shù)能得到發(fā)展,它一定是解決了當(dāng)前的痛點(diǎn),否則我們?yōu)槭裁匆褂盟??假如互?lián)網(wǎng)沒有興起,并發(fā)量始終很低,那么微服務(wù)也不會(huì)興起,直接使用傳統(tǒng)的單點(diǎn)應(yīng)用反而更簡單直接。
總結(jié)
本文主要講述了從單點(diǎn)應(yīng)用到分布式架構(gòu)的發(fā)展歷程,并且描述了微服務(wù)當(dāng)中為什么會(huì)誕生出一批組件,其根本原因就是為了解決微服務(wù)所帶來的的挑戰(zhàn)和問題,在文中最后對(duì)當(dāng)前流行的分布式架構(gòu)組件進(jìn)行了分類整理,幫助大家梳理思路,這樣就可以做到有目的的進(jìn)行針對(duì)性的學(xué)習(xí),希望通過本文能讓大家對(duì)微服務(wù)相關(guān)組件有一個(gè)清晰的學(xué)習(xí)思路。
原文鏈接:https://blog.csdn.net/zwx900102/article/details/121727985
版權(quán)聲明:本文為CSDN博主「雙子孤狼」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協(xié)程要來了。。。
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優(yōu)雅的方式??!
5.《Java開發(fā)手冊(cè)(嵩山版)》最新發(fā)布,速速下載!文章來源:http://www.zghlxwxcb.cn/news/detail-711676.html
覺得不錯(cuò),別忘了隨手點(diǎn)贊+轉(zhuǎn)發(fā)哦!文章來源地址http://www.zghlxwxcb.cn/news/detail-711676.html
到了這里,關(guān)于Spring Cloud 中的分布式組件五花八門,我到底該怎么學(xué)?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!