SpringCloud微服務學習筆記
SpringCloud微服務學習筆記
項目地址: https://github.com/taoweidong/Micro-service-learning
單體架構(Monolithic架構)
Monolithic比較適合小項目
單體架構優點:
- 開發簡單直接,集中式管理, 基本不會重復開發功能都在本地,沒有分布式的管理開銷和調用開銷。
單體架構缺點:
- 開發效率低:所有的開發在一個項目改代碼,遞交代碼相互等待,代碼沖突不斷
- 代碼維護難:代碼功能耦合在一起,新人不知道何從下手
- 部署不靈活:構建時間長,任何小修改必須重新構建整個項目,這個過程往往很長
- 穩定性不高:一個微不足道的小問題,可以導致整個應用掛掉
- 擴展性不夠:無法滿足高並發情況下的業務需求
微服務架構
? 微服務是指開發一個單個小型的但有業務功能的服務,每個服務都有自己的處理和輕量通訊機制,可以部署在單個或多個服務器上。微服務也指一種種松耦合的、有一定的有界上下文的面向服務架構。也就是說,如果每個服務都要同時修改,那麽它們就不是微服務,因為它們緊耦合在一起;如果你需要掌握一個服務太多的上下文場景使用條件,那麽它就是一個有上下文邊界的服務,這個定義來自DDD領域驅動設計。
? 微服務架構模式(MicroservicesArchitecture Pattern)的目的是將大型的、復雜的、長期運行的應用程序構建為一組相互配合的服務,每個服務都可以很容易得局部改良。Micro這個詞意味著每個服務都應該足夠小,但是,這裏的小不能用代碼量來比較,而應該是從業務邏輯上比較——符合SRP原則的才叫微服務。
相對於單體架構和SOA,它的主要特點是組件化、松耦合、自治、去中心化,體現在以下幾個方面:
- 一組小的服務
服務粒度要小,而每個服務是針對一個單一職責的業務能力的封裝,專註做好一件事情。 - 獨立部署運行和擴展
每個服務能夠獨立被部署並運行在一個進程內。這種運行和部署方式能夠賦予系統靈活的代碼組織方式和發布節奏,使得快速交付和應對變化成為可能。 - 獨立開發和演化
技術選型靈活,不受遺留系統技術約束。合適的業務問題選擇合適的技術可以獨立演化。服務與服務之間采取與語言無關的API進行集成。相對單體架構,微服務架構是更面向業務創新的一種架構模式。 - 獨立團隊和自治
團隊對服務的整個生命周期負責,工作在獨立的上下文中,自己決策自己治理,而不需要統一的指揮中心。團隊和團隊之間通過松散的社區部落進行銜接。
? 我們可以看到整個微服務的思想就如我們現在面對信息爆炸、知識爆炸是一樣的:通過解耦我們所做的事情,分而治之以減少不必要的損耗,使得整個復雜的系統和組織能夠快速的應對變化。
微服務優點
- 每個微服務都很小,這樣能聚焦一個指定的業務功能或業務需求。
- 微服務能夠被小團隊單獨開發,這個小團隊是2到5人的開發人員組成。
- 微服務是松耦合的,是有功能意義的服務,無論是在開發階段或部署階段都是獨立的。
- 微服務能使用不同的語言開發。
- 微服務允許容易且靈活的方式集成自動部署,通過持續集成工具,如Jenkins, bamboo 。
- 一個團隊的新成員能夠更快投入生產。
- 微服務易於被一個開發人員理解,修改和維護,這樣小團隊能夠更關註自己的工作成果。無需通過合作才能體現價值。
- 微服務允許你利用融合最新技術。
- 微服務只是業務邏輯的代碼,不會和HTML,CSS 或其他界面組件混合。
- 微服務能夠即時被要求擴展。
- 微服務能部署中低端配置的服務器上。
- 易於和第三方集成。
- 每個微服務都有自己的存儲能力,可以有自己的數據庫。也可以有統一數據庫。
微服務架構的缺點
- 微服務架構可能帶來過多的操作。
- 需要DevOps技巧 (http://en.wikipedia.org/wiki/DevOps).
- 可能雙倍的努力。
- 分布式系統可能復雜難以管理。
- 因為分布部署跟蹤問題難。
- 當服務數量增加,管理復雜性增加。
技術介紹
服務註冊中心:Eureka
Eureka是Spring Cloud Netflix微服務套件中的一部分,可以與Springboot構建的微服務很容易的整合起來。
Eureka包含了服務器端和客戶端組件。
服務器端,也被稱作是服務註冊中心,用於提供服務的註冊與發現。Eureka支持高可用的配置,當集群中有分片出現故障時,Eureka就會轉入自動保護模式,它允許分片故障期間繼續提供服務的發現和註冊,當故障分片恢復正常時,集群中其他分片會把他們的狀態再次同步回來。
客戶端組件包含服務消費者與服務生產者。在應用程序運行時,Eureka客戶端向註冊中心註冊自身提供的服務並周期性的發送心跳來更新它的服務租約。同時也可以從服務端查詢當前註冊的服務信息並把他們緩存到本地並周期性的刷新服務狀態。
參考:
https://www.cnblogs.com/demodashi/p/8509931.html
https://www.cnblogs.com/snowjeblog/p/8821325.html
作為服務註冊中心,Eureka比Zookeeper好在哪裏
著名的CAP理論指出,一個分布式系統不可能同時滿足C(一致性)、A(可用性)和P(分區容錯性)。由於分區容錯性在是分布式系統中必須要保證的,因此我們只能在A和C之間進行權衡。在此Zookeeper保證的是CP, 而Eureka則是AP。
Zookeeper保證CP
當向註冊中心查詢服務列表時,我們可以容忍註冊中心返回的是幾分鐘以前的註冊信息,但不能接受服務直接down掉不可用。也就是說,服務註冊功能對可用性的要求要高於一致性。但是zk會出現這樣一種情況,當master節點因為網絡故障與其他節點失去聯系時,剩余節點會重新進行leader選舉。問題在於,選舉leader的時間太長,30 ~ 120s, 且選舉期間整個zk集群都是不可用的,這就導致在選舉期間註冊服務癱瘓。在雲部署的環境下,因網絡問題使得zk集群失去master節點是較大概率會發生的事,雖然服務能夠最終恢復,但是漫長的選舉時間導致的註冊長期不可用是不能容忍的。
Eureka保證AP
Eureka看明白了這一點,因此在設計時就優先保證可用性。Eureka各個節點都是平等的,幾個節點掛掉不會影響正常節點的工作,剩余的節點依然可以提供註冊和查詢服務。而Eureka的客戶端在向某個Eureka註冊或時如果發現連接失敗,則會自動切換至其它節點,只要有一臺Eureka還在,就能保證註冊服務可用(保證可用性),只不過查到的信息可能不是最新的(不保證強一致性)。除此之外,Eureka還有一種自我保護機制,如果在15分鐘內超過85%的節點都沒有正常的心跳,那麽Eureka就認為客戶端與註冊中心出現了網絡故障,此時會出現以下幾種情況:
- Eureka不再從註冊列表中移除因為長時間沒收到心跳而應該過期的服務
- Eureka仍然能夠接受新服務的註冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用)
- 當網絡穩定時,當前實例新的註冊信息會被同步到其它節點中
因此, Eureka可以很好的應對因網絡故障導致部分節點失去聯系的情況,而不會像zookeeper那樣使整個註冊服務癱瘓。
聲明式客戶端訪問:Fegin
? Feign是一個聲明式的偽Http客戶端,它使得寫Http客戶端變得更簡單。使用Feign,只需要創建一個接口並用註解的方式來配置它,即可完成對服務提供方的接口綁定,簡化了在使用Ribbon時自行封裝服務調用客戶端的開發量。
? Feign具有可插拔的註解特性,包括Feign 註解和JAX-RS註解,同時也擴展了對SpringMVC的註解支持。Feign支持可插拔的編碼器和解碼器,默認集成了Ribbon,並和Eureka結合,默認實現了負載均衡的效果。
主要功能:簡化服務消費者調用服務提供者接口
參考:https://www.cnblogs.com/senlinyang/p/8595489.html
客戶端負載均衡:Ribbon
? Ribbon是Netflix發布的負載均衡器,它有助於控制HTTP和TCP的客戶端的行為。為Ribbon配置服務提供者地址後,Ribbon就可基於某種負載均衡算法,自動地幫助服務消費者去請求。Ribbon默認為我們提供了很多負載均衡算法,例如輪詢、隨機等。當然,我們也可為Ribbon實現自定義的負載均衡算法。
? 在Spring Cloud中,當Ribbon與Eureka配合使用時,Ribbon可自動從Eureka Server獲取服務提供者地址列表,並基於負載均衡算法,請求其中一個服務提供者實例。展示了Ribbon與Eureka配合使用時的架構。
參考:https://blog.csdn.net/chengqiuming/article/details/80711168
服務斷路器:Hystrix
所謂的熔斷機制和日常生活中見到電路保險絲是非常相似的,當出現了問題之後,保險絲會自動燒斷,以保護我們的電器, 那麽如果換到了程序之中呢?
當現在服務的提供方出現了問題之後整個的程序將出現錯誤的信息顯示,而這個時候如果不想出現這樣的錯誤信息,而希望替換為一個錯誤時的內容。
一個服務掛了後續的服務跟著不能用了,這就是雪崩效應
對於熔斷技術的實現需要考慮以下幾種情況:
出現錯誤之後可以 fallback 錯誤的處理信息;
如果要結合 Feign 一起使用的時候還需要在 Feign(客戶端)進行熔斷的配置。
Hystrix如何解決依賴隔離
- Hystrix使用命令模式HystrixCommand(Command)包裝依賴調用邏輯,每個命令在單獨線程中/信號授權下執行。
- 可配置依賴調用超時時間,超時時間一般設為比99.5%平均時間略高即可.當調用超時時,直接返回或執行fallback邏輯。
- 為每個依賴提供一個小的線程池(或信號),如果線程池已滿調用將被立即拒絕,默認不采用排隊.加速失敗判定時間。
- 依賴調用結果分:成功,失敗(拋出異常),超時,線程拒絕,短路。 請求失敗(異常,拒絕,超時,短路)時執行fallback(降級)邏輯。
- 提供熔斷器組件,可以自動運行或手動調用,停止當前依賴一段時間(10秒),熔斷器默認錯誤率閾值為50%,超過將自動運行。
- 提供近實時依賴的統計和監控
Hystrix依賴的隔離架構,如下圖:
參考:https://www.cnblogs.com/leeSmall/p/8847652.html
https://www.cnblogs.com/yepei/p/7169127.html
斷路器聚合監控:Hystrix Turbine
? 看單個的Hystrix Dashboard的數據並沒有什麽多大的價值,要想看這個系統的Hystrix Dashboard數據就需要用到Hystrix Turbine。Hystrix Turbine將每個服務Hystrix Dashboard數據進行了整合。Hystrix Turbine的使用非常簡單,只需要引入相應的依賴和加上註解和配置就可以了。
參考:https://www.cnblogs.com/allalongx/p/8383757.html
微服務網關:Zuul
zuul 是netflix開源的一個API Gateway 服務器, 本質上是一個web servlet應用。
Zuul 在雲平臺上提供動態路由,監控,彈性,安全等邊緣服務的框架。Zuul 相當於是設備和 Netflix 流應用的 Web 網站後端所有請求的前門。
zuul的工作原理
zuul的核心是一系列的filters, 其作用可以類比Servlet框架的Filter,或者AOP。
zuul把Request route到 用戶處理邏輯 的過程中,這些filter參與一些過濾處理,比如Authentication,Load Shedding等。
Zuul提供了一個框架,可以對過濾器進行動態的加載,編譯,運行。
Zuul的過濾器之間沒有直接的相互通信,他們之間通過一個RequestContext的靜態類來進行數據傳遞的。RequestContext類中有ThreadLocal變量來記錄每個Request所需要傳遞的數據。
Zuul的過濾器是由Groovy寫成,這些過濾器文件被放在Zuul Server上的特定目錄下面,Zuul會定期輪詢這些目錄,修改過的過濾器會動態的加載到Zuul Server中以便過濾請求使用。
下面有幾種標準的過濾器類型:
Zuul大部分功能都是通過過濾器來實現的。Zuul中定義了四種標準過濾器類型,這些過濾器類型對應於請求的典型生命周期。
(1) PRE:這種過濾器在請求被路由之前調用。我們可利用這種過濾器實現身份驗證、在集群中選擇請求的微服務、記錄調試信息等。
(2) ROUTING:這種過濾器將請求路由到微服務。這種過濾器用於構建發送給微服務的請求,並使用Apache HttpClient或Netfilx Ribbon請求微服務。
(3) POST:這種過濾器在路由到微服務以後執行。這種過濾器可用來為響應添加標準的HTTP Header、收集統計信息和指標、將響應從微服務發送給客戶端等。
(4) ERROR:在其他階段發生錯誤時執行該過濾器。
參考:https://www.cnblogs.com/lexiaofei/p/7080257.html
https://www.cnblogs.com/xd03122049/p/6036318.html
配置中心:Spring Cloud Config
? Spring Cloud Config為分布式系統中的外部配置提供服務器和客戶端支持。使用Config Server,您可以為所有環境中的應用程序管理其外部屬性。它非常適合spring應用,也可以使用在其他語言的應用上。隨著應用程序通過從開發到測試和生產的部署流程,您可以管理這些環境之間的配置,並確定應用程序具有遷移時需要運行的一切。服務器存儲後端的默認實現使用git,因此它輕松支持標簽版本的配置環境,以及可以訪問用於管理內容的各種工具。
Spring Cloud Config服務端特性
- HTTP,為外部配置提供基於資源的API(鍵值對,或者等價的YAML內容)
- 屬性值的加密和解密(對稱加密和非對稱加密)
- 通過使用@EnableConfigServer在Spring boot應用中非常簡單的嵌入。
Config客戶端的特性(特指Spring應用)
- 綁定Config服務端,並使用遠程的屬性源初始化Spring環境。
- 屬性值的加密和解密(對稱加密和非對稱加密)
參考:https://www.cnblogs.com/boboooo/p/8796636.html?utm_source=debugrun&utm_medium=referral
服務總線:spring cloud bus
? 我們如果要去更新所有微服務的配置,在不重啟的情況下去更新配置,只能依靠spring cloud config了,但是,是我們要一個服務一個服務的發送post請求,
? 我們能受的了嗎?這比之前的沒配置中心好多了,那麽我們如何繼續避免挨個挨個的向服務發送Post請求來告知服務,你的配置信息改變了,需要及時修改內存中的配置信息。
? 這時候我們就不要忘記消息隊列的發布訂閱模型。讓所有為服務來訂閱這個事件,當這個事件發生改變了,就可以通知所有微服務去更新它們的內存中的配置信息。這時Bus消息總線就能解決,你只需要在springcloud Config Server端發出refresh,就可以觸發所有微服務更新了。
架構圖:
原理:
參考:https://www.cnblogs.com/huangjuncong/p/9077099.html
https://www.cnblogs.com/songxh-scse/p/7833963.html
構建異構平臺的服務註冊與通信:sidecar
? Spring Cloud是目前非常流行的微服務化解決方案,它將Spring Boot的便捷開發和Netflix OSS的豐富解決方案結合起來。如我們所知,Spring Cloud不同於Dubbo,使用的是基於HTTP(s)的Rest服務來構建整個服務體系。
那麽有沒有可能使用一些非JVM語言,例如我們所熟悉的Node.js來開發一些Rest服務呢?當然是可以的。但是如果只有Rest服務,還不能接入Spring Cloud系統。我們還想使用起Spring Cloud提供的Eureka進行服務發現,使用Config Server做配置管理,使用Ribbon做客戶端負載均衡。這個時候Spring sidecar就可以大顯身手了。
Sidecar起源於Netflix Prana。他提供一個可以獲取既定服務所有實例的信息(例如host,端口等)的http api。你也可以通過一個嵌入的Zuul,代理服務到從Eureka獲取的相關路由節點。Spring Cloud Config Server可以直接通過主機查找或通過代理Zuul進行訪問。
? 需要註意的是你所開發的Node.js應用,必須去實現一個健康檢查接口,來讓Sidecar可以把這個服務實例的健康狀況報告給Eureka。
理解:簡單來說sidecar就是可以讓非java開發的微服務也可以在SpringCloud組建中使用,利用Eureka,Config等功能。
參考:https://blog.csdn.net/shenzhen_zsw/article/details/81009238
https://www.jianshu.com/p/2788b7220407
微服務鏈路跟蹤:Zipkin
? Zipkin是一款開源的分布式實時數據追蹤系統(Distributed Tracking System),基於 Google Dapper的論文設計而來,由 Twitter 公司開發貢獻。其主要功能是聚集來自各個異構系統的實時監控數據。分布式跟蹤系統還有其他比較成熟的實現,例如:Naver的Pinpoint、Apache的HTrace、阿裏的鷹眼Tracing、京東的Hydra、新浪的Watchman,美團點評的CAT,skywalking等。
如圖,在復雜的調用鏈路中假設存在一條調用鏈路響應緩慢,如何定位其中延遲高的服務呢?
- 日誌: 通過分析調用鏈路上的每個服務日誌得到結果
- zipkin:使用
zipkin
的web UI
可以一眼看出延遲高的服務
參考:https://blog.csdn.net/qq924862077/article/details/80285536
項目實際測試
測試:基本微服務測試
啟動微服務註冊中心Eureka:microservice-discovery-eureka 賬戶:admin 密碼:admin123
訪問註冊中心地址:http://127.0.0.1:8761/
啟動服務提供者:microservice-provider-user
啟動服務消費者:microservice-consume-movie
打開註冊中心檢查服務是否註冊
訪問消費者接口1:http://127.0.0.1:9100/say 此時沒有進行服務間的調用,只是單純的訪問服務消費者
訪問消費者接口2:http://127.0.0.1:9100/say2 此時消費者調用提供者,進行服務間的通訊,此時服務請求沒有參數並且返回數據為字符串
訪問消費者接口3:http://127.0.0.1:9100/getUserInfo/1 此時進行服務間通訊,並且請求帶有參數返回數據為對象
對應腳本:microservice-test01.bat
測試:客戶端負載均衡服務測試
啟動微服務註冊中心Eureka:microservice-discovery-eureka 賬戶:admin 密碼:admin123
訪問註冊中心地址:http://127.0.0.1:8761/
啟動服務提供者:microservice-provider-user1
啟動服務提供者:microservice-provider-user2
啟動服務消費者:microservice-consume-movie-feign
對應腳本:microservice-test02.bat
測試:Hystrix熔斷機制
- 啟動Eureka註冊中心:microservice-discovery-eureka
- 啟動服務提供者:microservice-provider-user
- 啟動服務消費者: microservice-consume-movie-feign-hystrix 其中包括Hystrix熔斷機制的方法回退
測試:Hystrix熔斷控制面板
- 啟動Eureka註冊中心:microservice-discovery-eureka
- 啟動服務提供者:microservice-provider-user
- 啟動服務消費者: microservice-consume-movie-feign-hystrix 其中包括Hystrix熔斷機制的方法回退
註意:此項目必須要確保被監控的服務打開了Actuator(依賴spring-boot-starter-actuator),
啟動程序開啟了斷路器(@EnableCircuitBreaker註解)。 - 啟動Hystrix DashBoard監控項目: microservice-hystrix-dashboard
註意:此項目無需註冊到Eureka中 - 訪問註冊中心: http://127.0.0.1:8761/ 檢查服務是否啟動
- 訪問服務消費者: http://127.0.0.1:9103/say2
- 訪問監控面板: http://127.0.0.1:9090/hystrix
填寫相應參數:http://127.0.0.1:9103/hystrix.stream
測試:路由規則
- 啟動服務註冊中心項目:microservice-discovery-eureka
- 啟動服務提供者項目:microservice-provider-user
- 啟動服務消費者項目:microservice-consume-movie-ribbon
- 啟動路由網關項目: microservice-getway-zuul
- 訪問:http://127.0.0.1:8761/ 檢查服務是否啟動成功
- 訪問:http://127.0.0.1:8040/microservice-consume-movie-ribbon/say2 檢查服務是否成功
- 訪問:http://127.0.0.1:8040/microservice-provider-user/getUser 檢查服務是否成功
Zuul路由規則:http://ZUUL_HOST:ZUUL_PORT/微服務在Eureka上的serviceId/會被轉發到serviceId對應的微服務上**
測試:負載均衡功能
- 啟動服務註冊中心:microservice-discovery-eureka
- 啟動多個服務提供者:microservice-provider-user(端口不同)
- 啟動路由網關項目:microservice-getway-zuul
- 訪問:http://127.0.0.1:8761/ 檢查服務是否啟動成功
多次訪問192.168.224.1:8040/microservice-provider-user/hello,會發現兩個服務提供者循環顯示,說明Zuul可以使用Ribbon達到負載均衡的效果
測試:Hystrix容錯與監控功能
- 啟動服務註冊中心項目:microservice-discovery-eureka
- 啟動服務提供者項目:microservice-provider-user
- 啟動服務消費者項目:microservice-consume-movie-ribbon
- 啟動路由網關項目: microservice-getway-zuul
- 啟動服務監控項目: microservice-hystrix-dashboard
- 訪問:http://127.0.0.1:8761/ 檢查服務是否啟動成功
- 訪問:192.168.224.1:8040/microservice-consume-movie-feign-hystrix3/say2 獲得預期效果
- 訪問服務監控:http://127.0.0.1:9090/hystrix 輸入:http://192.168.224.1:8040/hystrix.stream(網關地址),結果顯示
SpringCloud微服務學習筆記