javascript
SpringCloud 超详细个人笔记
文章目錄
- SpringCloud
- 1、常見面試題
- 2、微服務(wù)概述
- 2.1、什么是微服務(wù)
- 2.2、微服務(wù)和微服務(wù)架構(gòu)
- 2.3、微服務(wù)優(yōu)缺點(diǎn)
- 2.4、微服務(wù)技術(shù)棧有哪些?
- 2.5、為什么選擇SpringCloud 作為微服務(wù)架構(gòu)
- 2.5.1、選型依據(jù)
- 2.5.2、當(dāng)前各大IT公司用的微服務(wù)架構(gòu)有哪些?
- 2.5.3、各微服務(wù)框架對(duì)比
- 3、SpringCloud 入門概述
- 3.1、SpringCloud是什么
- 3.2、SpringCloud 和 SpringBoot關(guān)系
- 3.3、Dubbo 和 SpringCloud技術(shù)選型
- 3.3.1、分布式 + 服務(wù)治理 Dubbo
- 3.3.2、Dubbo 和 SpringCloud 對(duì)比
- 3.4、SpringCloud 能干嘛
- 3.5、SpringCloud在哪下
- 4.1、總體介紹
- 4.2、SpringCloud版本選擇
- 4.3、創(chuàng)建父工程
- 5、Eureka服務(wù)注冊(cè)與發(fā)現(xiàn)
- 5.1、什么是Euraka
- 5.2、原理理解
- 5.3、構(gòu)建步驟
- 1、eureka-server
- 2.、eureka-client
- 3、actuator 與注冊(cè)微服務(wù)信息完善
- 4、Eureka 的自我保護(hù)機(jī)制
- 5、8001服務(wù)發(fā)現(xiàn)Discovery
- 5.4、Eureka:集群環(huán)境配置
- 5.4.1、初始化
- 5.4.2、集群成員相互關(guān)聯(lián)
- 5.5、對(duì)比Zookeeper
- 6、Ribbon
- 6.1、負(fù)載均衡以及Ribbon
- 6.2、集成Ribbon
- 6.3、使用Ribbon實(shí)現(xiàn)負(fù)載均衡
- 7、Feign:負(fù)載均衡(基于服務(wù)端)
- 7.1 、Feign簡(jiǎn)介
- 7.2、Feign的使用步驟
- 7.3、Feign和Ribbon如何選擇?
- 8、Hystrix:服務(wù)熔斷
- 8.1、服務(wù)雪崩
- 8.2、什么是Hystrix?
- 8.3、Hystrix能干嘛?
- 8.4、服務(wù)熔斷
- 8.5、服務(wù)降級(jí)
- 8.6、服務(wù)熔斷和降級(jí)的區(qū)別
- 8.7、Dashboard 流監(jiān)控
- 9、Zull路由網(wǎng)關(guān)
- 9.1、概述
- 10、Spring Cloud Config 分布式配置
- 10.1、概述
- 10.2、入門案例
- 服務(wù)端
- 客戶端
- 10.3、實(shí)戰(zhàn)測(cè)試
- 用戶級(jí)別的配置
SpringCloud
1、常見面試題
1.1、什么是微服務(wù)?
1.2、微服務(wù)之間是如何獨(dú)立通訊的?
1.3、SpringCloud和Dubbo有哪些區(qū)別?
1.4、SpringBoot和SpringCloud,請(qǐng)你談?wù)剬?duì)他們的理解
1.5、什么是服務(wù)熔斷?什么是服務(wù)降級(jí)
1.6、微服務(wù)的優(yōu)缺點(diǎn)是分別是什么?說下你在項(xiàng)目開發(fā)中遇到的坑
1.7、你所知道的微服務(wù)技術(shù)棧有哪些?請(qǐng)列舉一二
1.8、eureka和zookeeper都可以提供服務(wù)注冊(cè)與發(fā)現(xiàn)的功能,請(qǐng)說說兩個(gè)的區(qū)別?
2、微服務(wù)概述
2.1、什么是微服務(wù)
什么是微服務(wù)?微服務(wù)(Microservice Architecture)是近幾年流行的一種架構(gòu)思想,關(guān)于它的概念很難一言以蔽之。
究竟什么是微服務(wù)呢?我們?cè)诖藨?yīng)用 ThoughtWorks 公司的首席科學(xué)家 Martin Fowler 于2014年提出的一段話:
原文:https://martinfowler.com/articles/microservices.html
漢化:https://www.cnblogs.com/liuning8023/p/4493156.html
- 就目前而言,對(duì)于微服務(wù),業(yè)界應(yīng)沒有一個(gè)統(tǒng)一的,標(biāo)準(zhǔn)的定義
- 但通常而言,微服務(wù)架構(gòu)是一種架構(gòu)模式,或者說是一種架構(gòu)風(fēng)格,它提倡將單一的應(yīng)用程序劃分成一組小的服務(wù),每個(gè)服務(wù)器運(yùn)行在其獨(dú)立的自己的進(jìn)程內(nèi),服務(wù)之間相互協(xié)調(diào),互相配置,為用戶提供最終價(jià)值。服務(wù)之間采用輕量級(jí)的通信機(jī)制互相溝通,每個(gè)服務(wù)都圍繞著具體的業(yè)務(wù)進(jìn)行構(gòu)建,并且能夠被獨(dú)立的部署到生產(chǎn)環(huán)境中,另外,應(yīng)盡量避免統(tǒng)一的,集中式的服務(wù)管理機(jī)制,對(duì)具體的一個(gè)服務(wù)而言,應(yīng)根據(jù)業(yè)務(wù)上下文,選擇合適的語言,工具對(duì)其進(jìn)行構(gòu)建,可以一個(gè)非常輕量級(jí)的集中式管理來協(xié)調(diào)這些服務(wù),可以使用不同的語言來編寫服務(wù),也可以使用不同的數(shù)據(jù)存儲(chǔ);
可能有的人覺得官方的話太過生澀,我們從技術(shù)維度來理解下:
- 微服務(wù)化的核心就是將傳統(tǒng)的一站式應(yīng)用,根據(jù)業(yè)務(wù)拆分成一個(gè)一個(gè)的服務(wù),徹底地去耦合,每一個(gè)微服務(wù)提供單個(gè)業(yè)務(wù)功能的服務(wù),一個(gè)服務(wù)做一件事情,從技術(shù)角度看就是一種小而獨(dú)立的處理過程,類似進(jìn)程的概念,能夠自行單獨(dú)啟動(dòng)或銷毀,擁有自己獨(dú)立的數(shù)據(jù)庫。
2.2、微服務(wù)和微服務(wù)架構(gòu)
微服務(wù)
強(qiáng)調(diào)的是服務(wù)的大小,他關(guān)注的某一個(gè)點(diǎn),是具體解決某一個(gè)問題/提供落地對(duì)應(yīng)服務(wù)的一個(gè)服務(wù)應(yīng)用,狹義的看,可以看做是IDEA中的一個(gè)個(gè)微服務(wù)工程,或者M(jìn)oudel
IDEA 工具里面使用Maven開發(fā)的一個(gè)個(gè)獨(dú)立的小Moudle,它具體是使用springboot開發(fā)的一個(gè)小模塊,專業(yè)的事情交給專業(yè)的模塊來做,一個(gè)模塊就做著一件事情強(qiáng)調(diào)的是一個(gè)個(gè)的個(gè)體,每個(gè)個(gè)體完成一個(gè)具體的任務(wù)或者功能!微服務(wù)架構(gòu)
一種新的架構(gòu)形式,Martin Fowler, 2014提出
微服務(wù)架構(gòu)是一種架構(gòu)模式,它提倡將單一應(yīng)用程序劃分成一組小的服務(wù),服務(wù)之間互相協(xié)調(diào),互相配合,為用戶提供最終價(jià)值。每個(gè)服務(wù)運(yùn)行在其獨(dú)立的進(jìn)程中,服務(wù)與服務(wù)間采用輕量級(jí)的通信機(jī)制互相協(xié)作,每個(gè)服務(wù)都圍繞著具體的業(yè)務(wù)進(jìn)行構(gòu)建,并且能夠被獨(dú)立的部署到生產(chǎn)環(huán)境中,另外,應(yīng)盡量避免統(tǒng)一的,集中式的服務(wù)管理機(jī)制,對(duì)具體的一個(gè)服務(wù)而言,應(yīng)根據(jù)業(yè)務(wù)上下文,選擇合適的語言,工具對(duì)其進(jìn)行構(gòu)建。
2.3、微服務(wù)優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 單一職責(zé)原則
- 每個(gè)服務(wù)足夠內(nèi)聚,組夠小,代碼容易理解,這樣能聚集一個(gè)指定的業(yè)務(wù)功能或業(yè)務(wù)需求;
- 開發(fā)簡(jiǎn)單,開發(fā)效率提供,一個(gè)服務(wù)可能就是專一的只敢一件事;
- 微服務(wù)能夠被小團(tuán)隊(duì)單獨(dú)開發(fā),這個(gè)小團(tuán)隊(duì)是2~5人的開發(fā)人員組成;
- 微服務(wù)是松耦合的,是有功能意義的服務(wù),無論是在開發(fā)階段或者部署階段都是獨(dú)立的。
- 微服務(wù)能使用不同的語言開發(fā)。
- 易于和第三方繼承,微服務(wù)允許容易且靈活的方式集成自動(dòng)部署,通過持續(xù)繼承工具,如 Jenkins,Hudson,Bamboo
- 微服務(wù)易于被一個(gè)開發(fā)人員理解,修改和維護(hù),這樣小團(tuán)隊(duì)能夠功能關(guān)注自己的工作成果。無需通過合作才能體現(xiàn)價(jià)值。
- 微服務(wù)允許你利用融合最新技術(shù)
- 微服務(wù)知識(shí)業(yè)務(wù)邏輯的代碼,不會(huì)和 HTML,CSS 或其他界面混合
- 每個(gè)微服務(wù)都有自己的存儲(chǔ)能力,可以有自己的數(shù)據(jù)庫,也可以有同意數(shù)據(jù)庫
缺點(diǎn):
- 開發(fā)人員要處理分布式系統(tǒng)的復(fù)雜性
- 多服務(wù)運(yùn)維難度,隨著服務(wù)的增加,運(yùn)維的壓力也在增大
- 系統(tǒng)部署依賴
- 服務(wù)間通信成本
- 數(shù)據(jù)一致性
- 系統(tǒng)集成測(cè)試
- 性能監(jiān)控。。。。
2.4、微服務(wù)技術(shù)棧有哪些?
| 服務(wù)開發(fā) | SpringBoot,Spring,SpringMVC |
| 服務(wù)配置與管理 | Netflix公司的Archaius、阿里的Diamond等 |
| 服務(wù)注冊(cè)與發(fā)現(xiàn) | Eureka、Consul、Zookeeper等 |
| 服務(wù)調(diào)用 | Rest、RPC、gRPC |
| 服務(wù)熔斷器 | Hystrix、Envoy等 |
| 負(fù)載均衡 | Ribbon、Nginx等 |
| 服務(wù)接口調(diào)用(客戶端調(diào)用服務(wù)的簡(jiǎn)化工具) | Feign等 |
| 消息隊(duì)列 | Kafka、RabbitMQ、ActiveMQ等 |
| 服務(wù)配置中心管理 | SpringCloudConfig、chef等 |
| 服務(wù)路由(API網(wǎng)關(guān)) | Zuul等 |
| 服務(wù)監(jiān)控 | Zabbix、Nagios、Metrics、Specatator等 |
| 全鏈路追蹤 | Zipkin、Brave、Dapper等 |
| 服務(wù)部署 | Docker、OpenStack、Kubernetes等 |
| 數(shù)據(jù)流操作開發(fā)包 | SpringCloud Stream(封裝與Redis,Rabbit,Kafka等發(fā)送接收消息) |
| 事件消息總線 | SpringCloud Bus |
2.5、為什么選擇SpringCloud 作為微服務(wù)架構(gòu)
2.5.1、選型依據(jù)
- 整體解決方案和框架成熟度
- 社區(qū)熱度
- 可維護(hù)性
- 學(xué)習(xí)曲線
2.5.2、當(dāng)前各大IT公司用的微服務(wù)架構(gòu)有哪些?
- 阿里:dubbo + HFS
- 京東:JSF
- 新浪:Motan
- 當(dāng)當(dāng)網(wǎng):DubboX
- …
2.5.3、各微服務(wù)框架對(duì)比
| 功能定位 | 完整的微服務(wù)框架 | RPC框架,但整合了ZK或Consul,實(shí)現(xiàn)集群環(huán)境基本服務(wù)注冊(cè)/發(fā)現(xiàn) | RPC框架 | RPC框架 | 服務(wù)框架 |
| 支持Rest | 是,Ribbon支持多種可插拔的序列化選擇 | 否 | 否 | 否 | 否 |
| 支持RPC | 否 | 是(Hession2) | 是 | 是 | 是 |
| 支持多語言 | 是(Rest形式)? | 否 | 是 | 是 | 否 |
| 負(fù)載均衡 | 是(服務(wù)端zuul+客戶端Ribbon),zuul-服務(wù),動(dòng)態(tài)路由,云端負(fù)載均衡Eureka(針對(duì)中間層服務(wù)器) | 是(客戶端) | 否 | 否 | 是(客戶端) |
| 配置服務(wù) | Netfix Archaius,Spring Cloud Config Server集中配置 | 是(zookeeper提供) | 否 | 否 | 否 |
| 服務(wù)調(diào)用鏈監(jiān)控 | 是(zuul),zuul提供邊緣服務(wù),API網(wǎng)關(guān) | 否 | 否 | 否 | 否 |
| 高可用/容錯(cuò) | 是(服務(wù)端Hystrix + 客戶端Ribbon) | 是(客戶端) | 否 | 否 | 是(客戶端) |
| 典型應(yīng)用案例 | Netfix | Sina | |||
| 社區(qū)活躍程度 | 高 | 一般 | 高 | 一般 | 2017年后重新開始維護(hù),之前中斷了5年 |
| 學(xué)習(xí)難度 | 中 | 低 | 高 | 高 | 低 |
| 文檔豐富程度 | 高 | 一般 | 一般 | 一般 | 高 |
| 其他 | Spring Cloud Bus為我們的應(yīng)用程序帶來了更多管理端點(diǎn) | 支持降級(jí) | Netflix內(nèi)部在開發(fā)集成gRPC | IDL定義 | 實(shí)踐的公司比較多 |
3、SpringCloud 入門概述
3.1、SpringCloud是什么
Spring官網(wǎng):https://spring.io/
SpringCloud,基于SpringBoot提供了一套微服務(wù)解決方案,包括服務(wù)注冊(cè)于發(fā)現(xiàn),配置中心,全鏈路監(jiān)控, 服務(wù)網(wǎng)關(guān),負(fù)載均衡, 熔斷器等組件,除了基于NetFlix的開源組件做高度抽象封裝之外,還有一些選型中立的開源組件。
SpringCloud 利用SpringBoot的開發(fā)便利性,巧妙地簡(jiǎn)化了分布式系統(tǒng)基礎(chǔ)設(shè)施的開發(fā),SpringCloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)的寫工具,包括配置管理,服務(wù)發(fā)現(xiàn),斷路器,路由,微代理,事件總線,全局鎖,決策競(jìng)選,分布式會(huì)話等等,他們都可以用SpringBoot開發(fā)風(fēng)格做的一鍵啟動(dòng)和部署。
SpringCloud并沒有重復(fù)造輪子,他只是將目前各家公司開發(fā)的比較成熟,經(jīng)得起實(shí)際考驗(yàn)的服務(wù)框架組合起來,通過SpringBoot風(fēng)格進(jìn)行再封裝,屏蔽掉了復(fù)雜的配置和實(shí)現(xiàn)原理,最終給開發(fā)者流出來一套簡(jiǎn)單易懂,易部署和易維護(hù)的分布式系統(tǒng)開發(fā)工具包
SpringCloud 是 分布式微服務(wù)架構(gòu)下的一站式解決方案,是各個(gè)微服務(wù)架構(gòu)落地技術(shù)的集合體,俗稱微服務(wù)全家桶。
3.2、SpringCloud 和 SpringBoot關(guān)系
- SpringBoot 專注于快速方便的開發(fā)單個(gè)個(gè)體微服務(wù)。
- SpringCloud 是關(guān)注全局的微服務(wù)協(xié)調(diào)整理治理框架,他將SpringBoot開發(fā)的一個(gè)個(gè)單體微服務(wù)整合并管理起來,為各個(gè)微服務(wù)之間提供:配置管理,服務(wù)發(fā)現(xiàn),斷路器,路由,微代理,事件總線,全局鎖,決策競(jìng)選,分布式會(huì)話等等集成服務(wù)。
- SpringBoot可以離開SpringCloud獨(dú)立使用,開發(fā)項(xiàng)目,但是SpringCloud離不開SpringBoot,屬于依賴關(guān)系
- SpringBoot專注于快速開發(fā)、方便的開發(fā)單個(gè)個(gè)體微服務(wù),SpringCloud關(guān)注全局的服務(wù)治理框架
3.3、Dubbo 和 SpringCloud技術(shù)選型
3.3.1、分布式 + 服務(wù)治理 Dubbo
目前成熟的互聯(lián)網(wǎng)架構(gòu):應(yīng)用服務(wù)化拆分 + 消息中間件
3.3.2、Dubbo 和 SpringCloud 對(duì)比
可以看一下社區(qū)活躍度
https://github.com/dubbo
https://github.com/spring-cloud
結(jié)果:
| 服務(wù)注冊(cè)中心 | Zookeeper | Spring Cloud Netfilx Eureka |
| 服務(wù)調(diào)用方式 | RPC | REST API |
| 服務(wù)監(jiān)控 | Dubbo-monitor | Spring Boot Admin |
| 斷路器 | 不完善 | Spring Cloud Netflix Hystrix |
| 服務(wù)網(wǎng)關(guān) | 無 | Spring Cloud Netflix Zuul |
| 分布式配置 | 無 | Spring Cloud Config |
| 服務(wù)跟蹤 | 無 | Spring Cloud Sleuth |
| 消息總線 | 無 | Spring Cloud Bus |
| 數(shù)據(jù)流 | 無 | Spring Cloud Stream |
| 批量任務(wù) | 無 | Spring Cloud Task |
最大區(qū)別:SpringCloud 拋棄了 Dubbo 的 RPC 通信,采用的是基于HTTP的REST方式。
嚴(yán)格來說,這兩種方式各有優(yōu)劣。雖然從一定程度上來說,后者犧牲了服務(wù)調(diào)用的性能,但也避免了上面提到的原來RPC帶來的問題。而且REST相比RPC更為靈活,服務(wù)提供方和調(diào)用方的依賴只依靠一紙鍥約,不存在代碼級(jí)別的強(qiáng)依賴,這在強(qiáng)調(diào)快速演化的微服務(wù)環(huán)境下,顯得更加合適。
品牌機(jī)與組裝機(jī)的區(qū)別
很明顯,Spring Cloud的功能比DUBBO更加強(qiáng)大,涵蓋面更廣,而且作為Spring的拳頭項(xiàng)目,它也能夠與SpringFramework、Spring Boot、Spring Data、Spring Batch等其他Spring項(xiàng)目完美融合,這些對(duì)于微服務(wù)而言是至關(guān)重要的。使用Dubbo構(gòu)建的微服務(wù)架構(gòu)就像組裝電腦,各環(huán)節(jié)我們的選擇自由度很高,但是最終結(jié)果很有可能因?yàn)橐粭l內(nèi)存質(zhì)量不行就點(diǎn)不亮了,總是讓人不怎么放心,但是如果你是一名高手,那這些都不是問題;而SpringCloud就像品牌機(jī),在Spring Source的整合下,做了大量的兼容性測(cè)試,保證了機(jī)器擁有更高的穩(wěn)定性,但是如果要在使用非原裝組件外的東西,就需要對(duì)其基礎(chǔ)有足夠的了解。
社區(qū)支持與更新力度
最為重要的是,DUBBO停止了5年左右的更新,雖然2017.7重啟了。對(duì)于技術(shù)發(fā)展的新需求,需要由開發(fā)者自行拓展升級(jí)(比如當(dāng)當(dāng)網(wǎng)弄出了DubboX),這對(duì)于很多想要采用微服務(wù)架構(gòu)的中小軟件組織,顯然是不太合適的,中小公司沒有這么強(qiáng)大的技術(shù)能力去修改Dubbo源碼+周邊的一整套解決方案,并不是每一個(gè)公司都有阿里的大牛+真實(shí)的線上生產(chǎn)環(huán)境測(cè)試過。
總結(jié):
曾風(fēng)靡國內(nèi)的開源 RPC 服務(wù)框架 Dubbo 在重啟維護(hù)后,令許多用戶位置雀躍,但同時(shí),也迎來了一些質(zhì)疑的聲音。互聯(lián)網(wǎng)技術(shù)發(fā)展迅速,Dubbo 是否還能跟上時(shí)代?Dubbo 與 Spring Cloud 相比又有何優(yōu)勢(shì)和差異?是否會(huì)有相關(guān)舉措保證 Dubbo 的后續(xù)更新頻率?
人物:Dubbo重啟維護(hù)開發(fā)的劉軍,主要負(fù)責(zé)人之一
劉軍,阿里巴巴中間件高級(jí)研發(fā)工程師,主導(dǎo)了 Dubbo 重啟維護(hù)以后的幾個(gè)發(fā)版計(jì)劃,專注于高性能 RPC 框架和微服務(wù)相關(guān)領(lǐng)域。曾負(fù)責(zé)網(wǎng)易考拉 RPC 框架的研發(fā)及指導(dǎo)在內(nèi)部使用,參與了服務(wù)治理平臺(tái)、分布式跟蹤系統(tǒng)、分布式一致性框架等從無到有的設(shè)計(jì)與開發(fā)過程。
解決的問題域不一樣:Dubbo 的定位是一款RPC框架,Spring Cloud 的目標(biāo)是微服務(wù)架構(gòu)下的一站式解決方案
3.4、SpringCloud 能干嘛
- Distributed/versioned configuration(分布式/版本控制配置)
- Service registration and discovery(服務(wù)注冊(cè)與發(fā)現(xiàn))
- Routing(路由)
- Service-to-service calls(服務(wù)到服務(wù)的調(diào)用)
- Load balancing(負(fù)載均衡配置)
- Circuit Breakers(斷路器)
- Distributed messaging(分布式消息管理)
- …
3.5、SpringCloud在哪下
官網(wǎng):https://spring.io/projects/spring-cloud
這玩意兒版本號(hào)有點(diǎn)特別
spring cloud 是一個(gè)由眾多獨(dú)立子項(xiàng)目組成的大型綜合項(xiàng)目,每個(gè)子項(xiàng)目有不同的發(fā)行節(jié)奏,都維護(hù)著自己的發(fā)布版本號(hào)。 spring cloud 通過一個(gè)資源清單 BOM (Bi11 of Materials)來管理每個(gè)版本的子項(xiàng)目清單。為避免與子項(xiàng)目的發(fā)布號(hào)混 淆,所以沒有采用版本號(hào)的方式,而是通過命名的方式。這些版本名稱的命名方式采用了倫敦地鐵站的名稱,同時(shí)根據(jù)字母表的順序來對(duì)應(yīng)版本時(shí)間順序,比如: 最早的 Release版 本: Ange1,第二個(gè)Release版本: Brixton,然后是camden、Dalston、Edgware,目前最新的是Finchley版本。參考書:
- https://www.springcloud.cc/spring-cloud-netflix.html
- 中文API文檔:https://www.springcloud.cc/spring-cloud-dalston.html
- SpringCloud 中國社區(qū):http://springcloud.cn/
- SpringCloud 中文網(wǎng):https://www.springcloud.cc/
4.1、總體介紹
-
我們會(huì)使用 Dept 部分模塊做一個(gè)微服務(wù)通用案例 Consumer 消費(fèi)者 (Client)通過 REST 調(diào)用 Provider 提供者 (Server)提供的服務(wù)。
-
會(huì)議 Spring,SpringMVC,Mybatis 等以往學(xué)過的知識(shí)。。。
-
Maven 的分包分模塊架構(gòu)復(fù)習(xí)
一個(gè)簡(jiǎn)單的maven模塊結(jié)構(gòu)是這樣的:-- app-parent:一個(gè)府項(xiàng)目(app-parent)聚合很多子項(xiàng)目(app-util,app-dao,app-web...)|-- pom.xml||-- app-core||---- pom.xml||-- ap-web||---- pom.xml......一個(gè)父工程帶著多個(gè)字Module子模塊
MicroServiceCloud父工程(Project)下初次帶著3個(gè)子模塊(Module)
- microservicecloud-api 【封裝的整體entity/接口/公共配置等】
- microservicecloud-provider-dept-8001【服務(wù)提供者】
- microservicecloud-consumer-dept-80 【服務(wù)消費(fèi)者】
-
動(dòng)手開干!
4.2、SpringCloud版本選擇
大版本說明
| 1.2.x | Angel版本(天使) | 兼容Spring Boot 1.2.x |
| 1.3.x | Brixton版本(布里克斯頓) | 兼容Spring Boot 1.3.x,也兼容Spring Boot 1.4.x |
| 1.4.x | Camden版本(卡姆登) | 兼容Spring Boot 1.4.x,也兼容Spring Boot 1.5.x |
| 1.5.x | Dalston版本(多爾斯頓) | 兼容Spring Boot 1.5.x,不兼容Spring Boot 2.0.x |
| 1.5.x | Edgware版本(埃奇韋爾) | 兼容Spring Boot 1.5.x,不兼容Spring Boot 2.0.x |
| 2.0.x | Finchley版本(芬奇利) | 兼容Spring Boot 2.0.x,不兼容Spring Boot 1.5.x |
| 2.1.x | Greenwich版本(格林威治) |
實(shí)際開發(fā)版本關(guān)系
| 版本號(hào) | 發(fā)布日期 | 版本號(hào) | 發(fā)布日期 |
| 1.5.2.RELEASE | 2017年3月 | Dalston.RC1 | 2017年未知月 |
| 1.5.9.RELEASE | Nov,2017 | Edgware.RELEASE | Nov, 2017 |
| 1.5.16.RELEASE | sep, 2018 | Edgware.SR5 | Oct,2018 |
| 1.5.20.RELEASE | Apr, 2019 | Edgware.SR5 | Oct, 2018 |
| 2.0.2.RELEASE | May, 2018 | Finchley.BUILD-SNAPSHOT | 2018年未知月 |
| 2.0.6.RELEASE | Oct, 2018 | Finchley.SR2 | Oct, 2018 |
| 2.1.4.RELEASE | Apr,2019 | Greenwich.SR1 | Mar,2019 |
使用最后的這兩個(gè)
4.3、創(chuàng)建父工程
-
新建父工程項(xiàng)目microservicecloud,切記Packageing是pom模式
-
主要是定義POM文件,將后續(xù)各個(gè)子模塊公用的jar包統(tǒng)一提取出來,類似一個(gè)抽象父類
<!-- 打包方式--><packaging>pom</packaging><modules><module>springcloud-api</module><module>springcloud-provider-dept-8001</module><module>springcloud-consumer-dept-80</module></modules><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencyManagement><dependencies><!-- springcloud的依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2020.0.2</version><type>pom</type><scope>import</scope></dependency><!-- springboot--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.4.0</version><type>pom</type><scope>import</scope></dependency><!--數(shù)據(jù)庫--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.48</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.3</version></dependency><!-- springboot啟動(dòng)器--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency><!-- 單元測(cè)試--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version></dependency></dependencies></dependencyManagement>
DeptConsumerController.java
@RestController public class DeptConsumerController {// 消費(fèi)者,不應(yīng)該有service層// RestTemplate.... 供我們直接調(diào)用就可以了!注冊(cè)到spring中//( url, Class<T> responseType, 實(shí)體:Map<String, ?> uriVariables)@Autowiredprivate RestTemplate restTemplate; // 提供多種邊界訪問遠(yuǎn)程http服務(wù)的方法,簡(jiǎn)單的restful服務(wù)模板private static final String REST_URL_PREFIX = "http://localhost:8001";@RequestMapping("/consumer/dept/get/{id}")public Dept get(@PathVariable("id") Long id){return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/"+ id, Dept.class);}@RequestMapping("/consumer/dept/add")public boolean add(Dept dept){return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);}@RequestMapping("/consumer/dept/list")public List<Dept> queryAll(){return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);} }使用RestTemplete先需要放入Spring容器中
ConfigBean.java
@Configuration public class ConfigBean {@Beanpublic RestTemplate getRestTemplate(){return new RestTemplate();} }詳細(xì)代碼:
https://gitee.com/su_shuwang/spring-cloud
5、Eureka服務(wù)注冊(cè)與發(fā)現(xiàn)
5.1、什么是Euraka
- Eureka:怎么讀?
- Netflix 在設(shè)計(jì)Eureka時(shí),遵循的就是AP原則
- Eureka 是 Netflix 的一個(gè)子模塊,也是核心模塊之一。Eureka 是一個(gè)基于 REST 的服務(wù),用于定位服務(wù),以實(shí)現(xiàn)云端中間層服務(wù)發(fā)現(xiàn)和故障轉(zhuǎn)移,就可以訪問到服務(wù),而不需要修改調(diào)用的配置文件了,功能類似于Dubbo 的注冊(cè)中心,比如 Zookeeper;
5.2、原理理解
-
Eureka 的基本架構(gòu)
- SpringCloud 封裝了 Netflix 公司開發(fā)的 Eureka 模塊來實(shí)現(xiàn)服務(wù)注冊(cè)和發(fā)現(xiàn)(對(duì)比Zookeeper)
- Eureka 采用了 C-S 的架構(gòu)設(shè)計(jì), EurekaServer 作為服務(wù)注冊(cè)功能的服務(wù)器,他是服務(wù)注冊(cè)中心
- 而系統(tǒng)中的其他微服務(wù)。使用Eureka的客戶端連接到 EurekaServer 并維持心跳連接。這樣系統(tǒng)的維護(hù)人員就可以通過EurekaServer來監(jiān)控系統(tǒng)中各個(gè)微服務(wù)是否正常運(yùn)行,SpringCloud的一些其他模塊(比如Zuul)就可以通過EurekaServer來發(fā)現(xiàn)系統(tǒng)中的其他微服務(wù),并執(zhí)行相關(guān)的邏輯;
- 和 Dubbo 架構(gòu)對(duì)比
- Eureka包含兩個(gè)組件: Eureka Server和 Eureka Client 。
- Eureka Server提供服務(wù)注冊(cè)服務(wù),各個(gè)節(jié)點(diǎn)啟動(dòng)后,會(huì)在EurekaServer中進(jìn)行注冊(cè),這樣Eureka Server中的服務(wù)注冊(cè)表中將會(huì)村粗所有可用服務(wù)節(jié)點(diǎn)的信息,服務(wù)節(jié)點(diǎn)的信息可以在界面中直觀的看到。
- Eureka Client是一個(gè)ava客戶端,用于簡(jiǎn)化EurekaServer的交互,客戶端同時(shí)也具備一個(gè)內(nèi)置的,使用輪詢負(fù)載算法的負(fù)載均衡器。在應(yīng)用啟動(dòng)后,將會(huì)向EurekaServer發(fā)送心跳(默認(rèn)周期為30秒)。如果Eureka Server在多個(gè)心跳周期內(nèi)沒有接收到某個(gè)節(jié)點(diǎn)的心跳,EurekaServer將會(huì)從服務(wù)注冊(cè)表中把這個(gè)服務(wù)節(jié)點(diǎn)移除掉(默認(rèn)周期為90秒)
-
三大角色
- Eureka Server:提供服務(wù)的注冊(cè)與發(fā)現(xiàn)。
- Service Provider:將自身服務(wù)注冊(cè)到Eureka中,從而使消費(fèi)方能夠找到。
- Service Consumer:服務(wù)消費(fèi)方從Eureka中獲取注冊(cè)服務(wù)列表,從而找到消費(fèi)服務(wù)。
5.3、構(gòu)建步驟
1、eureka-server
springcloud-eureka-7001 模塊建立
pom.xml 配置
spring-cloud-starter-eureka-server 已經(jīng)停止維護(hù),建議使用spring-cloud-starter-netflix-eureka-server
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springcloud</artifactId><groupId>com.su</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>springcloud-eureka-7001</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId><version>2.2.9.RELEASE</version></dependency></dependencies> </project>yml文件
server:port: 7001#Eureka 配置 eureka:instance:hostname: localhost #Eureka 服務(wù)端的實(shí)例名稱client:register-with-eureka: false # 表示是否向 Eureka注冊(cè)中心注冊(cè)自己fetch-registry: false # 如果為false,則表示自己為注冊(cè)中心,我的職責(zé)就是維護(hù)服務(wù)實(shí)例,并不需要去檢索服務(wù)service-url: # 監(jiān)控頁面~defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/# 設(shè)置與Eureka Server 交互的地址查詢服務(wù)和注冊(cè)服務(wù)都需要依賴這個(gè)defaultZone 地址編寫主啟動(dòng)類
@SpringBootApplication @EnableEurekaServer // 服務(wù)端的啟動(dòng)類,可以接受別人注冊(cè)進(jìn)來~ public class EurekaServer_7001 {public static void main(String[] args) {SpringApplication.run(EurekaServer_7001.class, args);} }啟動(dòng)成功后訪問 http://localhost:7001/ 得到以下頁面
2.、eureka-client
調(diào)整之前創(chuàng)建的springlouc-provider-dept-8001
修改8001服務(wù)的pom文件,增加eureka的支持!
spring-cloud-starter-eureka已經(jīng)停止維護(hù),建議使用 spring-cloud-starter-netflix-eureka-client
<!--將服務(wù)的provider注冊(cè)到eureka中--> <!--Eureka--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.2.9.RELEASE</version></dependency>yml修改
# Eureka 的配置, 服務(wù)注冊(cè)到哪里 eureka:client:service-url:defaultZone: http://localhost:7001/eureka/8001的主啟動(dòng)類注解支持
@SpringBootApplication @EnableEurekaClient // 自動(dòng)在服務(wù)啟動(dòng)后,自動(dòng)注冊(cè)到Eureka中! public class DeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8001.class, args);} }先啟動(dòng)7001服務(wù)端后啟動(dòng)8001客戶端進(jìn)行測(cè)試,然后訪問監(jiān)控頁http://localhost:7001/ 產(chǎn)看結(jié)果如圖,成功
3、actuator 與注冊(cè)微服務(wù)信息完善
主機(jī)名稱:服務(wù)名稱修改
-
在8001的yml中修改一下配置
# Eureka 的配置, 服務(wù)注冊(cè)到哪里 eureka:client:service-url:defaultZone: http://localhost:7001/eureka/instance:instance-id: springcloud-provider-dept8001 # 修改Eureka 上的默認(rèn)描述信息 -
查看結(jié)果
訪問信息有IP信息提示
-
在yml中再增加一個(gè)配置
# Eureka 的配置, 服務(wù)注冊(cè)到哪里 eureka:client:service-url:defaultZone: http://localhost:7001/eureka/instance:instance-id: springcloud-provider-dept8001 # 修改Eureka 上的默認(rèn)描述信息prefer-ip-address: true # 訪問路徑可以顯示ip地址 -
重啟服務(wù)測(cè)試
info內(nèi)容構(gòu)建
現(xiàn)在點(diǎn)擊info,出現(xiàn)ERROR頁面
-
修改8001的pom文件,新增依賴
<!-- actuator完善監(jiān)控信息--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> -
然后回到我們的8001的yaml配置文件中修改增加信息
# info配置 info:app.name: kuangshen-springcloudcompany.name: blog.kuangstudy.com -
重啟項(xiàng)目測(cè)試:7001、8001
4、Eureka 的自我保護(hù)機(jī)制
之前出現(xiàn)的這些紅色情況
我們修改一個(gè)服務(wù)名,故意制造錯(cuò)誤!
自我保護(hù)機(jī)制:好死不如賴活著
一句話總結(jié)就是:某時(shí)刻某一個(gè)微服務(wù)不可用,eureka不會(huì)立即清理,依舊會(huì)對(duì)該微服務(wù)的信息進(jìn)行保存!
- 默認(rèn)情況下,如果EurekaServer在一定時(shí)間內(nèi)沒有接收到某個(gè)微服務(wù)實(shí)例的心跳,EurekaServer將會(huì)注銷該實(shí)例(默認(rèn)90秒)。但是當(dāng)網(wǎng)絡(luò)分區(qū)故障發(fā)生時(shí),微服務(wù)與Eureka之間無法正常通行,以上行為可能變得非常危險(xiǎn)了——因?yàn)槲⒎?wù)本身其實(shí)是健康的,此時(shí)本不應(yīng)該注銷這個(gè)服務(wù)。Eureka通過自我保護(hù)機(jī)制來解決這個(gè)問題——當(dāng)EurekaServer節(jié)點(diǎn)在短時(shí)間內(nèi)丟失過多客戶端時(shí)(可能發(fā)生了網(wǎng)絡(luò)分區(qū)故障),那么這個(gè)節(jié)點(diǎn)就會(huì)進(jìn)入自我保護(hù)模式。一旦進(jìn)入該模式,EurekaServer就會(huì)保護(hù)服務(wù)注冊(cè)表中的信息,不再刪除服務(wù)注冊(cè)表中的數(shù)據(jù)(也就是不會(huì)注銷任何微服務(wù))。當(dāng)網(wǎng)絡(luò)故障恢復(fù)后,該EurekaServer節(jié)點(diǎn)會(huì)自動(dòng)退出自我保護(hù)模式。
- 在自我保護(hù)模式中,EurekaServer會(huì)保護(hù)服務(wù)注冊(cè)表中的信息,不再注銷任何服務(wù)實(shí)例。當(dāng)它收到的心跳數(shù)重新恢復(fù)到閾值以上時(shí),該EurekaServer節(jié)點(diǎn)就會(huì)自動(dòng)退出自我保護(hù)模式。它的設(shè)計(jì)哲學(xué)就是寧可保留錯(cuò)誤的服務(wù)注冊(cè)信息,也不盲目注銷任何可能健康的服務(wù)實(shí)例。一句話:好死不如賴活著
- 綜上,自我保護(hù)模式是一種應(yīng)對(duì)網(wǎng)絡(luò)異常的安全保護(hù)措施。它的架構(gòu)哲學(xué)是寧可同時(shí)保留所有微服務(wù)(健康的微服務(wù)和不健康的微服務(wù)都會(huì)保留),也不盲目注銷任何健康的微服務(wù)。使用自我保護(hù)模式,可以讓Eureka集群更加的健壯和穩(wěn)定
- 在SpringCloud中,可以使用eureka.server.enable-self-preservation = false禁用自我保護(hù)模式【不推薦關(guān)閉自我保護(hù)機(jī)制】
5、8001服務(wù)發(fā)現(xiàn)Discovery
DeptController.java新增方法
//獲取一些配置的信息,得到具體的微服務(wù)! @Autowired private DiscoveryClient client;//注冊(cè)進(jìn)來的微服務(wù)~,獲取一些信息~ @RequestMapping("/dept/discovery") public Object discovery(){//獲取微服務(wù)列表的清單List<String> services = client.getServices();System.out.println("discovery=>services:" + services);//得到一個(gè)具體的微服務(wù)信息,通過具體的微服務(wù)id,applicationNameList<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");for (ServiceInstance instance : instances) {System.out.println(instance.getHost() + "\t"+instance.getPort()+"\t"+instance.getUri()+"\t"+instance.getServiceId()+"\t");}return this.client; }主啟動(dòng)類中加入@EnableDiscoveryClient 注解
@SpringBootApplication @EnableEurekaClient // 自動(dòng)在服務(wù)啟動(dòng)后,自動(dòng)注冊(cè)到Eureka中! @EnableDiscoveryClient // 服務(wù)發(fā)現(xiàn)~ 可以用來獲取一些配置的信息,得到具體的微服務(wù) public class DeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8001.class, args);} }5.4、Eureka:集群環(huán)境配置
5.4.1、初始化
新建springcloud-eureka-7002、springcloud-eureka-7003 模塊
1.為pom.xml添加依賴 (與springcloud-eureka-7001相同)
<!--導(dǎo)包~--> <dependencies><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --><!--導(dǎo)入Eureka Server依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka-server</artifactId><version>1.4.6.RELEASE</version></dependency><!--熱部署工具--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency> </dependencies>3.主啟動(dòng)類(與springcloud-eureka-7001相同)
@SpringBootApplication // @EnableEurekaServer 服務(wù)端的啟動(dòng)類,可以接受別人注冊(cè)進(jìn)來~ public class EurekaServer_7003 {public static void main(String[] args) {SpringApplication.run(EurekaServer_7003.class,args);} }5.4.2、集群成員相互關(guān)聯(lián)
配置一些自定義本機(jī)名字,找到本機(jī)hosts文件并打開
在hosts文件最后加上,要訪問的本機(jī)名稱,默認(rèn)是localhost
修改application.yml的配置,如圖為springcloud-eureka-7001配置,springcloud-eureka-7002/springcloud-eureka-7003同樣分別修改為其對(duì)應(yīng)的名稱即可
在集群中使springcloud-eureka-7001關(guān)聯(lián)springcloud-eureka-7002、springcloud-eureka-7003
完整的springcloud-eureka-7001下的application.yml如下
server:port: 7001#Eureka 配置 eureka:instance:hostname: eureka7001.com #Eureka 服務(wù)端的實(shí)例名稱client:register-with-eureka: false # 表示是否向 Eureka注冊(cè)中心注冊(cè)自己fetch-registry: false # 如果為false,則表示自己為注冊(cè)中心service-url: # 監(jiān)控頁面~defaultZone: http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/同時(shí)在集群中使springcloud-eureka-7002關(guān)聯(lián)springcloud-eureka-7001、springcloud-eureka-7003
完整的springcloud-eureka-7002下的application.yml如下
server:port: 7002#Eureka 配置 eureka:instance:hostname: eureka7002.com #Eureka 服務(wù)端的實(shí)例名稱client:register-with-eureka: false # 表示是否向 Eureka注冊(cè)中心注冊(cè)自己fetch-registry: false # 如果為false,則表示自己為注冊(cè)中心service-url: # 監(jiān)控頁面~defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7003.com:7003/eureka/springcloud-eureka-7003配置方式同理可得.
通過springcloud-provider-dept-8001下的yml配置文件,修改Eureka配置:配置服務(wù)注冊(cè)中心地址
# Eureka配置:配置服務(wù)注冊(cè)中心地址 eureka:client:service-url:# 注冊(cè)中心地址7001-7003defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: springcloud-provider-dept-8001 #修改Eureka上的默認(rèn)描述信息這樣模擬集群就搭建號(hào)了,就可以把一個(gè)項(xiàng)目掛載到三個(gè)服務(wù)器上了
5.5、對(duì)比Zookeeper
回顧C(jī)AP原則
CAP原則又稱CAP定理,指的是在一個(gè)分布式系統(tǒng)中,一致性(Consistency)、可用性(Availability)、分區(qū)容錯(cuò)性(Partition tolerance)。CAP原則指的是,這三個(gè)要素最多只能同時(shí)實(shí)現(xiàn)兩點(diǎn),不可能三者兼顧。
RDBMS (MySQL\Oracle\sqlServer) ===> ACID
NoSQL (Redis\MongoDB) ===> CAP
ACID是什么?
- A (Atomicity) 原子性
- C (Consistency) 一致性
- I (Isolation) 隔離性
- D (Durability) 持久性
CAP是什么?
- C (Consistency) 強(qiáng)一致性
- A (Availability) 可用性
- P (Partition tolerance) 分區(qū)容錯(cuò)性
CAP的三進(jìn)二:CA、AP、CP
CAP理論的核心
- 一個(gè)分布式系統(tǒng)不可能同時(shí)很好的滿足一致性,可用性和分區(qū)容錯(cuò)性這三個(gè)需求
- 根據(jù)CAP原理,將NoSQL數(shù)據(jù)庫分成了滿足CA原則,滿足CP原則和滿足AP原則三大類
- CA:單點(diǎn)集群,滿足一致性,可用性的系統(tǒng),通常可擴(kuò)展性較差
- CP:滿足一致性,分區(qū)容錯(cuò)的系統(tǒng),通常性能不是特別高
- AP:滿足可用性,分區(qū)容錯(cuò)的系統(tǒng),通常可能對(duì)一致性要求低一些
作為分布式服務(wù)注冊(cè)中心,Eureka比Zookeeper好在哪里?
著名的CAP理論指出,一個(gè)分布式系統(tǒng)不可能同時(shí)滿足C (一致性) 、A (可用性) 、P (容錯(cuò)性)
由于分區(qū)容錯(cuò)性P再分布式系統(tǒng)中是必須要保證的,因此我們只能再A和C之間進(jìn)行權(quán)衡。
- Zookeeper 保證的是 CP —> 滿足一致性,分區(qū)容錯(cuò)的系統(tǒng),通常性能不是特別高
- Eureka 保證的是 AP —> 滿足可用性,分區(qū)容錯(cuò)的系統(tǒng),通常可能對(duì)一致性要求低一些
Zookeeper保證的是CP
當(dāng)向注冊(cè)中心查詢服務(wù)列表時(shí),我們可以容忍注冊(cè)中心返回的是幾分鐘以前的注冊(cè)信息,但不能接收服務(wù)直接down掉不可用。也就是說,服務(wù)注冊(cè)功能對(duì)可用性的要求要高于一致性。但zookeeper會(huì)出現(xiàn)這樣一種情況,當(dāng)master節(jié)點(diǎn)因?yàn)榫W(wǎng)絡(luò)故障與其他節(jié)點(diǎn)失去聯(lián)系時(shí),剩余節(jié)點(diǎn)會(huì)重新進(jìn)行l(wèi)eader選舉。問題在于,選舉leader的時(shí)間太長,30-120s,且選舉期間整個(gè)zookeeper集群是不可用的,這就導(dǎo)致在選舉期間注冊(cè)服務(wù)癱瘓。在云部署的環(huán)境下,因?yàn)榫W(wǎng)絡(luò)問題使得zookeeper集群失去master節(jié)點(diǎn)是較大概率發(fā)生的事件,雖然服務(wù)最終能夠恢復(fù),但是,漫長的選舉時(shí)間導(dǎo)致注冊(cè)長期不可用,是不可容忍的。
Eureka保證的是AP
Eureka看明白了這一點(diǎn),因此在設(shè)計(jì)時(shí)就優(yōu)先保證可用性。Eureka各個(gè)節(jié)點(diǎn)都是平等的,幾個(gè)節(jié)點(diǎn)掛掉不會(huì)影響正常節(jié)點(diǎn)的工作,剩余的節(jié)點(diǎn)依然可以提供注冊(cè)和查詢服務(wù)。而Eureka的客戶端在向某個(gè)Eureka注冊(cè)時(shí),如果發(fā)現(xiàn)連接失敗,則會(huì)自動(dòng)切換至其他節(jié)點(diǎn),只要有一臺(tái)Eureka還在,就能保住注冊(cè)服務(wù)的可用性,只不過查到的信息可能不是最新的,除此之外,Eureka還有之中自我保護(hù)機(jī)制,如果在15分鐘內(nèi)超過85%的節(jié)點(diǎn)都沒有正常的心跳,那么Eureka就認(rèn)為客戶端與注冊(cè)中心出現(xiàn)了網(wǎng)絡(luò)故障,此時(shí)會(huì)出現(xiàn)以下幾種情況:
- Eureka不再從注冊(cè)列表中移除因?yàn)殚L時(shí)間沒收到心跳而應(yīng)該過期的服務(wù)
- Eureka仍然能夠接受新服務(wù)的注冊(cè)和查詢請(qǐng)求,但是不會(huì)被同步到其他節(jié)點(diǎn)上 (即保證當(dāng)前節(jié)點(diǎn)依然可用)
- 當(dāng)網(wǎng)絡(luò)穩(wěn)定時(shí),當(dāng)前實(shí)例新的注冊(cè)信息會(huì)被同步到其他節(jié)點(diǎn)中
因此,Eureka可以很好的應(yīng)對(duì)因網(wǎng)絡(luò)故障導(dǎo)致部分節(jié)點(diǎn)失去聯(lián)系的情況,而不會(huì)像zookeeper那樣使整個(gè)注冊(cè)服務(wù)癱瘓
6、Ribbon
6.1、負(fù)載均衡以及Ribbon
Ribbon是什么?
- SpringCloud Rinbbon是基于Netflix Ribbon實(shí)現(xiàn)的一套客戶端負(fù)載均衡的工具。
- 簡(jiǎn)單的說,Ribbon是Netflix發(fā)布的開源項(xiàng)目,主要功能是提供客戶端的軟件負(fù)載均衡算法,將NetFlix的中間層服務(wù)連接在一起。Ribbon的客戶端組件提供一系列完成的配置項(xiàng)如:連接超時(shí)、重試等等。簡(jiǎn)單的說,就是配置文件中列出LoadBalancer(簡(jiǎn)稱LB:負(fù)載均衡)后面所有的機(jī)器,Ribbon會(huì)自動(dòng)的幫助你基于某種規(guī)則(如簡(jiǎn)單輪詢,隨機(jī)連接等等)去連接這些機(jī)器。我們也很容易使用Ribbon實(shí)現(xiàn)自定義的負(fù)載均衡算法!
Ribbon能干嘛?
- LB,即負(fù)載均衡 (LoadBalancer) ,在微服務(wù)或分布式集群中經(jīng)常用的一種應(yīng)用。
- 負(fù)載均衡簡(jiǎn)單的說就是將用戶的請(qǐng)求平攤的分配到多個(gè)服務(wù)上,從而達(dá)到系統(tǒng)的HA (高用)。
- 常見的負(fù)載均衡軟件有 Nginx、Lvs 等等。
- Dubbo、SpringCloud 中均給我們提供了負(fù)載均衡,SpringCloud 的負(fù)載均衡算法可以自定義。
- 負(fù)載均衡簡(jiǎn)單分類:
- 集中式LB
- 即在服務(wù)的提供方和消費(fèi)方之間使用獨(dú)立的LB設(shè)施,如Nginx(反向代理服務(wù)器),由該設(shè)施負(fù)責(zé)把訪問請(qǐng)求通過某種策略轉(zhuǎn)發(fā)至服務(wù)的提供方!
- 進(jìn)程式 LB
- 將LB邏輯集成到消費(fèi)方,消費(fèi)方從服務(wù)注冊(cè)中心獲知有哪些地址可用,然后自己再從這些地址中選出一個(gè)合適的服務(wù)器。
Ribbon 就屬于進(jìn)程內(nèi)LB,它只是一個(gè)類庫,集成于消費(fèi)方進(jìn)程,消費(fèi)方通過它來獲取到服務(wù)提供方的地址!
- 將LB邏輯集成到消費(fèi)方,消費(fèi)方從服務(wù)注冊(cè)中心獲知有哪些地址可用,然后自己再從這些地址中選出一個(gè)合適的服務(wù)器。
- 集中式LB
6.2、集成Ribbon
springcloud-consumer-dept-80向pom.xml中添加Ribbon和Eureka依賴
<!--Ribbon--> <!-- spring-cloud-starter-ribbon 已停止維護(hù),建議使用spring-cloud-starter-netflix-ribbon --><!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-ribbon</artifactId>--> <!-- <version>1.4.6.RELEASE</version>--> <!-- </dependency>--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId><version>2.2.9.RELEASE</version></dependency> <!--Eureka: Ribbon需要從Eureka服務(wù)中心獲取要拿什么--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.2.9.RELEASE</version> </dependency>依賴導(dǎo)入失敗,解決:
有的時(shí)候,依賴雖然下載失敗了,但是相關(guān)文件夾中卻多了以 .lastUpdated為后綴的文件,此時(shí),如果開發(fā)者在開發(fā)工具中反復(fù)導(dǎo) 入,會(huì)發(fā)現(xiàn)始終無法導(dǎo)入成功,這個(gè)時(shí)候就需要?jiǎng)h除本地倉庫中相關(guān)的 .lastUpdated文件,可以通過文件搜索找到本地倉庫中所有的 以 .lastUpdated為后綴的文件,如下:搜索 .lastupdate,找到對(duì)應(yīng)的依賴文件,刪除即可在application.yml文件中配置Eureka
# Eureka配置 eureka:client:register-with-eureka: false # 不向 Eureka注冊(cè)自己service-url: # 從三個(gè)注冊(cè)中心中隨機(jī)取一個(gè)去訪問defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/主啟動(dòng)類加上@EnableEurekaClient注解,開啟Eureka
//Ribbon 和 Eureka 整合以后,客戶端可以直接調(diào)用,不用關(guān)心IP地址和端口號(hào) @SpringBootApplication @EnableEurekaClient //開啟Eureka 客戶端 public class DeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(DeptConsumer_80.class, args);} }自定義Spring配置類:ConfigBean.java 配置負(fù)載均衡實(shí)現(xiàn)RestTemplate
@Configuration public class ConfigBean {//@Configuration -- spring applicationContext.xml@LoadBalanced //配置負(fù)載均衡實(shí)現(xiàn)RestTemplate@Beanpublic RestTemplate getRestTemplate() {return new RestTemplate();} }修改conroller:DeptConsumerController.java
//Ribbon:我們這里的地址,應(yīng)該是一個(gè)變量,通過服務(wù)名來訪問 //private static final String REST_URL_PREFIX = "http://localhost:8001"; private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";6.3、使用Ribbon實(shí)現(xiàn)負(fù)載均衡
流程圖:
1.新建兩個(gè)服務(wù)提供者M(jìn)oudle:springcloud-provider-dept-8002、springcloud-provider-dept-8003
2.參照springcloud-provider-dept-8001 依次為另外兩個(gè)Moudle添加pom.xml依賴 、resourece下的mybatis和application.yml配置,Java代碼
application.yml需要修改 instance-id
# Eureka 的配置, 服務(wù)注冊(cè)到哪里 eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: springcloud-provider-dept8002 # 修改Eureka 上的默認(rèn)描述信息prefer-ip-address: true # 訪問路徑可以顯示ip地址3.新建兩個(gè)數(shù)據(jù)庫db02、db03, 并修改數(shù)據(jù)
CREATE DATABASE /*!32312 IF NOT EXISTS*/`db01` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `db01`; /*Table structure for table `dept` */DROP TABLE IF EXISTS `dept`; CREATE TABLE `dept` (`deptno` bigint(20) NOT NULL AUTO_INCREMENT,`dname` varchar(60) DEFAULT NULL,`db_source` varchar(60) DEFAULT NULL,PRIMARY KEY (`deptno`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;/*Data for the table `dept` */ insert into dept (`deptno`,`dname`,`db_source`) values (1,'開發(fā)部',DATABASE()),(2,'人事部',DATABASE()),(3,'財(cái)務(wù)部',DATABASE()),(4,'市場(chǎng)部',DATABASE()),(5,'運(yùn)維部',DATABASE()),(6,NULL,DATABASE());4.啟動(dòng)所有服務(wù)測(cè)試(根據(jù)自身電腦配置決定啟動(dòng)服務(wù)的個(gè)數(shù)),訪問http://eureka7001.com:7002/查看結(jié)果
測(cè)試訪問http://localhost/consumer/dept/list
再次訪問
以上這種每次訪問http://localhost/consumer/dept/list隨機(jī)訪問集群中某個(gè)服務(wù)提供者,這種情況叫做輪詢,輪詢算法在SpringCloud中可以自定義。
如何切換或者自定義規(guī)則呢?
在springcloud-provider-dept-80模塊下的ConfigBean中進(jìn)行配置,切換使用不同的規(guī)則
@Configuration public class ConfigBean {//@Configuration -- spring applicationContext.xml/*** IRule:* RoundRobinRule 輪詢策略* RandomRule 隨機(jī)策略* AvailabilityFilteringRule : 會(huì)先過濾掉,跳閘,訪問故障的服務(wù)~,對(duì)剩下的進(jìn)行輪詢~* RetryRule : 會(huì)先按照輪詢獲取服務(wù)~,如果服務(wù)獲取失敗,則會(huì)在指定的時(shí)間內(nèi)進(jìn)行,重試*/@Beanpublic IRule myRule() {return new RandomRule();//使用隨機(jī)策略//return new RoundRobinRule();//使用輪詢策略//return new AvailabilityFilteringRule();//使用輪詢策略//return new RetryRule();//使用輪詢策略} }也可以自定義規(guī)則,在myRule包下自定義一個(gè)配置類MyRule.java,注意:該包不要和主啟動(dòng)類所在的包同級(jí),要跟啟動(dòng)類所在包同級(jí):
MyRule.java
@Configuration public class MyRule {@Beanpublic IRule myRule(){return new MyRandomRule(); //默認(rèn)是輪詢RandomRule,現(xiàn)在自定義為自己的} }主啟動(dòng)類開啟負(fù)載均衡并指定自定義的MyRule配置類
//Ribbon 和 Eureka 整合以后,客戶端可以直接調(diào)用,不用關(guān)心IP地址和端口號(hào) @SpringBootApplication @EnableEurekaClient //在微服務(wù)啟動(dòng)的時(shí)候就能去加載我們自定義的Ribbon類 @RibbonClient(name = "springcloud-provider-dept", configuration = MyRule.class) public class DeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(DeptConsumer_80.class, args);} }自定義的規(guī)則(這里我們參考Ribbon中默認(rèn)的規(guī)則代碼自己稍微改動(dòng)):MyRandomRule.java
public class MyRandomRule extends AbstractLoadBalancerRule {/*** 每個(gè)服務(wù)訪問5次則換下一個(gè)服務(wù)(總共3個(gè)服務(wù))* <p>* total=0,默認(rèn)=0,如果=5,指向下一個(gè)服務(wù)節(jié)點(diǎn)* index=0,默認(rèn)=0,如果total=5,index+1*/private int total = 0;//被調(diào)用的次數(shù)private int currentIndex = 0;//當(dāng)前是誰在提供服務(wù)//@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")public Server choose(ILoadBalancer lb, Object key) {if (lb == null) {return null;}Server server = null;while (server == null) {if (Thread.interrupted()) {return null;}List<Server> upList = lb.getReachableServers();//獲得當(dāng)前活著的服務(wù)List<Server> allList = lb.getAllServers();//獲取所有的服務(wù)int serverCount = allList.size();if (serverCount == 0) {return null;}//int index = chooseRandomInt(serverCount);//生成區(qū)間隨機(jī)數(shù)//server = upList.get(index);//從或活著的服務(wù)中,隨機(jī)獲取一個(gè)//=====================自定義代碼=========================if (total < 5) {server = upList.get(currentIndex);total++;} else {total = 0;currentIndex++;if (currentIndex > upList.size()) {currentIndex = 0;}server = upList.get(currentIndex);//從活著的服務(wù)中,獲取指定的服務(wù)來進(jìn)行操作}//======================================================if (server == null) {Thread.yield();continue;}if (server.isAlive()) {return (server);}// Shouldn't actually happen.. but must be transient or a bug.server = null;Thread.yield();}return server;}protected int chooseRandomInt(int serverCount) {return ThreadLocalRandom.current().nextInt(serverCount);}@Overridepublic Server choose(Object key) {return choose(getLoadBalancer(), key);}@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {// TODO Auto-generated method stub}}7、Feign:負(fù)載均衡(基于服務(wù)端)
7.1 、Feign簡(jiǎn)介
Feign是聲明式Web Service客戶端,它讓微服務(wù)之間的調(diào)用變得更簡(jiǎn)單,類似controller調(diào)用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供負(fù)載均衡的http客戶端。
只需要?jiǎng)?chuàng)建一個(gè)接口,然后添加注解即可~
Feign,主要是社區(qū)版,大家都習(xí)慣面向接口編程。這個(gè)是很多開發(fā)人員的規(guī)范。調(diào)用微服務(wù)訪問兩種方法
Feign能干什么?
- Feign旨在使編寫Java Http客戶端變得更容易
- 前面在使用Ribbon + RestTemplate時(shí),利用RestTemplate對(duì)Http請(qǐng)求的封裝處理,形成了一套模板化的調(diào)用方法。但是在實(shí)際開發(fā)中,由于對(duì)服務(wù)依賴的調(diào)用可能不止一處,往往一個(gè)接口會(huì)被多處調(diào)用,所以通常都會(huì)針對(duì)每個(gè)微服務(wù)自行封裝一個(gè)客戶端類來包裝這些依賴服務(wù)的調(diào)用。所以,Feign在此基礎(chǔ)上做了進(jìn)一步的封裝,由他來幫助我們定義和實(shí)現(xiàn)依賴服務(wù)接口的定義,==在Feign的實(shí)現(xiàn)下,我們只需要?jiǎng)?chuàng)建一個(gè)接口并使用注解的方式來配置它 (類似以前Dao接口上標(biāo)注Mapper注解,現(xiàn)在是一個(gè)微服務(wù)接口上面標(biāo)注一個(gè)Feign注解),==即可完成對(duì)服務(wù)提供方的接口綁定,簡(jiǎn)化了使用Spring Cloud Ribbon 時(shí),自動(dòng)封裝服務(wù)調(diào)用客戶端的開發(fā)量。
Feign默認(rèn)集成了Ribbon
利用Ribbon維護(hù)了MicroServiceCloud-Dept的服務(wù)列表信息,并且通過輪詢實(shí)現(xiàn)了客戶端的負(fù)載均衡,而與Ribbon不同的是,通過Feign只需要定義服務(wù)綁定接口且以聲明式的方法,優(yōu)雅而簡(jiǎn)單的實(shí)現(xiàn)了服務(wù)調(diào)用。
7.2、Feign的使用步驟
拷貝springcloud-consumer-dept-80模塊下的pom.xml,resource,以及java代碼到springcloud-consumer-feign模塊,并添加feign依賴。
<!--feign--> spring-cloud-starter-feign 已經(jīng)停止維護(hù),推薦使用spring-cloud-starter-openfeign <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>3.0.3</version> </dependency>通過Feign實(shí)現(xiàn):改造DeptConsumerController.java
@RestController public class DeptConsumerController {// private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";@Autowiredprivate DeptClientService service ;@RequestMapping("/consumer/dept/get/{id}")public Dept get(@PathVariable("id") Long id){return this.service.queryById(id);}@RequestMapping("/consumer/dept/add")public boolean add(Dept dept){return this.service.addDept(dept);}@RequestMapping("/consumer/dept/list")public List<Dept> queryAll(){return this.service.queryAll();} }Feign和Ribbon二者對(duì)比,前者顯現(xiàn)出面向接口編程特點(diǎn),代碼看起來更清爽,而且Feign調(diào)用方式更符合我們之前在做SSM或者SprngBoot項(xiàng)目時(shí),Controller層調(diào)用Service層的編程習(xí)慣!
主啟動(dòng)類:
//Ribbon 和 Eureka 整合以后,客戶端可以直接調(diào)用,不用關(guān)心IP地址和端口號(hào) @SpringBootApplication @EnableEurekaClient @EnableFeignClients(basePackages = {"com.su.springcloud"}) //@ComponentScan("com.su.springcloud") public class FeignDeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(FeignDeptConsumer_80.class, args);} }pom.xml添加feign依賴
<!--feign--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>3.0.3</version> </dependency>新建service包,并新建DeptClientService.java接口,
@Configuration @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT") public interface DeptClientService {@GetMapping("/dept/get/{id}")Dept queryById(@PathVariable("id") Long id);@GetMapping("/dept/list")List<Dept> queryAll();@PostMapping("/dept/add")boolean addDept(Dept dept); }7.3、Feign和Ribbon如何選擇?
根據(jù)個(gè)人習(xí)慣而定,如果喜歡REST風(fēng)格使用Ribbon;如果喜歡社區(qū)版的面向接口風(fēng)格使用Feign.
Feign 本質(zhì)上也是實(shí)現(xiàn)了 Ribbon,只不過后者是在調(diào)用方式上,為了滿足一些開發(fā)者習(xí)慣的接口調(diào)用習(xí)慣!
下面我們關(guān)閉springcloud-consumer-dept-80 這個(gè)服務(wù)消費(fèi)方,換用springcloud-consumer-dept-feign(端口還是80) 來代替:(依然可以正常訪問,就是調(diào)用方式相比于Ribbon變化了)
8、Hystrix:服務(wù)熔斷
分布式系統(tǒng)面臨的問題
復(fù)雜分布式體系結(jié)構(gòu)中的應(yīng)用程序有數(shù)十個(gè)依賴關(guān)系,每個(gè)依賴關(guān)系在某些時(shí)候?qū)⒉豢杀苊馐?#xff01;
8.1、服務(wù)雪崩
多個(gè)微服務(wù)之間調(diào)用的時(shí)候,假設(shè)微服務(wù)A調(diào)用微服務(wù)B和微服務(wù)C,微服務(wù)B和微服務(wù)C又調(diào)用其他的微服務(wù),這就是所謂的“扇出”,如果扇出的鏈路上某個(gè)微服務(wù)的調(diào)用響應(yīng)時(shí)間過長,或者不可用,對(duì)微服務(wù)A的調(diào)用就會(huì)占用越來越多的系統(tǒng)資源,進(jìn)而引起系統(tǒng)崩潰,所謂的“雪崩效應(yīng)”。
對(duì)于高流量的應(yīng)用來說,單一的后端依賴可能會(huì)導(dǎo)致所有服務(wù)器上的所有資源都在幾十秒內(nèi)飽和。比失敗更糟糕的是,這些應(yīng)用程序還可能導(dǎo)致服務(wù)之間的延遲增加,備份隊(duì)列,線程和其他系統(tǒng)資源緊張,導(dǎo)致整個(gè)系統(tǒng)發(fā)生更多的級(jí)聯(lián)故障,這些都表示需要對(duì)故障和延遲進(jìn)行隔離和管理,以達(dá)到單個(gè)依賴關(guān)系的失敗而不影響整個(gè)應(yīng)用程序或系統(tǒng)運(yùn)行。
我們需要,棄車保帥!
8.2、什么是Hystrix?
Hystrix是一個(gè)應(yīng)用于處理分布式系統(tǒng)的延遲和容錯(cuò)的開源庫,在分布式系統(tǒng)里,許多依賴不可避免的會(huì)調(diào)用失敗,比如超時(shí),異常等,Hystrix 能夠保證在一個(gè)依賴出問題的情況下,不會(huì)導(dǎo)致整個(gè)體系服務(wù)失敗,避免級(jí)聯(lián)故障,以提高分布式系統(tǒng)的彈性。
“斷路器”本身是一種開關(guān)裝置,當(dāng)某個(gè)服務(wù)單元發(fā)生故障之后,通過斷路器的故障監(jiān)控 (類似熔斷保險(xiǎn)絲) ,向調(diào)用方返回一個(gè)服務(wù)預(yù)期的,可處理的備選響應(yīng) (FallBack) ,而不是長時(shí)間的等待或者拋出調(diào)用方法無法處理的異常,這樣就可以保證了服務(wù)調(diào)用方的線程不會(huì)被長時(shí)間,不必要的占用,從而避免了故障在分布式系統(tǒng)中的蔓延,乃至雪崩。
官網(wǎng)資料
https://github.com/Netflix/Hystrix/wiki
8.3、Hystrix能干嘛?
- 服務(wù)降級(jí)
- 服務(wù)熔斷
- 服務(wù)限流
- 接近實(shí)時(shí)的監(jiān)控
- …
當(dāng)一切正常時(shí),請(qǐng)求流可以如下所示:
當(dāng)許多后端系統(tǒng)中有一個(gè)潛在阻塞服務(wù)時(shí),它可以阻止整個(gè)用戶請(qǐng)求:
隨著大容量通信量的增加,單個(gè)后端依賴項(xiàng)的潛在性會(huì)導(dǎo)致所有服務(wù)器上的所有資源在幾秒鐘內(nèi)飽和。
應(yīng)用程序中通過網(wǎng)絡(luò)或客戶端庫可能導(dǎo)致網(wǎng)絡(luò)請(qǐng)求的每個(gè)點(diǎn)都是潛在故障的來源。比失敗更糟糕的是,這些應(yīng)用程序還可能導(dǎo)致服務(wù)之間的延遲增加,從而備份隊(duì)列、線程和其他系統(tǒng)資源,從而導(dǎo)致更多跨系統(tǒng)的級(jí)聯(lián)故障。
當(dāng)使用Hystrix包裝每個(gè)基礎(chǔ)依賴項(xiàng)時(shí),上面的圖表中所示的體系結(jié)構(gòu)會(huì)發(fā)生類似于以下關(guān)系圖的變化。每個(gè)依賴項(xiàng)是相互隔離的,限制在延遲發(fā)生時(shí)它可以填充的資源中,并包含在回退邏輯中,該邏輯決定在依賴項(xiàng)中發(fā)生任何類型的故障時(shí)要做出什么樣的響應(yīng):
8.4、服務(wù)熔斷
什么是服務(wù)熔斷?
熔斷機(jī)制是賭贏雪崩效應(yīng)的一種微服務(wù)鏈路保護(hù)機(jī)制。
當(dāng)扇出鏈路的某個(gè)微服務(wù)不可用或者響應(yīng)時(shí)間太長時(shí),會(huì)進(jìn)行服務(wù)的降級(jí),進(jìn)而熔斷該節(jié)點(diǎn)微服務(wù)的調(diào)用,快速返回錯(cuò)誤的響應(yīng)信息。當(dāng)檢測(cè)到該節(jié)點(diǎn)微服務(wù)間調(diào)用的狀況,當(dāng)失敗的調(diào)用到一定閾值,缺省是5秒內(nèi)20次調(diào)用失敗就會(huì)啟動(dòng)熔斷機(jī)制。熔斷機(jī)制的注解是 @HystriCommand。
服務(wù)熔斷解決如下問題:
- 當(dāng)所依賴的對(duì)象不穩(wěn)定時(shí),能夠起到快速失敗的目的;
- 快速失敗后,能夠根據(jù)一定的算法動(dòng)態(tài)試探所依賴對(duì)象是否恢復(fù)。
入門案例
新建springcloud-provider-dept-hystrix-8001模塊并拷貝springcloud-provider-dept–8001內(nèi)的pom.xml、resource和Java代碼進(jìn)行初始化并調(diào)整。
導(dǎo)入hystrix依賴
<!--導(dǎo)入Hystrix依賴--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix</artifactId><version>1.4.6.RELEASE</version> </dependency>調(diào)整yml配置文件
# Eureka 的配置, 服務(wù)注冊(cè)到哪里 eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: springcloud-provider-dept-hystrix-8001 # 修改Eureka 上的默認(rèn)描述信息prefer-ip-address: true #改為true后默認(rèn)顯示的是ip地址而不再是localhostprefer-ip-address: false:
prefer-ip-address: true:
修改controller
@RestController public class DeptController {@Autowiredprivate DeptService deptService;@HystrixCommand(fallbackMethod = "hystrixGet")@GetMapping("/dept/get/{id}")public Dept get(@PathVariable("id") Long id){Dept dept = deptService.queryById(id);if (dept==null){throw new RuntimeException("id=>"+id + "不存在該用戶,或者信息無法找到~");}return dept;}// 備選方法public Dept hystrixGet(@PathVariable("id") Long id){return new Dept().setDeptno(id).setDname("id=>"+id + "沒有對(duì)應(yīng)的信息,null--@Hystrix").setDb_source("no this database in MySQL");} }為主啟動(dòng)類添加對(duì)熔斷的支持注解@EnableCircuitBreaker
@SpringBootApplication @EnableEurekaClient // 自動(dòng)在服務(wù)啟動(dòng)后,自動(dòng)注冊(cè)到Eureka中! @EnableDiscoveryClient // 服務(wù)發(fā)現(xiàn)~ 可以用來獲取一些配置的信息,得到具體的微服務(wù) //添加對(duì)熔斷的支持 @EnableHystrix public class DeptProviderHystrix_8001 {public static void main(String[] args) {SpringApplication.run(DeptProviderHystrix_8001.class, args);} }測(cè)試:
使用熔斷后,當(dāng)訪問一個(gè)不存在的id時(shí),前臺(tái)頁展示數(shù)據(jù)如下:
而不適用熔斷的springcloud-provider-dept–8001模塊訪問相同地址會(huì)出現(xiàn)下面狀況:
因此,為了避免因某個(gè)微服務(wù)后臺(tái)出現(xiàn)異常或錯(cuò)誤而導(dǎo)致整個(gè)應(yīng)用或網(wǎng)頁報(bào)錯(cuò),使用熔斷是必要的
8.5、服務(wù)降級(jí)
什么是服務(wù)降級(jí)?
服務(wù)降級(jí)是指 當(dāng)服務(wù)器壓力劇增的情況下,根據(jù)實(shí)際業(yè)務(wù)情況及流量,對(duì)一些服務(wù)和頁面有策略的不處理,或換種簡(jiǎn)單的方式處理,從而釋放服務(wù)器資源以保證核心業(yè)務(wù)正常運(yùn)作或高效運(yùn)作。說白了,就是盡可能的把系統(tǒng)資源讓給優(yōu)先級(jí)高的服務(wù)。
資源有限,而請(qǐng)求是無限的。如果在并發(fā)高峰期,不做服務(wù)降級(jí)處理,一方面肯定會(huì)影響整體服務(wù)的性能,嚴(yán)重的話可能會(huì)導(dǎo)致宕機(jī)某些重要的服務(wù)不可用。所以,一般在高峰期,為了保證核心功能服務(wù)的可用性,都要對(duì)某些服務(wù)降級(jí)處理。比如當(dāng)雙11活動(dòng)時(shí),把交易無關(guān)的服務(wù)統(tǒng)統(tǒng)降級(jí),如查看螞蟻深林,查看歷史訂單等等。
服務(wù)降級(jí)主要用于什么場(chǎng)景呢?當(dāng)整個(gè)微服務(wù)架構(gòu)整體的負(fù)載超出了預(yù)設(shè)的上限閾值或即將到來的流量預(yù)計(jì)將會(huì)超過預(yù)設(shè)的閾值時(shí),為了保證重要或基本的服務(wù)能正常運(yùn)行,可以將一些 不重要 或 不緊急 的服務(wù)或任務(wù)進(jìn)行服務(wù)的 延遲使用 或 暫停使用。
降級(jí)的方式可以根據(jù)業(yè)務(wù)來,可以延遲服務(wù),比如延遲給用戶增加積分,只是放到一個(gè)緩存中,等服務(wù)平穩(wěn)之后再執(zhí)行 ;或者在粒度范圍內(nèi)關(guān)閉服務(wù),比如關(guān)閉相關(guān)文章的推薦。
由上圖可得,當(dāng)某一時(shí)間內(nèi)服務(wù)A的訪問量暴增,而B和C的訪問量較少,為了緩解A服務(wù)的壓力,這時(shí)候需要B和C暫時(shí)關(guān)閉一些服務(wù)功能,去承擔(dān)A的部分服務(wù),從而為A分擔(dān)壓力,叫做服務(wù)降級(jí)。
服務(wù)降級(jí)需要考慮的問題
- 1)哪些服務(wù)是核心服務(wù),哪些服務(wù)是非核心服務(wù)?
- 2)哪些服務(wù)可以支持降級(jí),哪些服務(wù)不能支持降級(jí),降級(jí)策略是什么?
- 3)除服務(wù)降級(jí)之外是否存在更復(fù)雜的業(yè)務(wù)放通場(chǎng)景,策略是什么?
自動(dòng)降級(jí)分類
1)超時(shí)降級(jí):主要配置好超時(shí)時(shí)間和超時(shí)重試次數(shù)和機(jī)制,并使用異步機(jī)制探測(cè)回復(fù)情況
2)失敗次數(shù)降級(jí):主要是一些不穩(wěn)定的api,當(dāng)失敗調(diào)用次數(shù)達(dá)到一定閥值自動(dòng)降級(jí),同樣要使用異步機(jī)制探測(cè)回復(fù)情況
3)故障降級(jí):比如要調(diào)用的遠(yuǎn)程服務(wù)掛掉了(網(wǎng)絡(luò)故障、DNS故障、http服務(wù)返回錯(cuò)誤的狀態(tài)碼、rpc服務(wù)拋出異常),則可以直接降級(jí)。降級(jí)后的處理方案有:默認(rèn)值(比如庫存服務(wù)掛了,返回默認(rèn)現(xiàn)貨)、兜底數(shù)據(jù)(比如廣告掛了,返回提前準(zhǔn)備好的一些靜態(tài)頁面)、緩存(之前暫存的一些緩存數(shù)據(jù))
4)限流降級(jí):秒殺或者搶購一些限購商品時(shí),此時(shí)可能會(huì)因?yàn)樵L問量太大而導(dǎo)致系統(tǒng)崩潰,此時(shí)會(huì)使用限流來進(jìn)行限制訪問量,當(dāng)達(dá)到限流閥值,后續(xù)請(qǐng)求會(huì)被降級(jí);降級(jí)后的處理方案可以是:排隊(duì)頁面(將用戶導(dǎo)流到排隊(duì)頁面等一會(huì)重試)、無貨(直接告知用戶沒貨了)、錯(cuò)誤頁(如活動(dòng)太火爆了,稍后重試)。
在springcloud-api模塊下的 service包中 新建降級(jí)配置類 DeptClientServiceFallBackFactory.java
// 服務(wù)降級(jí)~ @Component public class DeptClientServiceFallbackFactory implements FallbackFactory {@Overridepublic DeptClientService create(Throwable throwable) {return new DeptClientService() {@Overridepublic Dept queryById(Long id) {return new Dept().setDeptno(id).setDname("id=>"+id+"沒有對(duì)應(yīng)的信息,客戶端提供了降級(jí)的信息,這個(gè)服務(wù)現(xiàn)在已經(jīng)被關(guān)閉了").setDb_source("沒有數(shù)據(jù)~");}@Overridepublic List<Dept> queryAll() {return null;}@Overridepublic boolean addDept(Dept dept) {return false;}};} }在DeptClientService中指定降級(jí)配置類DeptClientServiceFallBackFactory
@Configuration // 微服務(wù)客戶端注解,value:指定微服務(wù)的名字,這樣就可以使Feign客戶端直接找到對(duì)應(yīng)的微服務(wù) @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT" ,fallbackFactory = DeptClientServiceFallbackFactory.class) public interface DeptClientService {@GetMapping("/dept/get/{id}")Dept queryById(@PathVariable("id") Long id);@GetMapping("/dept/list")List<Dept> queryAll();@PostMapping("/dept/add")boolean addDept(Dept dept); }在springcloud-consumer-dept-feign模塊中開啟降級(jí):
server:port: 80# 開啟降級(jí)feign.hystrix feign:hystrix:enabled: true# Eureka 配置 eureka:client:register-with-eureka: falseservice-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/8.6、服務(wù)熔斷和降級(jí)的區(qū)別
服務(wù)熔斷—>服務(wù)端:某個(gè)服務(wù)超時(shí)或異常,引起熔斷~,類似于保險(xiǎn)絲(自我熔斷)
服務(wù)降級(jí)—>客戶端:從整體網(wǎng)站請(qǐng)求負(fù)載考慮,當(dāng)某個(gè)服務(wù)熔斷或者關(guān)閉之后,服務(wù)將不再被調(diào)用,此時(shí)在客戶端,我們可以準(zhǔn)備一個(gè) FallBackFactory ,返回一個(gè)默認(rèn)的值(缺省值)。會(huì)導(dǎo)致整體的服務(wù)下降,但是好歹能用,比直接掛掉強(qiáng)。
觸發(fā)原因不太一樣,服務(wù)熔斷一般是某個(gè)服務(wù)(下游服務(wù))故障引起,而服務(wù)降級(jí)一般是從整體負(fù)荷考慮;管理目標(biāo)的層次不太一樣,熔斷其實(shí)是一個(gè)框架級(jí)的處理,每個(gè)微服務(wù)都需要(無層級(jí)之分),而降級(jí)一般需要對(duì)業(yè)務(wù)有層級(jí)之分(比如降級(jí)一般是從最外圍服務(wù)開始)
實(shí)現(xiàn)方式不太一樣,服務(wù)降級(jí)具有代碼侵入性(由控制器完成/或自動(dòng)降級(jí)),熔斷一般稱為自我熔斷。
熔斷,降級(jí),限流:
限流:限制并發(fā)的請(qǐng)求訪問量,超過閾值則拒絕;
降級(jí):服務(wù)分優(yōu)先級(jí),犧牲非核心服務(wù)(不可用),保證核心服務(wù)穩(wěn)定;從整體負(fù)荷考慮;
熔斷:依賴的下游服務(wù)故障觸發(fā)熔斷,避免引發(fā)本系統(tǒng)崩潰;系統(tǒng)自動(dòng)執(zhí)行和恢復(fù)
8.7、Dashboard 流監(jiān)控
新建 springcloud-consumer-hystrix-dashboard 模塊
添加依賴
spring-cloud-starter-hystrix 已停止維護(hù),推薦使用 spring-cloud-starter-netflix-hystrix
<dependencies><!--Hystrix依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId><version>2.2.9.RELEASE</version></dependency><!--dashboard依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId><version>2.2.9.RELEASE</version></dependency><!--Ribbon--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId><version>2.2.9.RELEASE</version></dependency><!--Eureka: Ribbon需要從Eureka服務(wù)中心獲取要拿什么--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.2.9.RELEASE</version></dependency><dependency><groupId>com.su</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><version>2.4.5</version></dependency> </dependencies>配置文件
server:port: 9001主啟動(dòng)類
@SpringBootApplication @EnableHystrixDashboard // 開啟 public class DeptConsumerDashboard_9001 {public static void main(String[] args) {SpringApplication.run(DeptConsumerDashboard_9001.class, args);} }啟動(dòng)后訪問 http://localhost:9001/hystrix
給springcloud-provider-dept-hystrix-8001模塊下的主啟動(dòng)類添加如下代碼,添加監(jiān)控
@SpringBootApplication @EnableEurekaClient // 自動(dòng)在服務(wù)啟動(dòng)后,自動(dòng)注冊(cè)到Eureka中! @EnableDiscoveryClient // 服務(wù)發(fā)現(xiàn)~ 可以用來獲取一些配置的信息,得到具體的微服務(wù) //添加對(duì)熔斷的支持 @EnableHystrix public class DeptProviderHystrix_8001 {public static void main(String[] args) {SpringApplication.run(DeptProviderHystrix_8001.class, args);}// 增加一個(gè)Servlet@Beanpublic ServletRegistrationBean hystrixMetricsStreamServlet(){ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());//訪問該頁面就是監(jiān)控頁面registrationBean.addUrlMappings("/actuator/hystrix.stream");return registrationBean;} }訪問 http://localhost:8001/actuator/hystrix.stream
這里如果一直ping的話,啟動(dòng)80端口,訪問http://localhost/consumer/dept/get/1之后
再次訪問http://localhost:8001/actuator/hystrix.stream
進(jìn)入監(jiān)控頁面:
Unable to connect to Command Metric Stream 可以在
9001模塊的配置文件下添加:
hystrix:dashboard:proxy-stream-allow-list: "*"重新訪問
現(xiàn)在訪問http://localhost/consumer/dept/get/1
一直刷新,發(fā)現(xiàn)刷新的越快,這個(gè)圓圈就變的越大,停止一段時(shí)間后又變小
如何看
-
七色
-
一圈
實(shí)心圓:公有兩種含義,他通過顏色的變化代表了實(shí)例的健康程度
它的健康程度從綠色<黃色<橙色<紅色 遞減
該實(shí)心圓除了顏色的變化之外,它的大小也會(huì)根據(jù)實(shí)例的請(qǐng)求流量發(fā)生變化,流量越大,該實(shí)心圓就越大,所以通過該實(shí)心圓的展示,就可以在大量的實(shí)例中快速發(fā)現(xiàn)故障實(shí)例和高壓力實(shí)例
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-sgHxgw2K-1640001797533)(G:\jieduan2333\JavaEE第四階段\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1MjIzMTU5NTc0Mg==,size_16,color_FFFFFF,t_70)]
-
一線
曲線:用來記錄2分鐘內(nèi)流量的相對(duì)變化,可以通過它來觀察流量的上升和下降趨勢(shì)
-
整圖說明
搞懂一個(gè)才能看懂復(fù)雜的
9、Zull路由網(wǎng)關(guān)
9.1、概述
什么是zuul?
Zull包含了對(duì)請(qǐng)求的路由和過濾兩個(gè)最主要功能:
其中路由功能負(fù)責(zé)將外部請(qǐng)求轉(zhuǎn)發(fā)到具體的微服務(wù)實(shí)例上,是實(shí)現(xiàn)外部訪問統(tǒng)一入口的基礎(chǔ),而過濾器功能則負(fù)責(zé)對(duì)請(qǐng)求的處理過程進(jìn)行干預(yù),是實(shí)現(xiàn)請(qǐng)求校驗(yàn),服務(wù)聚合等功能的基礎(chǔ)。Zuul和Eureka進(jìn)行整合,將Zuul自身注冊(cè)為Eureka服務(wù)治理下的應(yīng)用,同時(shí)從Eureka中獲得其他服務(wù)的消息,也即以后的訪問微服務(wù)都是通過Zuul跳轉(zhuǎn)后獲得。
注意:Zuul 服務(wù)最終還是會(huì)注冊(cè)進(jìn) Eureka
提供:代理 + 路由 + 過濾 三大功能!
Zuul 能干嘛?
- 路由
- 過濾
官方文檔:https://github.com/Netflix/zuul/
新建springcloud-zuul模塊,并導(dǎo)入依賴
spring-cloud-starter-zuul 已經(jīng)停止維護(hù),建議使用 spring-cloud-starter-netflix-zuul
<!-- zuul依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId><version>2.2.9.RELEASE</version></dependency><!-- Hystrix依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId><version>2.2.9.RELEASE</version></dependency><!--dashboard依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId><version>2.2.9.RELEASE</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>3.0.3</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId><version>2.2.9.RELEASE</version></dependency><!--Eureka: Ribbon需要從Eureka服務(wù)中心獲取要拿什么--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.2.9.RELEASE</version></dependency><dependency><groupId>com.su</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><version>2.4.5</version></dependency> </dependencies>application.yml
server:port: 9527spring:application:name: springcloud-zuuleureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: zuul9527.comprefer-ip-address: trueinfo:app.name: kuang-springcloud # 項(xiàng)目名稱company.name: blog.kuangstudy.com # 公司名稱# zull 路由網(wǎng)關(guān)配置 zuul:# 路由相關(guān)配置# 原來訪問路由 http://www.kuangstudy.com:9527/springcloud-provider-dept/dept/get/1# zull路由配置后訪問路由 http://www.kuangstudy.com:9527/kuang/mydept/dept/get/1routes:mydept.serviceId: springcloud-provider-dept # eureka注冊(cè)中心的服務(wù)提供方路由名稱mydept.path: /mydept/** # 將eureka注冊(cè)中心的服務(wù)提供方路由名稱 改為自定義路由名稱# 不能再使用這個(gè)路徑訪問了,*: 忽略,隱藏全部的服務(wù)名稱~ignored-services: "*"# 設(shè)置公共的前綴prefix: /kuang修改 hosts
主啟動(dòng)類
@SpringBootApplication @EnableZuulProxy // 開啟zuul public class ZuulApplication_9527 {public static void main(String[] args) {SpringApplication.run(ZuulApplication_9527.class, args);} }測(cè)試
可以看出Zull路由網(wǎng)關(guān)被注冊(cè)到Eureka注冊(cè)中心中了!
上圖是沒有經(jīng)過Zull路由網(wǎng)關(guān)配置時(shí),服務(wù)接口訪問的路由,可以看出直接用微服務(wù)(服務(wù)提供方)名稱去訪問,這樣不安全,不能將微服務(wù)名稱暴露!
所以經(jīng)過Zull路由網(wǎng)關(guān)配置后,訪問的路由為:
我們看到,微服務(wù)名稱被替換并隱藏,換成了我們自定義的微服務(wù)名稱mydept,同時(shí)加上了前綴haust,這樣就做到了對(duì)路由訪問的加密處理!
詳情參考springcloud中文社區(qū)zuul組件 :https://www.springcloud.cc/spring-cloud-greenwich.html#_router_and_filter_zuul
10、Spring Cloud Config 分布式配置
Dalston.RELEASE
Spring Cloud Config為分布式系統(tǒng)中的外部配置提供服務(wù)器和客戶端支持。使用Config Server,您可以在所有環(huán)境中管理應(yīng)用程序的外部屬性。客戶端和服務(wù)器上的概念映射與Spring Environment和PropertySource抽象相同,因此它們與Spring應(yīng)用程序非常契合,但可以與任何以任何語言運(yùn)行的應(yīng)用程序一起使用。隨著應(yīng)用程序通過從開發(fā)人員到測(cè)試和生產(chǎn)的部署流程,您可以管理這些環(huán)境之間的配置,并確定應(yīng)用程序具有遷移時(shí)需要運(yùn)行的一切。服務(wù)器存儲(chǔ)后端的默認(rèn)實(shí)現(xiàn)使用git,因此它輕松支持標(biāo)簽版本的配置環(huán)境,以及可以訪問用于管理內(nèi)容的各種工具。很容易添加替代實(shí)現(xiàn),并使用Spring配置將其插入。
10.1、概述
分布式系統(tǒng)面臨的–配置文件問題
微服務(wù)意味著要將單體應(yīng)用中的業(yè)務(wù)拆分成一個(gè)個(gè)子服務(wù),每個(gè)服務(wù)的粒度相對(duì)較小,因此系統(tǒng)中會(huì)出現(xiàn)大量的服務(wù),由于每個(gè)服務(wù)都需要必要的配置信息才能運(yùn)行,所以一套集中式的,動(dòng)態(tài)的配置管理設(shè)施是必不可少的。spring cloud提供了configServer來解決這個(gè)問題,我們每一個(gè)微服務(wù)自己帶著一個(gè)application.yml,那上百個(gè)的配置文件修改起來,令人頭疼!
什么是SpringCloud config分布式配置中心?
spring cloud config 為微服務(wù)架構(gòu)中的微服務(wù)提供集中化的外部支持,配置服務(wù)器為各個(gè)不同微服務(wù)應(yīng)用的所有環(huán)節(jié)提供了一個(gè)中心化的外部配置。
spring cloud config 分為服務(wù)端和客戶端兩部分。
服務(wù)端也稱為 分布式配置中心,它是一個(gè)獨(dú)立的微服務(wù)應(yīng)用,用來連接配置服務(wù)器并為客戶端提供獲取配置信息,加密,解密信息等訪問接口。
客戶端則是通過指定的配置中心來管理應(yīng)用資源,以及與業(yè)務(wù)相關(guān)的配置內(nèi)容,并在啟動(dòng)的時(shí)候從配置中心獲取和加載配置信息。配置服務(wù)器默認(rèn)采用git來存儲(chǔ)配置信息,這樣就有助于對(duì)環(huán)境配置進(jìn)行版本管理。并且可用通過git客戶端工具來方便的管理和訪問配置內(nèi)容。
spring cloud config 分布式配置中心能干嘛?
- 集中式管理配置文件
- 不同環(huán)境,不同配置,動(dòng)態(tài)化的配置更新,分環(huán)境部署,比如 /dev /test /prod /beta /release
- 運(yùn)行期間動(dòng)態(tài)調(diào)整配置,不再需要在每個(gè)服務(wù)部署的機(jī)器上編寫配置文件,服務(wù)會(huì)向配置中心統(tǒng)一拉取配置自己的信息
- 當(dāng)配置發(fā)生變動(dòng)時(shí),服務(wù)不需要重啟,即可感知到配置的變化,并應(yīng)用新的配置
- 將配置信息以REST接口的形式暴露
spring cloud config 分布式配置中心與GitHub整合
由于spring cloud config 默認(rèn)使用git來存儲(chǔ)配置文件 (也有其他方式,比如自持SVN 和本地文件),但是最推薦的還是git ,而且使用的是 http / https 訪問的形式。
10.2、入門案例
在碼云新建倉庫 springcloud-config
克隆到本地
新建application.yml文件
spring:profiles:active: dev--- spring:profiles: devapplication:name: springcloud-config-dev--- spring:profiles: testapplication:name: springcloud-config-test然后上傳到云倉庫
https://gitee.com/su_shuwang/springcloud-config
服務(wù)端
新建springcloud-config-server-3344模塊導(dǎo)入pom.xml依賴
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--Eureka--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.2.9.RELEASE</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId><version>2.2.6.RELEASE</version></dependency><!-- actuator完善監(jiān)控信息--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> </dependencies>resource下創(chuàng)建application.yml配置文件,Spring Cloud Config服務(wù)器從git存儲(chǔ)庫(必須提供)為遠(yuǎn)程客戶端提供配置:
server:port: 3344spring:application:name: springcloud-config-server# 連接碼云遠(yuǎn)程倉庫cloud:config:server:git:# 注意是https的而不是sshuri: https://gitee.com/su_shuwang/springcloud-config.git# 不加這個(gè)配置會(huì)報(bào)Cannot execute request on any known server 這個(gè)錯(cuò):連接Eureka服務(wù)端地址不對(duì) # 或者直接注釋掉eureka依賴 這里暫時(shí)用不到eureka eureka:client:register-with-eureka: falsefetch-registry: false主啟動(dòng)類
@SpringBootApplication @EnableConfigServer public class Config_Server_3344 {public static void main(String[] args) {SpringApplication.run(Config_Server_3344.class, args);} }測(cè)試訪問http://localhost:3344/application-dev.yml
測(cè)試訪問http://localhost:3344/application-test.yml
測(cè)試訪問 http://localhost:3344/application/test/master
定位資源的默認(rèn)策略是克隆一個(gè)git倉庫(在spring.cloud.config.server.git.uri),并使用它來初始化一個(gè)迷你SpringApplication。小應(yīng)用程序的Environment用于枚舉屬性源并通過JSON端點(diǎn)發(fā)布。
HTTP服務(wù)具有以下格式的資源:
/{application}/{profile}[/{label}] /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties其中“應(yīng)用程序”作為SpringApplication中的spring.config.name注入(即常規(guī)的Spring Boot應(yīng)用程序中通常是“應(yīng)用程序”),“配置文件”是活動(dòng)配置文件(或逗號(hào)分隔列表的屬性),“l(fā)abel”是可選的git標(biāo)簽(默認(rèn)為“master”)。
客戶端
在本地git倉庫springcloud-config文件夾下新建的config-client.yml提交到碼云倉庫:
spring:profiles:active: dev--- server:port: 8201# spring的配置 spring:profiles: devapplication:name: springcloud-provider-dept# Eureka 的配置, 服務(wù)注冊(cè)到哪里 eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/--- server:port: 8202# spring的配置 spring:profiles: testapplication:name: springcloud-provider-dept# Eureka 的配置, 服務(wù)注冊(cè)到哪里 eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/新建一個(gè)springcloud-config-client-3355模塊,并導(dǎo)入依賴
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId><version>2.2.8.RELEASE</version></dependency><!-- actuator完善監(jiān)控信息--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> </dependencies>resources下創(chuàng)建application.yml和bootstrap.yml配置文件
bootstrap.yml 是系統(tǒng)級(jí)別的配置
# 系統(tǒng)級(jí)別的配置 spring:cloud:config:uri: http://localhost:3344name: config-client # 需要從git上讀取的資源名稱,不需要后綴profile: devlabel: masterapplication.yml 是用戶級(jí)別的配置
# 用戶級(jí)別的配置 spring:application:name: springcloud-config-client-3355創(chuàng)建controller包下的ConfigClientController.java 用于測(cè)試
@RestController public class ConfigClientController {@Value("${spring.application.name}")private String applicationName;@Value("${spring.client.service-url.defaultZone}")private String eurekaServer;@Value("${server.port}")private String port;@GetMapping("/config")public String getConfig() {return "applicationName:" + applicationName +"eurekaServer:" + eurekaServer +"port:" + port;} }主啟動(dòng)類
@SpringBootApplication public class ConfigClient_3355 {public static void main(String[] args) {SpringApplication.run(ConfigClient_3355.class, args);} }測(cè)試:
啟動(dòng)服務(wù)端Config_server_3344 再啟動(dòng)客戶端ConfigClient
訪問:http://localhost:8201/config/
10.3、實(shí)戰(zhàn)測(cè)試
在springcloud-config下新建config-eureka.yml 文件
spring:profiles:active: dev---server:port: 7001spring:profiles: devapplication:name: springcloud-config-eurekaeureka:instance:hostname: eureka7001.comclient:register-with-eureka: falsefetch-registry: falseservice-url:defaultZone: http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/---server:port: 7001spring:profiles: testapplication:name: springcloud-config-eurekaeureka:instance:hostname: eureka7001.comclient:register-with-eureka: falsefetch-registry: falseservice-url:defaultZone: http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/新建config-dept.yml文件
spring:profiles:active: dev---server:port: 8001mybatis:type-aliases-package: com.su.springcloud.pojoconfig-location: classpath:mybatis/mybatis-config.xmlmapper-locations: classpath:mybatis/mapper/*.xmlspring:profiles: devapplication:name: springcloud-provider-deptdatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: rootpassword: 123456eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: springcloud-provider-dept8001 # 修改Eureka 上的默認(rèn)描述信息prefer-ip-address: true # 訪問路徑可以顯示ip地址info:app.name: kuangshen-springcloudcompany.name: blog.kuangstudy.com---server:port: 8001mybatis:type-aliases-package: com.su.springcloud.pojoconfig-location: classpath:mybatis/mybatis-config.xmlmapper-locations: classpath:mybatis/mapper/*.xmlspring:profiles: testapplication:name: springcloud-provider-deptdatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/db02?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: rootpassword: 123456eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: springcloud-provider-dept8001 # 修改Eureka 上的默認(rèn)描述信息prefer-ip-address: true # 訪問路徑可以顯示ip地址info:app.name: kuangshen-springcloudcompany.name: blog.kuangstudy.com上傳云倉庫
新建springcloud-config-eureka-7001模塊,并將原來的springcloud-eureka-7001模塊下的內(nèi)容拷貝的該模塊。
1.在pom.xml中添加spring cloud config依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId><version>2.2.8.RELEASE</version> </dependency>2.清空該模塊的application.yml配置,并新建bootstrap.yml連接遠(yuǎn)程配置
bootstrap.yml
spring:cloud:config:name: config-eurekalabel: masterprofile: devuri: http://localhost:3344application.yml
spring:application:name: spring-cloud-eureka-70013.主啟動(dòng)類
4.測(cè)試
第一步:啟動(dòng) Config_Server_3344,并訪問 http://localhost:3344/master/config-eureka-dev.yml 測(cè)試
第二部:啟動(dòng)ConfigEurekaServer_7001,訪問 http://localhost:7001/ 測(cè)試
顯示上圖則成功
新建springcloud-config-dept-8001模塊并拷貝springcloud-provider-dept-8001的內(nèi)容
同理導(dǎo)入spring cloud config依賴、清空application.yml 、新建bootstrap.yml配置文件并配置
spring:cloud:config:name: config-deptlabel: masterprofile: devuri: http://localhost:3344用戶級(jí)別的配置
spring:application:name: springcloud-config-client-3355主啟動(dòng)類
@SpringBootApplication @EnableEurekaClient // 自動(dòng)在服務(wù)啟動(dòng)后,自動(dòng)注冊(cè)到Eureka中! @EnableDiscoveryClient // 服務(wù)發(fā)現(xiàn)~ 可以用來獲取一些配置的信息,得到具體的微服務(wù) public class ConfigDeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(ConfigDeptProvider_8001.class, args);} }完結(jié)撒花
總結(jié)
以上是生活随笔為你收集整理的SpringCloud 超详细个人笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: access开发精要(4)-参考与查阅
- 下一篇: 学习Spring Boot:(十六)使用