中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

縣城做信息網(wǎng)站賺不賺錢(qián)品牌推廣策略怎么寫(xiě)

縣城做信息網(wǎng)站賺不賺錢(qián),品牌推廣策略怎么寫(xiě),怎么做獨(dú)立網(wǎng)站,微信運(yùn)營(yíng)簡(jiǎn)歷一、微服務(wù)演變 1、單體架構(gòu)(Monolithic Architecture) 是一種傳統(tǒng)的軟件架構(gòu)模式,應(yīng)用程序的所有功能和組件都集中在一個(gè)單一的應(yīng)用中。 在單體架構(gòu)中,應(yīng)用程序通常由一個(gè)大型的、單一的代碼庫(kù)組成,其中包含了所有…

一、微服務(wù)演變

1、單體架構(gòu)(Monolithic Architecture)

是一種傳統(tǒng)的軟件架構(gòu)模式,應(yīng)用程序的所有功能和組件都集中在一個(gè)單一的應(yīng)用中。

在單體架構(gòu)中,應(yīng)用程序通常由一個(gè)大型的、單一的代碼庫(kù)組成,其中包含了所有的功能模塊和業(yè)務(wù)邏輯。這個(gè)應(yīng)用程序作為一個(gè)整體部署和運(yùn)行在一個(gè)應(yīng)用服務(wù)器上,并共享相同的內(nèi)存和數(shù)據(jù)庫(kù)。

當(dāng)單體架構(gòu)項(xiàng)目的性能無(wú)法滿(mǎn)足需求時(shí),但又希望繼續(xù)沿用單體架構(gòu)的話,你可以采取以下一些優(yōu)化手段來(lái)改善性能,如以下方法:

  1. 使用緩存:引入緩存機(jī)制,將經(jīng)常請(qǐng)求的數(shù)據(jù)緩存起來(lái),減少對(duì)數(shù)據(jù)庫(kù)等后端系統(tǒng)的訪問(wèn),以提高性能。

  2. 數(shù)據(jù)庫(kù)優(yōu)化:進(jìn)行數(shù)據(jù)庫(kù)性能調(diào)優(yōu),包括建立索引、優(yōu)化查詢(xún)語(yǔ)句、使用合適的數(shù)據(jù)庫(kù)引擎等,以提高數(shù)據(jù)庫(kù)的響應(yīng)速度。

  3. 使用消息隊(duì)列:引入消息隊(duì)列來(lái)解耦耗時(shí)操作,將其轉(zhuǎn)化為異步的處理任務(wù)。這樣可以提高并發(fā)處理能力和系統(tǒng)的響應(yīng)性能。

  4. 水平擴(kuò)展:通過(guò)復(fù)制多個(gè)實(shí)例來(lái)處理更多的請(qǐng)求??梢允褂秘?fù)載均衡器將請(qǐng)求分發(fā)到不同的實(shí)例上,從而提高系統(tǒng)的整體性能和容量。

  5. 引入分布式架構(gòu):將應(yīng)用程序拆分為多個(gè)獨(dú)立的服務(wù),并通過(guò)網(wǎng)絡(luò)進(jìn)行通信和協(xié)作。這樣可以將負(fù)載分散到多個(gè)節(jié)點(diǎn)上,提高整體性能和可伸縮性。

?接下來(lái)就說(shuō)一下單體架構(gòu)優(yōu)化中的引入分布式架構(gòu)。

2、分布式架構(gòu)

將系統(tǒng)的各個(gè)組件部署在不同的計(jì)算機(jī)節(jié)點(diǎn)上,并通過(guò)網(wǎng)絡(luò)進(jìn)行通信和協(xié)作的軟件架構(gòu)模式。在分布式架構(gòu)中,各個(gè)節(jié)點(diǎn)可以獨(dú)立運(yùn)行和處理任務(wù),并通過(guò)消息傳遞、遠(yuǎn)程過(guò)程調(diào)用或其他通信機(jī)制進(jìn)行數(shù)據(jù)交換和協(xié)調(diào)。

?在使用分布式時(shí),我們就會(huì)有一下的疑問(wèn):

  • 服務(wù)拆分到什么程度?
  • 服務(wù)集群地址如何維護(hù)?
  • 服務(wù)之間如何實(shí)現(xiàn)遠(yuǎn)程調(diào)用?
  • 服務(wù)健康狀況如何感知?

?3、微服務(wù)

?微服務(wù)是一種經(jīng)過(guò)改良好的架構(gòu)設(shè)計(jì)的分布式架構(gòu)方案,微服務(wù)架構(gòu)特征:

  1. 單一職責(zé):微服務(wù)拆分力度更小,每個(gè)服務(wù)都對(duì)應(yīng)唯一的服務(wù)能力,做的單一職責(zé),避免重復(fù)開(kāi)發(fā)
  2. 面向服務(wù):微服務(wù)對(duì)外暴露業(yè)務(wù)接口
  3. 自治:團(tuán)隊(duì)獨(dú)立、技術(shù)獨(dú)立、數(shù)據(jù)獨(dú)立、部署獨(dú)立
  4. 隔離性強(qiáng):服務(wù)調(diào)用做好隔離、容錯(cuò)、降級(jí),避免出現(xiàn)級(jí)聯(lián)問(wèn)題

假如我們有一個(gè)電商系統(tǒng),其中有以下一些微服務(wù):

  1. 用戶(hù)服務(wù)(User Service)負(fù)責(zé)用戶(hù)的注冊(cè)、登錄、信息管理等功能。
  2. 商品服務(wù)(Product Service)負(fù)責(zé)商品的查詢(xún)、添加、更新等功能。
  3. 訂單服務(wù)(Order Service)負(fù)責(zé)訂單的創(chuàng)建、支付、取消等功能。

現(xiàn)在假設(shè)用戶(hù)服務(wù)依賴(lài)于商品服務(wù)來(lái)獲取商品信息,并且訂單服務(wù)依賴(lài)于用戶(hù)服務(wù)來(lái)獲取用戶(hù)信息。這里我們可以看到微服務(wù)的幾個(gè)特征是如何應(yīng)用的:

  1. 單一職責(zé):每個(gè)微服務(wù)都具有清晰的職責(zé)。例如,用戶(hù)服務(wù)只負(fù)責(zé)用戶(hù)相關(guān)的功能,而不涉及商品或訂單。
  2. 面向服務(wù):每個(gè)微服務(wù)都對(duì)外暴露業(yè)務(wù)接口,其他微服務(wù)可以通過(guò)調(diào)用這些接口來(lái)訪問(wèn)所需的功能。例如,用戶(hù)服務(wù)可以提供獲取用戶(hù)信息的接口給訂單服務(wù)使用。
  3. 自治:每個(gè)微服務(wù)的團(tuán)隊(duì)在技術(shù)和數(shù)據(jù)上都是獨(dú)立的。例如,用戶(hù)服務(wù)的團(tuán)隊(duì)可以獨(dú)立開(kāi)發(fā)、測(cè)試、部署和擴(kuò)展該服務(wù),無(wú)需依賴(lài)其他團(tuán)隊(duì)。
  4. 隔離性強(qiáng):微服務(wù)之間的調(diào)用需要做好隔離、容錯(cuò)和降級(jí),以避免出現(xiàn)級(jí)聯(lián)問(wèn)題。例如,當(dāng)商品服務(wù)不可用時(shí),用戶(hù)服務(wù)可以使用緩存或默認(rèn)數(shù)據(jù)來(lái)避免影響用戶(hù)操作。

這個(gè)例子中提供了不同的微服務(wù)來(lái)處理不同的功能,并且彼此解耦、獨(dú)立運(yùn)行。每個(gè)微服務(wù)都具有單一職責(zé),對(duì)外提供明確定義的業(yè)務(wù)接口,團(tuán)隊(duì)在技術(shù)和數(shù)據(jù)上具有自治能力,同時(shí)采取適當(dāng)?shù)母綦x措施來(lái)保證系統(tǒng)的彈性和穩(wěn)定性。這些特征有助于提高開(kāi)發(fā)效率、靈活性和可維護(hù)性,使得微服務(wù)架構(gòu)在構(gòu)建大型、復(fù)雜系統(tǒng)時(shí)具有優(yōu)勢(shì)。

4、 總結(jié)

單體架構(gòu)特點(diǎn):簡(jiǎn)單方便,高度耦合,擴(kuò)展性差,合適小型項(xiàng)目。如:學(xué)生管理系統(tǒng)。

分布式架構(gòu)特點(diǎn):松耦合,擴(kuò)展性好,但架構(gòu)復(fù)雜,難道大,適合大型互聯(lián)網(wǎng)項(xiàng)目。如:京東、淘寶

微服務(wù):一種良好的分布式架構(gòu)方案。

  • 優(yōu)點(diǎn):拆分粒度更小、服務(wù)更獨(dú)立、耦合更低
  • 缺點(diǎn):架構(gòu)非常復(fù)雜,運(yùn)維、監(jiān)控、部署難道更高

5、微服務(wù)架構(gòu)

微服務(wù)這方案需要技術(shù)框架來(lái)落地實(shí)現(xiàn),全球的互聯(lián)網(wǎng)公司都在積極嘗試自己的微服務(wù)落地技術(shù)。在國(guó)內(nèi)最知名的就是SpringCloud和阿里巴巴的Dubbo。

5.1、 微服務(wù)技術(shù)對(duì)比

?Dubbo、Spring Cloud、Spring Cloud和Spring Cloud Alibaba都是用于構(gòu)建分布式系統(tǒng)的開(kāi)源框架。盡管它們的目標(biāo)相同,但它們?cè)趯?shí)現(xiàn)方式和功能特點(diǎn)上有所不同。

  1. Dubbo:Dubbo是一個(gè)高性能的分布式服務(wù)框架,由阿里巴巴開(kāi)發(fā)。它基于傳統(tǒng)的服務(wù)治理理念,提供了服務(wù)注冊(cè)、發(fā)現(xiàn)、路由、負(fù)載均衡、容錯(cuò)等功能。Dubbo的核心特點(diǎn)是高性能和低延遲的RPC調(diào)用,適用于大規(guī)模的微服務(wù)架構(gòu)。Dubbo提供了對(duì)多種協(xié)議(如Dubbo協(xié)議、REST協(xié)議)和注冊(cè)中心(如ZooKeeper、Consul)的支持。

  2. Spring Cloud:Spring Cloud是一個(gè)由Pivotal開(kāi)發(fā)的微服務(wù)框架,構(gòu)建在Spring Framework之上,使得構(gòu)建分布式系統(tǒng)更加便捷。它提供了一系列的組件和模塊,用于實(shí)現(xiàn)服務(wù)注冊(cè)與發(fā)現(xiàn)、負(fù)載均衡、斷路器、配置管理、消息總線等功能。Spring Cloud采用了Spring Boot作為底層的開(kāi)發(fā)框架,提供了更簡(jiǎn)潔、快速搭建分布式系統(tǒng)的解決方案。

  3. Spring Cloud Alibaba:Spring Cloud Alibaba是Spring Cloud與Alibaba開(kāi)放平臺(tái)合作的結(jié)果,提供了一些在云原生應(yīng)用開(kāi)發(fā)中常用的解決方案。它主要基于Spring Cloud框架,結(jié)合了一些Alibaba技術(shù)棧,如Nacos(服務(wù)注冊(cè)與發(fā)現(xiàn))、Sentinel(流量控制和熔斷降級(jí))、RocketMQ(消息驅(qū)動(dòng))等。Spring Cloud Alibaba旨在提供云原生應(yīng)用開(kāi)發(fā)的全棧解決方案。

雖然Dubbo和Spring Cloud都是用于構(gòu)建分布式系統(tǒng)的框架,但Dubbo更加注重于高性能的RPC調(diào)用和服務(wù)治理,而Spring Cloud則提供了一整套更全面的微服務(wù)解決方案。而Spring Cloud Alibaba則是在Spring Cloud的基礎(chǔ)上,進(jìn)一步整合了Alibaba的一些技術(shù),為云原生應(yīng)用提供更全面的開(kāi)發(fā)支持。選擇適合的框架取決于具體的需求、技術(shù)棧和團(tuán)隊(duì)偏好。

5.2、企業(yè)需求

  1. Spring Cloud + Spring Cloud Alibaba:Spring Cloud提供了豐富的微服務(wù)組件和解決方案,包括服務(wù)注冊(cè)與發(fā)現(xiàn)、負(fù)載均衡、斷路器、配置管理等。Spring Cloud Alibaba擴(kuò)展了Spring Cloud,整合了阿里巴巴技術(shù)棧,如Nacos(服務(wù)注冊(cè)與發(fā)現(xiàn))、Sentinel(流量控制和熔斷降級(jí))、RocketMQ(消息驅(qū)動(dòng))等。組合使用這兩個(gè)框架可以獲得全面的云原生應(yīng)用開(kāi)發(fā)解決方案,適用于構(gòu)建現(xiàn)代化的微服務(wù)架構(gòu)。

  2. Dubbo原生模式 + Spring Cloud Alibaba:Dubbo是一個(gè)高性能的RPC框架,提供了服務(wù)治理、負(fù)載均衡、容錯(cuò)等功能。Spring Cloud Alibaba擴(kuò)展了Dubbo,為Dubbo提供了更多云原生的支持,如Nacos作為注冊(cè)中心、Sentinel用于流量控制和熔斷降級(jí)等。通過(guò)將Dubbo和Spring Cloud Alibaba集成,可以獲得高性能的RPC調(diào)用和全面的云原生的服務(wù)治理解決方案。

無(wú)論是使用Spring Cloud + Spring Cloud Alibaba還是Dubbo原生模式 + Spring Cloud Alibaba,都可以受益于Spring Cloud和Spring Cloud Alibaba提供的豐富的微服務(wù)功能和云原生支持。具體選擇哪種組合取決于企業(yè)需求、技術(shù)棧和團(tuán)隊(duì)實(shí)際情況。需要評(píng)估技術(shù)要求、性能需求、開(kāi)發(fā)復(fù)雜度等因素,選擇適合的框架組合來(lái)構(gòu)建穩(wěn)定、高效的分布式系統(tǒng)。

二、spring cloud

SpringCloud是目前國(guó)內(nèi)使用最廣泛的微服務(wù)框架。官網(wǎng)地址:

????????????????????????????????????????????????Spring Cloud

SpringCloud集成了各種微服務(wù)功能組件,并基于SpringBoot實(shí)現(xiàn)了這些組件的自動(dòng)裝配,從而提供了良好的開(kāi)箱即用體驗(yàn):

?springCloud與SpringBoot的版本兼容關(guān)系

?本文學(xué)習(xí)版本是Hoxton.SR10,因此對(duì)應(yīng)的springboot版本是2.3.x版本。

1、服務(wù)拆分及遠(yuǎn)程調(diào)用

1.1、服務(wù)拆分
1.1.1、服務(wù)拆分注意事項(xiàng)
  1. 不同微服務(wù),不要重復(fù)開(kāi)發(fā)相同業(yè)務(wù)
  2. 微服務(wù)數(shù)據(jù)獨(dú)立,不要訪問(wèn)其他微服務(wù)的數(shù)據(jù)庫(kù)
  3. 微服務(wù)可以將自己的業(yè)務(wù)暴露為接口,供其它微服務(wù)調(diào)用

1.1.2、項(xiàng)目實(shí)戰(zhàn)

實(shí)戰(zhàn)代碼:阿里云下載

把數(shù)據(jù)庫(kù)文件那到數(shù)據(jù)庫(kù)管理工具里執(zhí)行和idea中導(dǎo)入cloud-demo項(xiàng)目

最終數(shù)據(jù)庫(kù)結(jié)構(gòu):

?對(duì)與cloud-demo這個(gè)項(xiàng)目主要看一下用戶(hù)和訂單如何進(jìn)行項(xiàng)目拆分的,結(jié)合這單體架構(gòu)的結(jié)果對(duì)比一下有什么變化和不同。

1.1.3、總結(jié)
  1. 微服務(wù)需要根據(jù)業(yè)務(wù)模塊拆分,做到單一職責(zé),不要重復(fù)開(kāi)發(fā)相同業(yè)務(wù)。
  2. 微服務(wù)可以將業(yè)務(wù)暴露為接口,供其他微服務(wù)使用。
  3. 不同微服務(wù)都應(yīng)該有自己獨(dú)立的數(shù)據(jù)庫(kù)。
1.2、遠(yuǎn)程調(diào)用

?需求:根據(jù)訂單id查詢(xún)訂單的同時(shí),把訂單所屬的用戶(hù)信息一起返回。

1.2.1、遠(yuǎn)程調(diào)用方法

?在我們的controller類(lèi)中使用@GetMapping("/user/{id}")向外暴露了一個(gè)接口來(lái)訪問(wèn),可以將user信息放回為json數(shù)據(jù)格式,我們可以想一下瀏覽器可以發(fā)一個(gè)Ajax請(qǐng)求來(lái)獲取數(shù)據(jù),我們的訂單服務(wù)可不可以發(fā)一個(gè)Ajax請(qǐng)求來(lái)獲取數(shù)據(jù)呢?

1.2.2、實(shí)現(xiàn)遠(yuǎn)程調(diào)用步驟
1)注冊(cè)RestTemplate
Spring Cloud中也使用了RestTemplate類(lèi)。RestTemplate是Spring框架中的一部分,它在Spring Cloud項(xiàng)目中被廣泛用于進(jìn)行微服務(wù)之間的通信。在微服務(wù)架構(gòu)中,各個(gè)微服務(wù)之間通常通過(guò)RESTful API進(jìn)行通信。為了簡(jiǎn)化這個(gè)過(guò)程,Spring Cloud對(duì)RestTemplate進(jìn)行了增強(qiáng),以便更好地支持微服務(wù)架構(gòu)。在Spring Cloud中,RestTemplate被稱(chēng)為"服務(wù)調(diào)用"的一部分。通過(guò)使用RestTemplate,開(kāi)發(fā)人員可以方便地發(fā)起HTTP請(qǐng)求來(lái)調(diào)用其他微服務(wù)的API。Spring Cloud還提供了一些增強(qiáng)功能,例如服務(wù)發(fā)現(xiàn)和負(fù)載均衡。開(kāi)發(fā)人員可以使用服務(wù)名代替具體的URL,Spring Cloud會(huì)自動(dòng)根據(jù)服務(wù)名找到可用的實(shí)例并進(jìn)行負(fù)載均衡,從而實(shí)現(xiàn)更靈活和高效的服務(wù)調(diào)用。需要注意的是,自Spring Cloud 2020.0.0版本(即Hoxton.SR9及之后的版本)開(kāi)始,官方推薦使用WebClient替代RestTemplate作為HTTP客戶(hù)端,因?yàn)閃ebClient提供了更強(qiáng)大、更靈活的功能,并且更適用于非阻塞的響應(yīng)式編程模型。但是,為了向后兼容,RestTemplate仍然可以繼續(xù)使用并被支持。

在order-service的OrderApplication中注冊(cè)ResteTemplate,將ResteTemplate用@Bean注解注冊(cè)為spring管理的對(duì)象,以后不管在什么地方都可以使用到RestTemplate對(duì)象。

?完成調(diào)用主要是在service層中實(shí)現(xiàn),向被調(diào)用服務(wù)發(fā)起一個(gè)Rest請(qǐng)求,在需要調(diào)用其他服務(wù)的服務(wù)中使用,實(shí)現(xiàn)步驟:

1、在服務(wù)啟動(dòng)類(lèi)中注冊(cè)RestTemplate,如這里是在order的啟動(dòng)類(lèi)中

2、在要調(diào)用其他服務(wù)的服務(wù)中的service層中自動(dòng)裝配RestTemplate對(duì)象

3、使用RestTemplate的api來(lái)實(shí)現(xiàn)即可,里面有很多api,這里我使用的是getForObject()方法

4、將遠(yuǎn)程調(diào)用返回的數(shù)據(jù)封裝到要封裝的對(duì)象中即可,這里我使用的是將遠(yuǎn)程調(diào)用獲取的user對(duì)象信息封裝到order對(duì)象中。

1.3、提供者與消費(fèi)者

?服務(wù)提供者:一次業(yè)務(wù)中,被其他微服務(wù)調(diào)用的服務(wù)。(提供接口給其他服務(wù)調(diào)用)如:user服務(wù)

服務(wù)消費(fèi)者:一次業(yè)務(wù)中,調(diào)用其他微服務(wù)的服務(wù)。(調(diào)用其他微服務(wù)提供的接口)如order服務(wù)

總結(jié):

1.服務(wù)調(diào)用關(guān)系

  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?服務(wù)提供者:暴露接口給其它微服務(wù)調(diào)用
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?服務(wù)消費(fèi)者:調(diào)用其它微服務(wù)提供的接口
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?提供者與消費(fèi)者角色其實(shí)是相對(duì)的
  • ? ? ? ? ? ? ? ? ? ? ? ? ? ?一個(gè)服務(wù)可以同時(shí)是服務(wù)提供者和服務(wù)消費(fèi)者

三、Eureka注冊(cè)中心

1、服務(wù)調(diào)用出現(xiàn)的問(wèn)題

在前面我們使用RestTemplate來(lái)實(shí)現(xiàn)服務(wù)遠(yuǎn)程調(diào)用,在寫(xiě)url時(shí)使用的是硬編碼方式,就會(huì)產(chǎn)生以下的問(wèn)題,這些問(wèn)題是值得我們考慮一下的。

  • 服務(wù)消費(fèi)者該如何獲取服務(wù)提供者的地址信息?
  • 如果有多個(gè)服務(wù)提供者,消費(fèi)者該如何選擇?
  • 消費(fèi)者如何得知服務(wù)提供者的健康狀態(tài)?

2、 Eureka基本原理

Eureka是Netflix開(kāi)源的服務(wù)治理框架,在Spring Cloud中廣泛應(yīng)用。它的基本原理是建立了一個(gè)分布式的服務(wù)注冊(cè)中心,用于管理和維護(hù)各個(gè)微服務(wù)實(shí)例的注冊(cè)和發(fā)現(xiàn)。

以下是Eureka的基本原理:

  1. Eureka服務(wù)器:Eureka由一個(gè)或多個(gè)Eureka服務(wù)器組成,它們構(gòu)成了服務(wù)注冊(cè)中心。每個(gè)微服務(wù)實(shí)例都將自己的信息注冊(cè)到Eureka服務(wù)器,包括服務(wù)名、主機(jī)名、端口號(hào)等。

  2. 服務(wù)注冊(cè):微服務(wù)啟動(dòng)時(shí),會(huì)向Eureka服務(wù)器發(fā)送注冊(cè)請(qǐng)求,將自己的信息注冊(cè)到注冊(cè)中心。注冊(cè)中心維護(hù)一個(gè)服務(wù)注冊(cè)表,記錄所有已注冊(cè)的微服務(wù)實(shí)例。

  3. 服務(wù)發(fā)現(xiàn):其他微服務(wù)需要調(diào)用某個(gè)服務(wù)時(shí),首先向注冊(cè)中心發(fā)送查詢(xún)請(qǐng)求,獲得目標(biāo)服務(wù)的實(shí)例列表。注冊(cè)中心將會(huì)返回所有可用的服務(wù)實(shí)例信息,包括IP地址、端口號(hào)等。

  4. 服務(wù)監(jiān)控:Eureka服務(wù)器會(huì)定期向已注冊(cè)的微服務(wù)實(shí)例發(fā)送心跳請(qǐng)求,微服務(wù)實(shí)例返回響應(yīng)以證明自己的健康狀態(tài)。如果一個(gè)微服務(wù)長(zhǎng)時(shí)間未發(fā)送心跳消息或返回異常狀態(tài),Eureka服務(wù)器將從注冊(cè)表中刪除該實(shí)例。

  5. 服務(wù)同步:Eureka服務(wù)器之間會(huì)相互復(fù)制注冊(cè)表信息,以保證數(shù)據(jù)的一致性。當(dāng)有新的微服務(wù)實(shí)例注冊(cè)或注銷(xiāo)時(shí),注冊(cè)中心會(huì)通知其他服務(wù)器進(jìn)行注冊(cè)表更新。

通過(guò)Eureka提供的服務(wù)注冊(cè)和發(fā)現(xiàn)機(jī)制,微服務(wù)之間可以動(dòng)態(tài)地發(fā)現(xiàn)和調(diào)用其他微服務(wù),從而實(shí)現(xiàn)了服務(wù)之間的解耦和靈活性。Eureka還提供了負(fù)載均衡、故障恢復(fù)等一些附加功能,使得微服務(wù)架構(gòu)更加可靠和高效。

回顧之前我們的幾個(gè)問(wèn)題:

消費(fèi)者該如何獲取服務(wù)提供者具體信息?

  • 服務(wù)提供者啟動(dòng)時(shí)向eureka注冊(cè)自己的信息
  • eureka保存這些信息
  • 消費(fèi)者根據(jù)服務(wù)名稱(chēng)向eureka拉取提供者信息

如果有多個(gè)服務(wù)提供者,消費(fèi)者該如何選擇?

  • 服務(wù)消費(fèi)者利用負(fù)載均衡算法,從服務(wù)列表中挑選一個(gè)

消費(fèi)者如何感知服務(wù)提供者健康狀態(tài)?

  • 服務(wù)提供者會(huì)每隔30秒向EurekaServer發(fā)送心跳請(qǐng)求,報(bào)告健康狀態(tài)
  • eureka會(huì)更新記錄服務(wù)列表信息,心跳不正常會(huì)被剔除
  • 消費(fèi)者就可以拉取到最新的信息
?總結(jié)

在Eureka架構(gòu)中,微服務(wù)角色有兩類(lèi):

? ?1、EurekaServer:服務(wù)端,注冊(cè)中心

  • 記錄服務(wù)信息
  • 心跳監(jiān)控

? ?2、EurekaClient: 客戶(hù)端

? ? ? ? ?1)Provider:服務(wù)提供者,例如案例中的 user-service

  • ? ? ? ? ? ? ? 注冊(cè)自己的信息到EurekaServer
  • ? ? ? ? ? ? ? 每隔30秒向EurekaServer發(fā)送心跳

? ? ? ? ?2)consumer:服務(wù)消費(fèi)者,例如案例中的 order-service

  • ? ? ? ? ? ? ? ? ? ? 根據(jù)服務(wù)名稱(chēng)從EurekaServer拉取服務(wù)列表
  • ? ? ? ? ? ? ? ? ? ? 基于服務(wù)列表做負(fù)載均衡,選中一個(gè)微服務(wù)后發(fā)起遠(yuǎn)程調(diào)用

3、手動(dòng)實(shí)戰(zhàn)

3.1、搭建eureka服務(wù)注冊(cè)中心(服務(wù)名稱(chēng))

1、創(chuàng)建項(xiàng)目,引入spring-cloud-starter-netflix-eureka-server的依賴(lài)

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>

?2、啟用Eureka服務(wù)器:創(chuàng)建一個(gè)啟動(dòng)類(lèi),并使用@EnableEurekaServer注解來(lái)啟用Eureka服務(wù)器功能。

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class,args);}
}

3、配置Eureka服務(wù)器:在應(yīng)用程序的配置文件(如application.propertiesapplication.yml)中配置Eureka服務(wù)器的相關(guān)信息,例如:

# 服務(wù)器配置
server:port: 10001   # Eureka服務(wù)器運(yùn)行的端口號(hào)# Spring應(yīng)用程序配置
spring:application:name: eurekaserver   # Eureka服務(wù)器應(yīng)用程序的名稱(chēng)# Eureka客戶(hù)端配置
eureka:client:service-url:defaultZone: http://localhost:10001/eureka/# Eureka客戶(hù)端注冊(cè)自身的Eureka服務(wù)器的URL# 在本例中,將Eureka服務(wù)器的URL設(shè)置為運(yùn)行在10001端口的本地服務(wù)器
3.2、注冊(cè)u(píng)ser-service

這個(gè)操作是在user-service項(xiàng)目下實(shí)現(xiàn)的,主要是將服務(wù)信息注冊(cè)到Eureka服務(wù)端,eureka將這些服務(wù)信息保存到注冊(cè)表中進(jìn)行管理。

將user-service服務(wù)注冊(cè)到EurekaServer步驟:
1、在user-service項(xiàng)目中引入spring-cloud-starter-netflix-eureka-client的依賴(lài)
   <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
2、在application.yml位置文件中編寫(xiě)配置
spring:application:name: userservice  #配置服務(wù)名稱(chēng)
eureka:client:service-url:defaultZone: http://localhost:10001/eureka/   #配置eureka服務(wù)地址信息

其實(shí)orderservice的注冊(cè)也是這兩個(gè)步驟,我就寫(xiě)了。

做完之后,我我們可以瀏覽一下eureka的服務(wù)網(wǎng)站看一下:http://localhost:10001

這里的端口號(hào)是你在自己的eureka的配置文件application.yml配置的eureka端口號(hào)一致。

?總結(jié):

1.服務(wù)注冊(cè)

  • 引入eureka-client依賴(lài)
  • 在application.yml中配置eureka地址

2.無(wú)論是消費(fèi)者還是提供者,引入eureka-client依賴(lài)
知道eureka(服務(wù)注冊(cè)中心)地址后,都可以完成服務(wù)注冊(cè)

3.3、在order-service完成服務(wù)拉取

服務(wù)拉取是基于服務(wù)名稱(chēng)獲取服務(wù)列表,然后在對(duì)服務(wù)列表做負(fù)載均衡

1.修改OrderService的代碼,修改訪問(wèn)的url路徑,用服務(wù)名代替ip、端口:
String url ="http://userservice/user/" + order.getUserId();
2.在order-service項(xiàng)目的啟動(dòng)類(lèi)OrderApplication中的RestTemplate添加負(fù)載均衡注解:
@Bean
@LoadBalanced  #負(fù)載均衡
public RestTemplate restTemplate() {return new RestTemplate();
}
總結(jié)

1.搭建EurekaServer

  • 引入eureka-server依賴(lài)
  • 添加@EnableEurekaServer注解
  • 在application.yml中配置eureka地址

2.服務(wù)注冊(cè)

  • 引入eureka-client依賴(lài)
  • 在application.yml中配置連接eureka服務(wù)注冊(cè)中心地址

3.服務(wù)發(fā)現(xiàn)

  • 引入eureka-client依賴(lài)
  • 在application.yml中配置eureka服務(wù)注冊(cè)中心地址
  • 給RestTemplate添加@LoadBalanced注解
  • 用服務(wù)提供者的服務(wù)名稱(chēng)遠(yuǎn)程調(diào)用

四、Ribbon負(fù)載均衡

Ribbon是一個(gè)負(fù)載均衡解決方案,主要用于在分布式系統(tǒng)中將負(fù)載均勻地分發(fā)給多個(gè)服務(wù)實(shí)例。它是Netflix開(kāi) 源的一個(gè)組件,常用于微服務(wù)架構(gòu)中。

1、負(fù)載均衡流程

?Ribbon的負(fù)載均衡原理可以概括如下:

  1. 服務(wù)注冊(cè):Ribbon首先需要與服務(wù)注冊(cè)中心(如Eureka、Consul等)進(jìn)行交互,獲取可用的服務(wù)實(shí)例列表。

  2. 負(fù)載均衡策略:Ribbon支持多種負(fù)載均衡策略,如隨機(jī)策略、輪詢(xún)策略、權(quán)重策略等。根據(jù)選擇的策略,Ribbon會(huì)根據(jù)服務(wù)實(shí)例的狀態(tài)、性能等因素來(lái)選擇一個(gè)合適的服務(wù)實(shí)例。

  3. 服務(wù)調(diào)用:一旦選擇了一個(gè)服務(wù)實(shí)例,Ribbon會(huì)將請(qǐng)求發(fā)送給該實(shí)例。它會(huì)維護(hù)一個(gè)與服務(wù)實(shí)例的長(zhǎng)連接,并在需要時(shí)將請(qǐng)求發(fā)送給該實(shí)例。

  4. 失敗處理:如果請(qǐng)求在與服務(wù)實(shí)例的通信中失敗,Ribbon會(huì)嘗試選擇另一個(gè)可用的服務(wù)實(shí)例進(jìn)行重試,以增加系統(tǒng)的可用性。

Ribbon還可以與其他組件配合使用,例如Netflix的Hystrix熔斷器,用于實(shí)現(xiàn)服務(wù)的容錯(cuò)和故障保護(hù)。

總之,Ribbon通過(guò)動(dòng)態(tài)獲取服務(wù)實(shí)例列表并根據(jù)負(fù)載均衡策略選擇合適的實(shí)例來(lái)進(jìn)行負(fù)載均衡,從而提高系統(tǒng)的性能、可用性和可擴(kuò)展性。

源碼執(zhí)行流程:

?2、Ribbon負(fù)載均衡策略

Ribbon負(fù)載均衡規(guī)則是一個(gè)叫做IRule的接口來(lái)實(shí)現(xiàn)的,每個(gè)子接口都是一種規(guī)則:

2.1、 負(fù)載均衡策略

?2.2、調(diào)整負(fù)責(zé)均衡策略的規(guī)則

通過(guò)定義IRule實(shí)現(xiàn)可以修改負(fù)載均衡規(guī)則,有兩種方式:

方式一:代碼方式

如消費(fèi)者服務(wù)order-service,只要在OrderApplication類(lèi)中定義一個(gè)新的IRule:

@Bean
public IRule iRule(){return new RandomRule();
}

其實(shí)也不一定要在OrderApplication啟動(dòng)類(lèi)中配置,也可以自己創(chuàng)建一個(gè)配置類(lèi)來(lái)配置,在有@configuration注解的類(lèi)就可以。

這種配置方案是全局的配置,只要使用了這種配置方案,以后不管你調(diào)用的是user-service服務(wù)還是order-service服務(wù)都是使用這里的配置方案。

方式二:配置文件方式

在order-service的application.yml文件中,添加新的配置也可以修改規(guī)則:

userservice: #被調(diào)用微服務(wù)器的服務(wù)名稱(chēng)ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #負(fù)載均衡規(guī)則

這種配置方案是只針對(duì)某個(gè)微服務(wù)的,是局部配置。

3、Ribbon餓加載

Ribbon默認(rèn)是采用懶加載,即第一次訪問(wèn)才會(huì)創(chuàng)建LoadBalanceClient,請(qǐng)求時(shí)間會(huì)很長(zhǎng)。

而餓加載則會(huì)在項(xiàng)目啟動(dòng)時(shí)創(chuàng)建,降低每一次訪問(wèn)的耗時(shí)

3.1、配置開(kāi)啟配置饑餓加載
#當(dāng)服務(wù)饑餓加載
ribbon:eager-load:enabled: true #開(kāi)啟饑餓加載clients: userservice #指定對(duì)userservice這個(gè)服務(wù)饑餓加載#當(dāng)有多個(gè)服務(wù)需要饑餓加載可以用下面的方式:
ribbon:eager-load:enabled: true #開(kāi)啟饑餓加載clients:  #指定對(duì)userservice這個(gè)服務(wù)饑餓加載- userservice - xxservice
總結(jié)
1.Ribbon負(fù)載均衡規(guī)則
  • 規(guī)則接口是IRule
  • 默認(rèn)實(shí)現(xiàn)是ZoneAvoidanceRule,根據(jù)zone選擇服務(wù)列表,然后輪詢(xún)
2.負(fù)載均衡自定義方式
  • 代碼方式:配置靈活,但修改時(shí)需要重新打包布
  • 配置方式:直觀,方便,無(wú)需重新打包發(fā)布但是無(wú)法做全局配置
3.饑餓加載
  • 開(kāi)啟饑餓加載
  • 指定饑餓加載的微服務(wù)名稱(chēng)

五、Nacos注冊(cè)中心

微服務(wù)的注冊(cè)中心我們已經(jīng)學(xué)了eureka,大家肯定會(huì)有疑問(wèn),為啥還有學(xué)校nacos呢?

其實(shí)nacos不僅有服務(wù)注冊(cè)中心和服務(wù)發(fā)現(xiàn)功能,還有更加強(qiáng)大的功能。

1、nacos和eureka對(duì)比

Nacos和Eureka是兩個(gè)常用的服務(wù)發(fā)現(xiàn)和注冊(cè)工具,它們都具有類(lèi)似的功能,但在一些方面存在一些差異。以下是Nacos和Eureka的一些對(duì)比:

  1. 開(kāi)發(fā)者生態(tài)圈:Nacos是由Alibaba開(kāi)發(fā)并開(kāi)源,擁有龐大的Alibaba生態(tài)圈支持,而Eureka是由Netflix開(kāi)發(fā)并開(kāi)源,得到了Netflix和Spring Cloud社區(qū)的廣泛應(yīng)用。

  2. 功能和特性:Nacos提供了更多的功能和特性,除了服務(wù)注冊(cè)與發(fā)現(xiàn)外,還包括配置管理、動(dòng)態(tài)DNS、動(dòng)態(tài)路由和流量管理等功能。Eureka主要關(guān)注服務(wù)注冊(cè)與發(fā)現(xiàn)的功能。

  3. 容錯(cuò)性:Nacos具有更強(qiáng)的容錯(cuò)性,支持多數(shù)據(jù)中心的分布式部署,可以保證在網(wǎng)絡(luò)分區(qū)和節(jié)點(diǎn)故障情況下的高可用性。Eureka在這方面的容錯(cuò)性相對(duì)較弱。

  4. 數(shù)據(jù)一致性:Nacos使用Raft算法來(lái)實(shí)現(xiàn)數(shù)據(jù)一致性和高可用性,而Eureka使用的是AP模型,即優(yōu)先保證可用性而不保證強(qiáng)一致性。

  5. 社區(qū)活躍度:Nacos的開(kāi)源社區(qū)活躍度相對(duì)較高,有更多的貢獻(xiàn)者和更新的版本發(fā)布。Eureka的開(kāi)源社區(qū)相對(duì)較少活躍,更新較為緩慢。

選擇使用Nacos還是Eureka可以根據(jù)具體需求和項(xiàng)目背景來(lái)決定。如果需要更多的功能和特性,以及較強(qiáng)的容錯(cuò)性和高可用性,Nacos可能是更好的選擇。如果項(xiàng)目已經(jīng)依賴(lài)于Netflix和Spring Cloud生態(tài)圈,或者對(duì)于服務(wù)注冊(cè)和發(fā)現(xiàn)的簡(jiǎn)單功能需求,Eureka可能是更適合的選項(xiàng)。

2、Nacos下載安裝服務(wù)注冊(cè)中心

2.1下載nacos

在Nacos的GitHub頁(yè)面,提供有下載鏈接,可以下載編譯好的Nacos服務(wù)端或者源代碼:

GitHub主頁(yè):https://github.com/alibaba/nacos

GitHub的Release下載頁(yè):https://github.com/alibaba/nacos/releases

這里我提供了阿里云盤(pán)下載:Nacos1.4.1

2.2、解壓Nacos

?我這里使用的是在Windows下安裝的。

直接解壓到一個(gè)沒(méi)有中文字符的路徑下。

?目錄說(shuō)明:

  • - bin:啟動(dòng)腳本
  • - conf:配置文件
2.2.1、配置端口

Nacos的默認(rèn)端口是8848,如果你電腦上的其它進(jìn)程占用了8848端口,請(qǐng)先嘗試關(guān)閉該進(jìn)程。

**如果無(wú)法關(guān)閉占用8848端口的進(jìn)程**,也可以進(jìn)入nacos的conf目錄,修改配置文件中的端口:

修改其中的內(nèi)容修改為一個(gè)沒(méi)有被占用的端口號(hào)。

2.2.2.啟動(dòng)nacos服務(wù)注冊(cè)中心

啟動(dòng)非常簡(jiǎn)單,進(jìn)入bin目錄,進(jìn)入cmd窗口執(zhí)行下面的命令

startup.cmd -m standalone#startup.cmd -m standalone 的含義是執(zhí)行Nacos服務(wù)器的啟動(dòng)腳本,并使用獨(dú)立模式啟動(dòng)Nacos服務(wù)器。
#這將在單個(gè)節(jié)點(diǎn)上運(yùn)行Nacos,并使用默認(rèn)的配置文件和端口。這個(gè)命令適用于簡(jiǎn)單部署或測(cè)試,并非生產(chǎn)環(huán)境下常見(jiàn)的集群模式啟動(dòng)命令。

執(zhí)行后的效果如圖:?

在瀏覽器輸入地址:http://127.0.0.1:8848/nacos即可:

用戶(hù)名和密碼都是:nacos

?網(wǎng)頁(yè)直接就是中文的,對(duì)于英語(yǔ)不太好的比eureka的友好。

3、將服務(wù)注冊(cè)到nacos服務(wù)注冊(cè)中心

1、在cloud-demo父工程中添加spring-cloud-alibaba的管理依賴(lài):

            <!--nacos版本管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.5.RELEASE</version><type>pom</type><scope>import</scope></dependency>

2、注釋掉order-service和user-service中原有的eureka依賴(lài)。

3、添加nacos的客戶(hù)端依賴(lài):

        <!-- nacos客戶(hù)端依賴(lài)包 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>

4、修改user-service & order-service中的application.yml文件,注釋掉eureka的地址,添加nacos地址:

spring:cloud:nacos:server-addr: localhost:8848

啟動(dòng)項(xiàng)目測(cè)試:

?其實(shí)eureka和nacos在spring-cloud中除了依賴(lài)和端口號(hào)配置不同外其他的使用都是一樣的,他們底層使用的接口都是一樣的,所以代碼其他地方根本不用做改變。

總結(jié):

1.Nacos服務(wù)搭建
  • 下載安裝包
  • 解壓
  • 在bin目錄下運(yùn)行指令:startup.cmd -mstandalone
2.Nacos服務(wù)注冊(cè)或發(fā)現(xiàn)
  • 引入nacos.discovery依賴(lài)
  • 配置nacos地址spring.cloudnacos.server-addr

4、Nacos服務(wù)分級(jí)存儲(chǔ)模型

之前我們?cè)趯W(xué)中,我們的服務(wù)分層都是只有兩層的,第一層是服務(wù),第二層是實(shí)例(如user-service、order-service),在我們部署時(shí),都是將這些服務(wù)我實(shí)例部署到一個(gè)機(jī)器上或者一個(gè)機(jī)房里,但是如果這個(gè)機(jī)房收到破壞(地震、火災(zāi))時(shí),服務(wù)就無(wú)法訪問(wèn)了。

? 而nacos服務(wù)分層存儲(chǔ)模型則引出了集群的概念,一個(gè)集群就好比是我們的一個(gè)機(jī)房,而我們的一個(gè)服務(wù)下面就可以部署很多個(gè)集群,每個(gè)集群就可以部署在全球各地(北京、上海、深圳等),因此服務(wù)的層次結(jié)構(gòu)就變成了三層(服務(wù)、集群、實(shí)例)。

4.1、服務(wù)跨集群調(diào)用問(wèn)題
  • ?服務(wù)調(diào)用盡可能選擇本地集群的服務(wù),跨集群調(diào)用延遲高
  • 本地集群不可以訪問(wèn)時(shí),在去訪問(wèn)其他集群

?4.2、服務(wù)集群實(shí)現(xiàn)

1、修改application.yml,添加如下內(nèi)容,配置服務(wù)集群名稱(chēng)

spring:cloud:nacos:server-addr: localhost:8848  #nacos 服務(wù)端地址cluster-name: YN #配置集群名稱(chēng),也就是機(jī)房位置,例如:YN ,云南

2、在Nacos控制臺(tái)可以看到集群變化

?現(xiàn)在的集群變成了yn,在沒(méi)有配置集群名稱(chēng)是default。

總結(jié)
1.Nacos服務(wù)分級(jí)存儲(chǔ)模型
  • 一級(jí)是服務(wù),例如userservice
  • 二級(jí)是集群,例如杭州或上海
  • 三級(jí)是實(shí)例,例如杭州機(jī)房的某臺(tái)部署了userservice的服務(wù)器
2.如何設(shè)置實(shí)例的集群屬性
  • 修改application.yml文件,添加spring.cloud.nacos.discovery.cluster-name屬性即可
4.3、Nacos集群負(fù)載均衡

Nacos集群負(fù)載均衡的規(guī)則其實(shí)是優(yōu)先選擇本集群內(nèi)的服務(wù),如果本服務(wù)掛了,才會(huì)去選擇其他集群的服務(wù)來(lái)訪問(wèn)。

配置

1、修改order-service中的application.yml,設(shè)置集群為HZ:

spring:cloud:nacos:server-addr: Localhost:8848    # nacos 服務(wù)端地加discovery:cLuster-name: HZdiscovery:cluster-name: bj    #配集群名稱(chēng),也就是機(jī)房位置

2、然后在order-service中設(shè)置負(fù)載均衡的IRule為NacosRule,這個(gè)規(guī)則優(yōu)先會(huì)尋找與自己同集群的服務(wù):

userservice:    #服務(wù)名稱(chēng)ribbon:NFLoadBalancerRulecassName: com.alibaba.cloud.nacos.ribbon.NacosRule #負(fù)載均衡規(guī)則

3、注意將user-service的權(quán)重都設(shè)置為1

總結(jié):

1.NacosRule負(fù)載均衡策略

  • 優(yōu)先選擇同集群服務(wù)實(shí)例列表
  • 本地集群找不到提供者,才去其它集群尋找,并且會(huì)報(bào)警告
  • 確定了可用實(shí)例列表后,再采用隨機(jī)負(fù)載均衡挑選實(shí)例
4.4、根據(jù)權(quán)重負(fù)載均衡

假設(shè)有一個(gè)微服務(wù)架構(gòu)的電子商務(wù)網(wǎng)站,其中包括以下幾個(gè)服務(wù):商品服務(wù)、訂單服務(wù)用戶(hù)服務(wù)。這些服務(wù)都注冊(cè)到了Nacos中進(jìn)行服務(wù)發(fā)現(xiàn),并且它們有不同的實(shí)例數(shù)和性能配置。在這種情況下,可以通過(guò)基于權(quán)重的負(fù)載均衡來(lái)實(shí)現(xiàn)對(duì)這些服務(wù)實(shí)例的合理請(qǐng)求分配。以下是一些示例場(chǎng)景:

  1. 不同實(shí)例性能差異較大:

    假設(shè)商品服務(wù)有3個(gè)實(shí)例,其中實(shí)例A和實(shí)例B配置較高,實(shí)例C配置較低。此時(shí),可以設(shè)置實(shí)例A和實(shí)例B的權(quán)重為2,實(shí)例C的權(quán)重為1。這樣,每次有請(qǐng)求到來(lái)時(shí),有較高性能的實(shí)例A和實(shí)例B將會(huì)處理更多的請(qǐng)求,而較低性能的實(shí)例C將會(huì)處理較少的請(qǐng)求,從而實(shí)現(xiàn)了性能調(diào)控。

  2. 服務(wù)實(shí)例容量不均衡:

    假設(shè)訂單服務(wù)有5個(gè)實(shí)例,其中實(shí)例A、B和C的容量比實(shí)例D和E大??梢詾閷?shí)例A、B和C設(shè)置較高的權(quán)重值,如3,而為實(shí)例D和E設(shè)置較低的權(quán)重值,如1。這樣,請(qǐng)求將均衡分配到實(shí)例A、B和C之間,并保持實(shí)例D和E的請(qǐng)求數(shù)較少。

  3. 降低故障實(shí)例的負(fù)載:

    假設(shè)用戶(hù)服務(wù)有4個(gè)實(shí)例,其中實(shí)例A由于某種原因,出現(xiàn)了故障或不穩(wěn)定情況。為了減少對(duì)實(shí)例A的請(qǐng)求分配,可以為其設(shè)置較低的權(quán)重值,如0,而將其他正常的實(shí)例設(shè)置為較高的權(quán)重值,如3。這樣,請(qǐng)求將主要被分配給其他正常的實(shí)例,降低了對(duì)故障實(shí)例A的負(fù)載。

通過(guò)在Nacos中設(shè)置服務(wù)實(shí)例的權(quán)重,可以根據(jù)實(shí)際情況動(dòng)態(tài)調(diào)整請(qǐng)求的負(fù)載比例。這樣能夠充分利用資源、提高系統(tǒng)性能、保證服務(wù)穩(wěn)定性,并對(duì)不同實(shí)例進(jìn)行合理分配。

Nacos提供了權(quán)重配置來(lái)控制訪問(wèn)頻率,權(quán)重越大則訪問(wèn)頻率越高。

配置

?

?4.5、環(huán)境隔離-namespace
1、認(rèn)識(shí)環(huán)境隔離-namvespace

應(yīng)用場(chǎng)景:

假設(shè)有一個(gè)電商平臺(tái),該平臺(tái)設(shè)計(jì)了一個(gè)基于Nacos的命名空間配置和服務(wù)注冊(cè)方案,以支持環(huán)境隔離和多租戶(hù)功能。

首先,假設(shè)該電商平臺(tái)有三個(gè)環(huán)境:開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境和生產(chǎn)環(huán)境。每個(gè)環(huán)境都有獨(dú)立的配置和服務(wù)需求。

  1. 環(huán)境隔離和配置管理:

    • 使用Nacos的命名空間功能,平臺(tái)管理員可以創(chuàng)建三個(gè)命名空間:dev-namespace、test-namespace和prod-namespace。

    • 在dev-namespace中,可以配置開(kāi)發(fā)環(huán)境所需的各種參數(shù),如數(shù)據(jù)庫(kù)連接信息、調(diào)試模式等。

    • 在test-namespace中,可以配置測(cè)試環(huán)境所需的參數(shù),如測(cè)試數(shù)據(jù)庫(kù)連接信息、測(cè)試數(shù)據(jù)源等。

    • 在prod-namespace中,可以配置生產(chǎn)環(huán)境所需的參數(shù),如正式數(shù)據(jù)庫(kù)連接信息、生產(chǎn)級(jí)別的服務(wù)配置等。

    • 每個(gè)命名空間下的配置項(xiàng)是相互隔離的,這樣就保證了不同環(huán)境配置的獨(dú)立性,并且可根據(jù)需求靈活管理和更新配置信息。

  2. 服務(wù)注冊(cè)和版本管理:

    • 在每個(gè)命名空間中,可以注冊(cè)相應(yīng)環(huán)境需要的服務(wù)實(shí)例,如商品服務(wù)、訂單服務(wù)等。

    • 平臺(tái)管理員可以使用命名空間功能來(lái)管理不同環(huán)境的服務(wù)注冊(cè)表,確保每個(gè)環(huán)境只能訪問(wèn)屬于自己的服務(wù)實(shí)例。

    • 每個(gè)命名空間可以獨(dú)立管理服務(wù)實(shí)例的版本,例如,在開(kāi)發(fā)環(huán)境中可以注冊(cè)和測(cè)試新的服務(wù)版本,而在生產(chǎn)環(huán)境中則使用穩(wěn)定的服務(wù)版本。

通過(guò)這樣的命名空間配置和服務(wù)注冊(cè)方案,電商平臺(tái)能夠?qū)崿F(xiàn)對(duì)不同環(huán)境的配置和服務(wù)進(jìn)行隔離,并支持多租戶(hù)功能。開(kāi)發(fā)團(tuán)隊(duì)可以獨(dú)立管理各自環(huán)境的配置和服務(wù),而不會(huì)相互干擾。此外,平臺(tái)還可以利用灰度發(fā)布和版本管理功能,在不同命名空間中進(jìn)行服務(wù)版本控制,確保系統(tǒng)穩(wěn)定性和可用性。

2、配置命名空間

1)創(chuàng)建命名空間(在nacos服務(wù)頁(yè)面創(chuàng)建)

?2、將服務(wù)配置到指定的命名空間中(修改application.yml配置文件)
server:port: 8081
spring:datasource:url: jdbc:mysql://192.168.10.130:3306/cloud-user?useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driverapplication:name: userservice  #配置服務(wù)名稱(chēng)cloud:nacos:server-addr: localhost:8848discovery:cluster-name: yn #集群名稱(chēng),地址在云南namespace: 074da7cb-c3e3-4848-b893-3d15114e8729  #命令空間id

?此時(shí),配置了namespace的服務(wù)已經(jīng)被配置到dev中了

?如果此時(shí)使用order-service去調(diào)用user-service就會(huì)報(bào)錯(cuò)了

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for userservice] with root causeservlet .service()的servlet [dispatcherServlet]在上下文與路徑[]拋出異常[請(qǐng)求處理失敗;嵌套異常是java.lang.IllegalStateException: No instances available for userservice],有根本原因

5、nacos注冊(cè)中介細(xì)節(jié)分析

?服務(wù)注冊(cè):服務(wù)提供者啟動(dòng)時(shí),會(huì)向服務(wù)注冊(cè)中心發(fā)起注冊(cè)請(qǐng)求,包括服務(wù)名、IP 地址、端口等。注冊(cè)中心會(huì)將這些信息保存起來(lái)。

服務(wù)發(fā)現(xiàn):服務(wù)發(fā)現(xiàn)有兩種(pull和push相結(jié)合)

  1. pull:服務(wù)消費(fèi)者會(huì)每隔30秒定時(shí)主動(dòng)向服務(wù)注冊(cè)中心發(fā)起請(qǐng)求,來(lái)拉取服務(wù)信息,在服務(wù)消費(fèi)者中有一個(gè)服務(wù)列表緩存,用于緩存從服務(wù)注冊(cè)中心拉取下的服務(wù)信息。
  2. push:當(dāng)有服務(wù)停掉后服務(wù)注冊(cè)中心會(huì)主動(dòng)推送變更信息給消費(fèi)者,消費(fèi)者就會(huì)更新服務(wù)列表緩存。

心跳與健康檢查:也是有兩種(對(duì)臨時(shí)實(shí)力和非臨時(shí)實(shí)例)

  1. 臨時(shí)實(shí)例:采心跳檢測(cè),是臨時(shí)實(shí)例主動(dòng)向注冊(cè)中心發(fā)送心跳檢測(cè),如果一段時(shí)間注冊(cè)中心沒(méi)有收到臨時(shí)實(shí)例心跳檢測(cè),就會(huì)剔除該臨時(shí)實(shí)例。
  2. 非臨時(shí)實(shí)例:采用nacos主動(dòng)詢(xún)問(wèn),nacos主動(dòng)詢(xún)問(wèn)非臨時(shí)實(shí)例的健康狀態(tài),如果非臨時(shí)實(shí)例停止了,也不會(huì)剔除非臨時(shí)實(shí)例,只是修改非臨時(shí)實(shí)例的健康轉(zhuǎn)態(tài),會(huì)等待非臨時(shí)實(shí)例健康。

負(fù)載均衡:負(fù)載均衡和流量控制是由服務(wù)消費(fèi)者一側(cè)的客戶(hù)端組件來(lái)實(shí)現(xiàn)的,而不是由注冊(cè)中心來(lái)處理。當(dāng)客戶(hù)端從Nacos注冊(cè)中心獲取到可用的服務(wù)實(shí)例列表后,負(fù)載均衡和流量控制的責(zé)任落在了客戶(hù)端的實(shí)現(xiàn)上。

5.1、臨時(shí)實(shí)例與非臨時(shí)實(shí)例

Nacos中的實(shí)例分為臨時(shí)實(shí)例和非臨時(shí)實(shí)例,它們?cè)谏芷诤陀猛旧嫌兴煌?#xff1a;

1、非臨時(shí)實(shí)例(Persistent Instance):

  • 非臨時(shí)實(shí)例是指注冊(cè)到Nacos注冊(cè)中心的服務(wù)實(shí)例,其生命周期不會(huì)受到外部因素的影響,除非主動(dòng)取消注冊(cè)或服務(wù)下線。
  • 這種實(shí)例適用于通常情況下穩(wěn)定運(yùn)行的服務(wù),它們的注冊(cè)信息會(huì)被持久化存儲(chǔ)在Nacos服務(wù)器中,提供持久性的服務(wù)發(fā)現(xiàn)和注冊(cè)功能。

2、臨時(shí)實(shí)例(Ephemeral Instance):

  • 臨時(shí)實(shí)例是指服務(wù)實(shí)例在持有連接的客戶(hù)端斷開(kāi)連接時(shí),會(huì)自動(dòng)從Nacos注冊(cè)中心上注銷(xiāo)的一種實(shí)例類(lèi)型。
  • 當(dāng)客戶(hù)端與Nacos注冊(cè)中心建立心跳連接后,臨時(shí)實(shí)例會(huì)周期性地向注冊(cè)中心進(jìn)行連接進(jìn)行檢測(cè)。如果一段時(shí)間注冊(cè)中心沒(méi)有收到臨時(shí)實(shí)例的心態(tài)檢測(cè),注冊(cè)中心會(huì)將對(duì)應(yīng)的實(shí)例注銷(xiāo)。
  • 臨時(shí)實(shí)例適用于動(dòng)態(tài)擴(kuò)縮容、臨時(shí)性訪問(wèn)等場(chǎng)景,允許實(shí)例根據(jù)連接狀態(tài)進(jìn)行動(dòng)態(tài)管理。

臨時(shí)實(shí)例和非臨時(shí)實(shí)例在實(shí)踐中有不同的應(yīng)用場(chǎng)景:

  • 對(duì)于穩(wěn)定運(yùn)行的服務(wù),應(yīng)使用非臨時(shí)實(shí)例。這樣服務(wù)實(shí)例的注冊(cè)信息將持久存在于注冊(cè)中心中,即使服務(wù)發(fā)生故障或重啟,也能保證注冊(cè)信息的持久性,其他服務(wù)能夠繼續(xù)發(fā)現(xiàn)和使用該實(shí)例。

  • 對(duì)于臨時(shí)性的任務(wù),如定時(shí)任務(wù)、臨時(shí)數(shù)據(jù)處理服務(wù)等,可以選擇使用臨時(shí)實(shí)例。這樣在任務(wù)完成后,實(shí)例會(huì)自動(dòng)注銷(xiāo),降低注冊(cè)中心中無(wú)用實(shí)例的數(shù)量,也能更好地適應(yīng)動(dòng)態(tài)需求變化。

需要注意的是,臨時(shí)實(shí)例的自動(dòng)注銷(xiāo)是基于與Nacos注冊(cè)中心之間的心跳連接,而非基于服務(wù)實(shí)例的具體運(yùn)行狀態(tài)。因此,在使用臨時(shí)實(shí)例時(shí),需要相應(yīng)地配置和管理心跳連接,以保證實(shí)例的不間斷注冊(cè)和注銷(xiāo)。

5.2、配置臨時(shí)實(shí)例與非臨時(shí)實(shí)例(默認(rèn)是臨時(shí)實(shí)例)

服務(wù)注冊(cè)到nacos時(shí),可以選擇注冊(cè)為臨時(shí)或非臨時(shí)實(shí)例,通過(guò)在application.yml文件中添加下面的配置來(lái)設(shè)置:

spring:cloud:nacos:discovery:   #discovery:發(fā)現(xiàn),透露 ; ephemeral:短暫的ephemeral: false  #設(shè)置為非臨時(shí)實(shí)例

?總結(jié)
1.Nacos與eureka的共同點(diǎn)
  • 都支持服務(wù)注冊(cè)和服務(wù)拉取
  • 都支持服務(wù)提供者心跳方式做健康檢測(cè)
2.Nacos與Eureka的區(qū)別
  • Nacos支持服務(wù)端主動(dòng)檢測(cè)提供者狀態(tài):臨時(shí)實(shí)例采用心跳模式,非臨時(shí)實(shí)例采用主動(dòng)檢測(cè)模式
  • 臨時(shí)實(shí)例心跳不正常會(huì)被剔除,非臨時(shí)實(shí)例則不會(huì)被剔除
  • Nacos支持服務(wù)列表變更的消息推送模式,服務(wù)列表更新更及時(shí)
  • Nacos集群默認(rèn)采用AP方式,當(dāng)集群中存在非臨時(shí)實(shí)例時(shí),采用CP模式;Eureka采用AP方式

6、Nacos配置管理

以下是幾個(gè)使用Nacos配置管理的實(shí)際業(yè)務(wù)場(chǎng)景的例子:

  1. 微服務(wù)配置管理:
    假設(shè)你的公司采用了微服務(wù)架構(gòu),有多個(gè)微服務(wù)需要連接到不同的數(shù)據(jù)庫(kù)。通過(guò)使用Nacos配置管理,你可以將每個(gè)微服務(wù)的數(shù)據(jù)庫(kù)連接信息存儲(chǔ)在Nacos中,并動(dòng)態(tài)地更新配置。例如,當(dāng)你需要更改數(shù)據(jù)庫(kù)的連接地址或密碼時(shí),你可以直接在Nacos中修改配置,而無(wú)需重新部署微服務(wù),所有微服務(wù)將自動(dòng)獲取最新的配置信息。

  2. 多環(huán)境配置管理:
    假設(shè)你的應(yīng)用在開(kāi)發(fā)、測(cè)試和生產(chǎn)環(huán)境中運(yùn)行,并且每個(gè)環(huán)境都有不同的配置。使用Nacos配置管理,你可以為每個(gè)環(huán)境創(chuàng)建不同的配置文件,并通過(guò)Nacos的命名空間和配置組進(jìn)行組織。開(kāi)發(fā)人員可以通過(guò)選擇不同的命名空間和配置組,輕松地切換到不同的環(huán)境,而不必手動(dòng)修改配置文件。

  3. 動(dòng)態(tài)路由配置:
    假設(shè)你的微服務(wù)架構(gòu)中使用了Spring Cloud Gateway作為API網(wǎng)關(guān),并且你希望能夠動(dòng)態(tài)路由請(qǐng)求到不同的后端服務(wù)。通過(guò)使用Nacos配置管理,你可以將路由規(guī)則存儲(chǔ)在Nacos中,并通過(guò)Spring Cloud Gateway與Nacos集成。當(dāng)需要更新路由規(guī)則時(shí),你可以直接在Nacos中修改配置,Spring Cloud Gateway將自動(dòng)更新路由,并將請(qǐng)求動(dòng)態(tài)地轉(zhuǎn)發(fā)到相應(yīng)的后端服務(wù)。

  4. 定時(shí)任務(wù)配置:
    假設(shè)你的應(yīng)用需要執(zhí)行定時(shí)任務(wù),例如生成報(bào)表或清理數(shù)據(jù)。通過(guò)使用Nacos配置管理,你可以將定時(shí)任務(wù)的觸發(fā)時(shí)間、任務(wù)參數(shù)等信息存儲(chǔ)在Nacos中,并由任務(wù)調(diào)度器定期從Nacos獲取最新的配置。當(dāng)你需要調(diào)整定時(shí)任務(wù)的執(zhí)行時(shí)間或參數(shù)時(shí),只需在Nacos中修改配置,任務(wù)調(diào)度器將自動(dòng)根據(jù)最新的配置執(zhí)行任務(wù)。

這些例子只是Nacos配置管理功能的一部分,Nacos還提供了更多的特性,例如配置監(jiān)聽(tīng)、配置推送等,可以根據(jù)具體的業(yè)務(wù)需求進(jìn)行靈活使用。

6.1、統(tǒng)一配置管理
6.1.1、配置更改熱更新

?在Nacos中添加配置信息:

?在彈出表單中填寫(xiě)配置信息:

?在nacos服務(wù)頁(yè)面中配置,讓服務(wù)找到nacos的配置:

1、引入nacos的配置管理客戶(hù)依賴(lài):
        <!--nacos配置管理依賴(lài)--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>
2、在userservice中的resource目錄添加一個(gè)bootstrap.yml文件,這個(gè)文件是引導(dǎo)文件,優(yōu)先級(jí)高于application.yml:
spring:application:name: userservice  #配置服務(wù)名稱(chēng)cloud:nacos:server-addr: localhost:8848   #配置nacos服務(wù)地址config:file-extension: yaml  #文件后綴profiles:active: dev  #開(kāi)發(fā)環(huán)境,這里是dev

可以在Usercontroller類(lèi)中獲取一下nacos配置的信息來(lái)驗(yàn)證一下:

    @Value("${pattern.dateformat}")private String dateformat;@GetMapping("/now")public String now(){return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));}
6.1.2、配置自動(dòng)刷新

nacos中的配置文件變更后,微服務(wù)無(wú)需重新啟動(dòng)就可以感知。不過(guò)需要通過(guò)下面兩種配置實(shí)現(xiàn):

方式一:在@Value注入的變量所在類(lèi)上添加注解@RefreshScope

?方式二:使用@ConfigurationProperties注解

這種方式使用的是約束大于配置的配置方法。

@Data
@Component
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {private String dateformat;
}

使用了Spring框架的注解(Data,Component,ConfigurationProperties)。這段代碼定義了一個(gè)名為PatternProperties的類(lèi)。

@ConfigurationProperties注解是Spring框架中用于綁定配置屬性的注解。它的prefix屬性指定了配置文件中的屬性前綴為"pattern",這意味著在配置文件中,所有以"pattern"開(kāi)頭的屬性會(huì)被綁定到PatternProperties類(lèi)的對(duì)應(yīng)屬性上。

PatternProperties類(lèi)中只有一個(gè)私有的String類(lèi)型屬性dateformat,它對(duì)應(yīng)配置文件中的"pattern.dateformat"屬性。在配置文件中,你可以設(shè)置這個(gè)屬性的值,例如:

pattern:dateformat: yyyy-MM-dd HH:mm:ss

這樣,當(dāng)你運(yùn)行程序時(shí),Spring框架會(huì)自動(dòng)將配置文件中的值綁定到PatternProperties類(lèi)的dateformat屬性上,你可以通過(guò)獲取PatternProperties實(shí)例的方式來(lái)訪問(wèn)并使用這個(gè)屬性的值。

在類(lèi)中使用nacos中配置時(shí)可以通過(guò)以下方式獲取:

?總結(jié)
Nacos配置更改后,微服務(wù)可以實(shí)現(xiàn)熱更新,方式:
  • 通過(guò)@Value注解注入,結(jié)合@RefreshScope來(lái)刷新
  • 通過(guò)@ConfigurationProperties注入,自動(dòng)刷新
注意事項(xiàng):
  • 不是所有的配置都適合放到配置中心,維護(hù)起來(lái)比較麻煩
  • 建議將一些關(guān)鍵參數(shù),需要運(yùn)行時(shí)調(diào)整的參數(shù)放到nacos配置中心,一般都是自定義配置

7、Nacos集群搭建

7.1、集群結(jié)構(gòu)圖
官方給出的Nacos集群圖:

其中包含3個(gè)nacos節(jié)點(diǎn),然后一個(gè)負(fù)載均衡器代理3個(gè)Nacos。這里負(fù)載均衡器可以使用nginx。

DNS(Domain Name System)、SLB(Server Load Balancer)和Nacos可以一起使用來(lái)構(gòu)建一個(gè)完整的服務(wù)發(fā)現(xiàn)和負(fù)載均衡的系統(tǒng)。

DNS是用于將域名解析為對(duì)應(yīng)的IP地址的系統(tǒng)。在服務(wù)發(fā)現(xiàn)和負(fù)載均衡中,DNS可以被用來(lái)解析服務(wù)名稱(chēng)為對(duì)應(yīng)的服務(wù)實(shí)例的IP地址。例如,假設(shè)有一個(gè)服務(wù)名為"my-service",通過(guò)將其注冊(cè)到DNS中,可以將"my-service"解析為具體的服務(wù)實(shí)例的IP地址。

SLB是一種負(fù)載均衡器,用于將流量分發(fā)到多個(gè)后端服務(wù)實(shí)例上,從而實(shí)現(xiàn)負(fù)載均衡和高可用性。SLB可以接收客戶(hù)端請(qǐng)求,并根據(jù)負(fù)載均衡算法將請(qǐng)求分發(fā)到多個(gè)服務(wù)實(shí)例上。例如,當(dāng)有多個(gè)服務(wù)實(shí)例提供相同的服務(wù)時(shí),SLB可以根據(jù)負(fù)載情況,將請(qǐng)求分發(fā)到負(fù)載較低的實(shí)例上,以實(shí)現(xiàn)流量的均衡分布。

Nacos是一個(gè)用于服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)治理的開(kāi)源項(xiàng)目。在服務(wù)發(fā)現(xiàn)和負(fù)載均衡中,Nacos作為服務(wù)注冊(cè)中心和配置中心,可以用來(lái)管理各個(gè)服務(wù)實(shí)例的注冊(cè)和注銷(xiāo),以及維護(hù)服務(wù)實(shí)例的元數(shù)據(jù)信息。Nacos可以提供給SLB和DNS所需的服務(wù)實(shí)例信息,從而實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)和負(fù)載均衡的功能。

結(jié)合這三個(gè)組件,整體的架構(gòu)可以如下所示:

  1. 服務(wù)實(shí)例注冊(cè):服務(wù)實(shí)例可以將自己的元數(shù)據(jù)信息注冊(cè)到Nacos中,包括服務(wù)名稱(chēng)、IP地址、端口等信息。

  2. Nacos服務(wù)注冊(cè)中心:Nacos注冊(cè)中心負(fù)責(zé)存儲(chǔ)和管理所有服務(wù)實(shí)例的元數(shù)據(jù)信息。

  3. Nacos配置中心:Nacos配置中心負(fù)責(zé)存儲(chǔ)和管理應(yīng)用程序的配置信息。

  4. DNS解析:客戶(hù)端可以通過(guò)DNS解析服務(wù)名稱(chēng)為具體的服務(wù)實(shí)例的IP地址。

  5. SLB負(fù)載均衡器:SLB可以接收客戶(hù)端請(qǐng)求,并根據(jù)負(fù)載均衡算法將請(qǐng)求分發(fā)到多個(gè)服務(wù)實(shí)例上。

通過(guò)這樣的結(jié)構(gòu),客戶(hù)端可以通過(guò)DNS解析獲取到服務(wù)實(shí)例的IP地址,并通過(guò)SLB將請(qǐng)求發(fā)送到可用的服務(wù)實(shí)例上,實(shí)現(xiàn)負(fù)載均衡。同時(shí),Nacos作為服務(wù)注冊(cè)中心和配置中心,可以管理服務(wù)實(shí)例的注冊(cè)和配置信息,以確保服務(wù)的可用性和配置的一致性。這樣的架構(gòu)既提供了可靠的服務(wù)發(fā)現(xiàn)和負(fù)載均衡,也保證了配置的集中管理和動(dòng)態(tài)更新能力。

我們計(jì)劃的集群結(jié)構(gòu):

?三個(gè)nacos節(jié)點(diǎn)的地址:

| 節(jié)點(diǎn) ? | ip ? ? ? ? ? ?| port || nacos1 | 192.168.150.1 | 8845 || nacos2 | 192.168.150.1 | 8846 || nacos3 | 192.168.150.1 | 8847 |
7.2、集群搭建

搭建集群的基本步驟:

- 搭建數(shù)據(jù)庫(kù),初始化數(shù)據(jù)庫(kù)表結(jié)構(gòu)- 下載nacos安裝包- 配置nacos- 啟動(dòng)nacos集群- nginx反向代理

六、Feign遠(yuǎn)程調(diào)用

RestTemplate方法調(diào)用存在的問(wèn)題

先看一下我們以前利用RestTemplate發(fā)起遠(yuǎn)程調(diào)用的代碼:

存在下面的問(wèn)題:

  • 代碼可讀性差,編程體驗(yàn)不統(tǒng)一
  • 參數(shù)復(fù)雜URL難維護(hù)

1、Feign的介紹

Feign 提供了一種簡(jiǎn)單且優(yōu)雅的方式來(lái)定義和調(diào)用基于HTTP的遠(yuǎn)程服務(wù)。通過(guò)使用Feign,您可以在客戶(hù)端代碼中定義接口,然后Feign會(huì)根據(jù)這些接口的定義自動(dòng)生成實(shí)際的HTTP請(qǐng)求,并將其轉(zhuǎn)發(fā)到遠(yuǎn)程服務(wù)。這樣,您可以像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程服務(wù)的方法,無(wú)需顯式地處理HTTP請(qǐng)求和響應(yīng)。

Feign 還支持對(duì)請(qǐng)求進(jìn)行編碼和解碼、錯(cuò)誤處理、請(qǐng)求和響應(yīng)攔截器等功能,使得在微服務(wù)架構(gòu)中處理遠(yuǎn)程服務(wù)變得更加方便和高效。

使用Feign的一些優(yōu)點(diǎn)包括:

  1. 簡(jiǎn)化了客戶(hù)端代碼,使其更易于維護(hù)和理解。
  2. 減少了手動(dòng)處理HTTP請(qǐng)求和響應(yīng)的工作量。
  3. 支持多種編解碼器,可處理多種數(shù)據(jù)格式。
  4. 可與Spring Cloud等微服務(wù)框架無(wú)縫集成。

在使用Feign時(shí),您需要定義一個(gè)Java接口,該接口包含與遠(yuǎn)程服務(wù)相對(duì)應(yīng)的方法和參數(shù)。然后,通過(guò)在應(yīng)用程序的配置中啟用Feign并使用Spring的依賴(lài)注入功能,您可以將Feign客戶(hù)端注入到您的代碼中,從而實(shí)現(xiàn)對(duì)遠(yuǎn)程服務(wù)的調(diào)用。

Feign作為一個(gè)聲明式的HTTP客戶(hù)端,在微服務(wù)架構(gòu)和分布式系統(tǒng)中有許多應(yīng)用場(chǎng)景。以下是一些常見(jiàn)的使用場(chǎng)景:

  1. 微服務(wù)間的通信:在微服務(wù)架構(gòu)中,各個(gè)服務(wù)之間需要頻繁地進(jìn)行通信,Feign可以幫助簡(jiǎn)化服務(wù)間的HTTP通信,使得調(diào)用遠(yuǎn)程服務(wù)更加方便。

  2. 服務(wù)消費(fèi)者:當(dāng)一個(gè)服務(wù)需要調(diào)用其他服務(wù)提供的API時(shí),可以使用Feign來(lái)作為客戶(hù)端來(lái)消費(fèi)這些服務(wù),而無(wú)需手動(dòng)處理HTTP請(qǐng)求和響應(yīng)。

  3. 代理遠(yuǎn)程API:Feign可以將遠(yuǎn)程服務(wù)的API映射為本地接口,使得調(diào)用遠(yuǎn)程服務(wù)的過(guò)程就像調(diào)用本地方法一樣簡(jiǎn)單。

  4. 負(fù)載均衡:結(jié)合負(fù)載均衡的工具(如Ribbon),Feign可以實(shí)現(xiàn)在多個(gè)服務(wù)實(shí)例之間進(jìn)行負(fù)載均衡,從而提高系統(tǒng)的可用性和性能。

  5. 聲明式的錯(cuò)誤處理:Feign支持定義統(tǒng)一的錯(cuò)誤處理邏輯,使得在發(fā)生錯(cuò)誤時(shí)可以采取一致的處理方式,從而減少重復(fù)代碼。

  6. 數(shù)據(jù)格式處理:Feign支持多種編解碼器,可以處理不同的數(shù)據(jù)格式,例如JSON、XML等,使得數(shù)據(jù)的傳輸和解析更加靈活和便捷。

  7. 請(qǐng)求攔截與日志:Feign支持請(qǐng)求和響應(yīng)攔截器,可以在發(fā)送請(qǐng)求和接收響應(yīng)時(shí)進(jìn)行攔截和處理,例如記錄日志、鑒權(quán)等。

總體而言,Feign適用于任何需要在微服務(wù)架構(gòu)中進(jìn)行HTTP通信的場(chǎng)景,特別是當(dāng)您希望簡(jiǎn)化遠(yuǎn)程服務(wù)調(diào)用的代碼并增加可讀性和可維護(hù)性時(shí),Feign是一個(gè)非常有用的工具。

2、定義和使用Feign客戶(hù)端

在之前我是在調(diào)用其他服務(wù)提供的接口是使用的是RestTempale,為什么還要學(xué)Feign呢?

Feign和RestTemplate都是在Spring框架中用于進(jìn)行HTTP請(qǐng)求的工具,但它們?cè)谑褂梅绞胶吞攸c(diǎn)上有一些區(qū)別。

  1. 聲明式 vs. 編程式:

    • Feign是一個(gè)聲明式的HTTP客戶(hù)端,它允許您通過(guò)定義接口來(lái)描述對(duì)遠(yuǎn)程服務(wù)的請(qǐng)求,并自動(dòng)生成底層HTTP調(diào)用。Feign使用注解來(lái)配置請(qǐng)求的URL、HTTP方法、請(qǐng)求參數(shù)等信息,使得代碼更加簡(jiǎn)潔和易讀。
    • RestTemplate是一個(gè)編程式的HTTP客戶(hù)端,您需要在代碼中顯式地構(gòu)建HTTP請(qǐng)求,包括指定URL、HTTP方法、請(qǐng)求頭、請(qǐng)求體等信息。雖然可以通過(guò)RestTemplate靈活地控制請(qǐng)求細(xì)節(jié),但相比Feign,代碼可能會(huì)更冗長(zhǎng)和復(fù)雜。
  2. 整合Spring Cloud vs. 單獨(dú)使用:

    • Feign是Spring Cloud項(xiàng)目的一部分,它與Spring Cloud的其他組件(如Eureka、Ribbon、Hystrix等)緊密集成,使得在微服務(wù)架構(gòu)中使用Feign更加方便,并且提供了一些額外的特性,如負(fù)載均衡、服務(wù)發(fā)現(xiàn)等。
    • RestTemplate是Spring Framework的一部分,它可以單獨(dú)使用,沒(méi)有與Spring Cloud的深度集成。如果您在非微服務(wù)環(huán)境中,或者不需要Spring Cloud提供的其他功能,RestTemplate是一個(gè)不錯(cuò)的選擇。
  3. 自動(dòng)化的負(fù)載均衡:

    • Feign與Ribbon(Spring Cloud中的負(fù)載均衡組件)集成,可以自動(dòng)進(jìn)行負(fù)載均衡,使得在多個(gè)服務(wù)實(shí)例中選擇合適的目標(biāo)服務(wù)。
    • RestTemplate在默認(rèn)情況下不支持自動(dòng)的負(fù)載均衡,您需要手動(dòng)編寫(xiě)代碼來(lái)實(shí)現(xiàn)負(fù)載均衡,或者結(jié)合Ribbon來(lái)實(shí)現(xiàn)自動(dòng)化負(fù)載均衡。
  4. 請(qǐng)求攔截器和錯(cuò)誤處理:

    • Feign允許您定義請(qǐng)求和響應(yīng)攔截器,從而可以在發(fā)送請(qǐng)求和接收響應(yīng)時(shí)進(jìn)行攔截和處理,例如記錄日志、鑒權(quán)等。它還提供了聲明式的錯(cuò)誤處理機(jī)制,讓您可以統(tǒng)一處理請(qǐng)求錯(cuò)誤。
    • RestTemplate也支持請(qǐng)求和響應(yīng)攔截器,但是在處理錯(cuò)誤時(shí)可能相對(duì)繁瑣,需要通過(guò)捕獲異常等方式來(lái)處理請(qǐng)求錯(cuò)誤。

綜上所述,如果您在使用Spring Cloud和微服務(wù)架構(gòu),特別是在Feign與Ribbon、Eureka等組件進(jìn)行集成時(shí),Feign可能是更好的選擇,因?yàn)樗峁┝艘环N簡(jiǎn)單且聲明式的方式來(lái)定義和調(diào)用遠(yuǎn)程服務(wù)。然而,如果您在非微服務(wù)環(huán)境或不需要Spring Cloud提供的其他功能,RestTemplate仍然是一個(gè)可行的選擇,尤其是當(dāng)您需要更多的靈活性和對(duì)HTTP請(qǐng)求的直接控制時(shí)。

2.1、Feign實(shí)戰(zhàn)

定義和使用Feign客戶(hù)端需要以下步驟:

1、添加依賴(lài):首先,您需要在項(xiàng)目中添加Feign的依賴(lài)。如果您是使用Spring Boot項(xiàng)目,可以在pom.xml中添加以下依賴(lài):

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、啟用Feign客戶(hù)端:為了使Feign客戶(hù)端生效,您需要在Spring Boot應(yīng)用程序的主類(lèi)上添加@EnableFeignClients注解,這將啟用Feign客戶(hù)端的自動(dòng)配置和發(fā)現(xiàn)。

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}}

3、創(chuàng)建Feign客戶(hù)端接口:接下來(lái),您需要定義一個(gè)Java接口,該接口將包含與遠(yuǎn)程服務(wù)相對(duì)應(yīng)的方法和參數(shù)。這些方法的定義類(lèi)似于普通的Spring組件接口,但是您可以使用Spring的注解來(lái)定義遠(yuǎn)程服務(wù)的URL、HTTP方法和其他相關(guān)信息。

package cn.itcast.order.clients;import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient("userservice")  //使用@FeignClient來(lái)指導(dǎo)這個(gè)接口所有接口方法要訪問(wèn)的服務(wù)名稱(chēng)
public interface UserClient {//定義調(diào)用接口@GetMapping("/user/{id}")  User findUserById(@PathVariable("id") Long id);
}

?4、使用Feign客戶(hù)端:現(xiàn)在您可以在其他組件或服務(wù)中注入Feign客戶(hù)端,并使用它來(lái)調(diào)用遠(yuǎn)程服務(wù)的方法。

package cn.itcast.order.service;import cn.itcast.order.clients.UserClient;
import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate UserClient userClient;   //注入U(xiǎn)ser的Feign客戶(hù)端public Order queryOrderById(Long id){Order order = orderMapper.findById(id);Long userId = order.getUserId();//使用Feign遠(yuǎn)程調(diào)用User user = userClient.findUserById(userId);order.setUser(user);return order;}
}
總結(jié)

Feign的使用步驟

  1. 引入依賴(lài)
  2. 添加@EnableFeignClients注解
  3. 編寫(xiě)FeignClient接口
  4. 使用FeignClient中定義的方法代替RestTemplate

3、自定義Feign的配置

Feign運(yùn)行自定義配置來(lái)覆蓋默認(rèn)配置,可以修改的配置如下:

?一般我們需要配置的就是日志級(jí)別。

日志級(jí)別

Feign支持四種不同的日志級(jí)別,您可以根據(jù)需要選擇適合的日志級(jí)別。這些日志級(jí)別用于控制Feign在發(fā)送請(qǐng)求和接收響應(yīng)時(shí)記錄的日志信息的詳細(xì)程度。

  1. NONE:該日志級(jí)別最低,不記錄任何日志信息。如果您不想在控制臺(tái)輸出任何關(guān)于Feign請(qǐng)求和響應(yīng)的日志,可以選擇此級(jí)別。

  2. BASIC:在BASIC級(jí)別下,Feign僅記錄請(qǐng)求方法、URL和響應(yīng)狀態(tài)碼的基本信息。這對(duì)于快速了解請(qǐng)求的基本情況很有幫助,但不會(huì)記錄請(qǐng)求和響應(yīng)的詳細(xì)內(nèi)容。

  3. HEADERS:在HEADERS級(jí)別下,Feign將記錄請(qǐng)求和響應(yīng)的頭部信息,包括請(qǐng)求頭和響應(yīng)頭。這樣可以更詳細(xì)地查看請(qǐng)求和響應(yīng)的頭部信息,有助于調(diào)試和了解請(qǐng)求的上下文。

  4. FULL:FULL級(jí)別是最詳細(xì)的日志級(jí)別,它會(huì)記錄請(qǐng)求和響應(yīng)的所有詳細(xì)信息,包括請(qǐng)求頭、請(qǐng)求體、響應(yīng)頭和響應(yīng)體。如果您需要完整的請(qǐng)求和響應(yīng)信息來(lái)進(jìn)行詳細(xì)的調(diào)試和排查問(wèn)題,FULL級(jí)別是最合適的選擇。

3.1自定義Feign的配置方式
方式一:配置文件方式

當(dāng)使用配置文件的方式來(lái)配置Feign的自定義配置時(shí),您可以借助Spring Boot的屬性配置功能來(lái)實(shí)現(xiàn)。通過(guò)在配置文件(如application.properties或application.yml)中添加特定的屬性,您可以自定義Feign的行為。

首先,您需要在配置文件中添加Feign的相關(guān)屬性。以YAML格式的配置文件為例,假設(shè)您想要配置Feign的日志級(jí)別為FULL,可以這樣寫(xiě):

1、全局生效
# application.yml
feign:client:config:default: #這里用default就是全局配置,如果是寫(xiě)服務(wù)器名稱(chēng),則是針對(duì)在某個(gè)微服務(wù)的配置loggerLevel: full  #日志級(jí)別
2、局部生效
# application.yml
feign:client:config:orderservice:    #這里用服務(wù)名稱(chēng),則只針對(duì)這個(gè)服務(wù)的配置loggerLevel: full   #日志級(jí)別
方式二:java代碼方式,需要先聲明一個(gè)Bean:

在使用Feign時(shí),您可以通過(guò)自定義配置來(lái)修改其行為和屬性。為了自定義Feign的配置,您需要?jiǎng)?chuàng)建一個(gè)配置類(lèi),并在其中添加相關(guān)的Bean定義。下面是一個(gè)簡(jiǎn)單的示例來(lái)說(shuō)明如何自定義Feign的配置:

package cn.itcast.order.config;import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FeignConfig {@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.BASIC;}
}
全局配置:

如果是全局配置,則把它放到@EnableFeignClients這個(gè)注解中:

@EnableFeignClients(defaultConfiguration = FeignConfig.class)
局部配置:

如果是局部配置,則把它放到@FeignClient這個(gè)注解中:

@FeignClient(value = "userservice",configuration = FeignConfig.class)  
總結(jié)

Feign的日志配置
1.方式一是配置文件,feign.client.config.xxx.loggerLevel

  1. O如果xxx是default則代表全局
  2. 如果xxx是服務(wù)名稱(chēng),例如userservice則代表某服務(wù)

2.方式二是java代碼配置Logger.Level這個(gè)Bean

  1. 如果在@EnableFeignClients注解聲明則代表全局
  2. 如果在@FeignClient注解中聲明則代表某服務(wù)

4、Feign的性能優(yōu)化

Feign的底層客戶(hù)端實(shí)現(xiàn)是通過(guò)集成了其他HTTP客戶(hù)端庫(kù)來(lái)實(shí)現(xiàn)的。具體來(lái)說(shuō),Feign支持兩種主要的HTTP客戶(hù)端實(shí)現(xiàn):JDK的URLConnection和Apache HttpClient。

  1. JDK的URLConnection:這是Java標(biāo)準(zhǔn)庫(kù)中提供的用于HTTP通信的API。Feign可以直接使用JDK的URLConnection來(lái)發(fā)送HTTP請(qǐng)求。它是輕量級(jí)的,對(duì)于簡(jiǎn)單的HTTP通信,可能足夠滿(mǎn)足需求。如果您在項(xiàng)目中沒(méi)有引入其他HTTP客戶(hù)端庫(kù),Feign會(huì)默認(rèn)使用JDK的URLConnection作為底層的客戶(hù)端實(shí)現(xiàn)。

  2. Apache HttpClient:Apache HttpClient是Apache基金會(huì)提供的一個(gè)功能豐富、靈活的HTTP客戶(hù)端庫(kù)。它提供了許多高級(jí)功能,如連接池、重試機(jī)制、認(rèn)證等。如果您在項(xiàng)目中引入了Apache HttpClient的依賴(lài),Feign會(huì)自動(dòng)選擇使用Apache HttpClient作為底層的客戶(hù)端實(shí)現(xiàn)。

  3. OkHttp:OkHttp是Square公司開(kāi)發(fā)的一款高效的HTTP客戶(hù)端庫(kù)。它支持HTTP/2、連接池、攔截器等現(xiàn)代特性。如果您在項(xiàng)目中引入了OkHttp的依賴(lài),Feign會(huì)自動(dòng)切換到OkHttp作為底層實(shí)現(xiàn)。

Feign的這種設(shè)計(jì)使得您可以根據(jù)需要靈活地選擇底層的HTTP客戶(hù)端。默認(rèn)情況下,如果項(xiàng)目中沒(méi)有引入其他HTTP客戶(hù)端庫(kù),Feign將使用JDK的URLConnection作為底層客戶(hù)端。如果您希望使用Apache HttpClient或OkHttp,只需在項(xiàng)目中添加相應(yīng)的依賴(lài),Feign會(huì)自動(dòng)檢測(cè)并使用它們作為底層實(shí)現(xiàn)。

通過(guò)這種方式,Feign可以同時(shí)滿(mǎn)足不同項(xiàng)目對(duì)HTTP客戶(hù)端的需求,并提供簡(jiǎn)便的遠(yuǎn)程服務(wù)調(diào)用方式。

因此優(yōu)化Feign的性能主要包括:
  1. 使用連接池代替默認(rèn)的URLConnection
  2. 日志級(jí)別,做好使用basic或者none
4.1、 Feign性能優(yōu)化HttpClient的支持:
1、Feign添加HttpClient的支持:

引入依賴(lài):

        <dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId></dependency>

配置連接池:

#feign自定義配置,配置日志級(jí)別
feign:client:config:default:  #這里用default就是全局配置,如果是寫(xiě)服務(wù)器名稱(chēng),則是針對(duì)在某個(gè)微服務(wù)的配置loggerLevel: basic  #日志級(jí)別httpclient:enabled: true   #開(kāi)啟feign對(duì)HttpClient的支持max-connections: 200   #最大連接數(shù)量max-connections-per-route: 50   #每個(gè)路徑的最大連接數(shù)量
總結(jié)

Feign的優(yōu)化
1.日志級(jí)別盡量用basic
2.使用HttpClient或OKHttp代替URLConnection

  1. 引入feign-httpClient依賴(lài)
  2. 配置文件開(kāi)啟httpClient功能,設(shè)置連接池參數(shù)

5、Feign的最佳實(shí)際

方式一(繼承):給消費(fèi)者的FeignClient和提供者的controller系統(tǒng)定義一個(gè)父接口作為標(biāo)準(zhǔn)。

這種實(shí)現(xiàn)方式雖然可以讓Controller和Feign Client共享同一個(gè)接口定義,但存在一些問(wèn)題和注意事項(xiàng):

  1. 潛在的耦合:共享同一個(gè)接口定義會(huì)讓Controller和Feign Client在代碼層面產(chǎn)生耦合,導(dǎo)致它們緊密地關(guān)聯(lián)在一起。一旦接口定義發(fā)生變化,兩者都需要進(jìn)行相應(yīng)的修改,這可能影響到多個(gè)模塊。

  2. 不符合單一職責(zé)原則:Controller負(fù)責(zé)處理HTTP請(qǐng)求和返回響應(yīng),而Feign Client負(fù)責(zé)遠(yuǎn)程服務(wù)調(diào)用。將它們共享同一個(gè)接口可能會(huì)讓代碼功能變得混亂,違反了單一職責(zé)原則。

  3. 難以做到完全解耦:盡管接口定義可以共享,但是在Feign Client的實(shí)現(xiàn)中,仍然需要涉及到遠(yuǎn)程服務(wù)調(diào)用的邏輯。這會(huì)讓Feign Client的實(shí)現(xiàn)和Controller之間仍然有一定的耦合。

  4. 接口定義可能會(huì)變得復(fù)雜:為了適應(yīng)不同的調(diào)用場(chǎng)景,共享接口可能會(huì)變得復(fù)雜,可能需要添加各種參數(shù)和注解,從而導(dǎo)致接口的冗長(zhǎng)和不易維護(hù)。

  5. 功能不一致問(wèn)題:在Controller和Feign Client共享同一個(gè)接口的情況下,兩者的功能可能不完全一致。在Controller中可能需要做一些本地邏輯處理,而在Feign Client中可能需要進(jìn)行額外的遠(yuǎn)程服務(wù)調(diào)用。

綜上所述,雖然共享接口可以在一定程度上減少重復(fù)代碼,但也會(huì)引入潛在的問(wèn)題和復(fù)雜性。在實(shí)際開(kāi)發(fā)中,更常見(jiàn)的做法是將Controller和Feign Client分別定義獨(dú)立的接口,通過(guò)接口定義來(lái)規(guī)范各自的功能和職責(zé)。在需要共享方法定義的情況下,可以使用Java接口繼承來(lái)實(shí)現(xiàn)方法的復(fù)用,而避免在Feign Client中直接實(shí)現(xiàn)Controller的方法。這樣可以更好地保持代碼的清晰和可維護(hù)性,并符合單一職責(zé)原則。

方式二(抽取):將FeignClient抽取為獨(dú)立模塊,并且把接口有關(guān)的POJO、默認(rèn)的Feign配置都放到這個(gè)模塊中,提供給所有消費(fèi)者使用

以前實(shí)現(xiàn)?

假如:我們有order-service、pay-service和user-service兩個(gè)服務(wù),現(xiàn)在order-service和pay-service都要去調(diào)用user-service提供的接口,我們就得order-service和pay-service服務(wù)里都要實(shí)現(xiàn)UserClient,假如我們不止只有這兩個(gè)服務(wù)調(diào)用user-service呢,有10個(gè)、20個(gè)服務(wù)都要調(diào)用,那UserClient就得寫(xiě)10遍、20遍,就會(huì)重復(fù)的開(kāi)發(fā)代碼了。

現(xiàn)在

我們獨(dú)立創(chuàng)建一個(gè)項(xiàng)目,將哪些重復(fù)的代碼編寫(xiě)的東西全部放到這個(gè)項(xiàng)目/模塊中(如UserClient、User實(shí)體類(lèi)、DefaultConfig等),我們可以把這個(gè)項(xiàng)目的內(nèi)容打成jar包,假如以后服務(wù)需要的時(shí)候直接引用依賴(lài)就可以

?總結(jié)

Feign的最佳實(shí)踐

  1. 讓controller和FeignClient繼承同一接口
  2. 將FeignClient、poJo、Feign的默認(rèn)配置都定義到一個(gè)項(xiàng)目中,供所有消費(fèi)者使用
?抽取FeignClient
實(shí)現(xiàn)最佳實(shí)踐方式二的步驟如下:
1、創(chuàng)建一個(gè)module,命名為feign-api,然后引入feign的starter依賴(lài)

引入feign的starter依賴(lài):

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
2、將order-service中編寫(xiě)的UserClient、User、DefaultFeignConfiguration都復(fù)制到feign-api項(xiàng)目中

?之前在order-service服務(wù)模塊中餓這些東西就可以刪除了。

?3、在order-service中引入feign-api的依賴(lài)
        <!--引入feign的同一api--><dependency><groupId>cn.itcast.demo</groupId><artifactId>feign-api</artifactId><version>1.0</version></dependency>

這個(gè)依賴(lài)是我們項(xiàng)目中的feign-api模塊里的內(nèi)容。

4、修改order-service中的所有與上述三個(gè)組件有關(guān)的import部分,改成導(dǎo)入feign-api中的包

5、重啟測(cè)試
當(dāng)定義的FeignClient不在springApplication的包掃描范圍時(shí),這些FeignClient無(wú)法使用問(wèn)題

重啟order-service服務(wù)后我們會(huì)發(fā)現(xiàn)報(bào)錯(cuò)了

Field userClient in cn.itcast.order.service.OrderService required a bean of type 'cn.itcast.feign.clients.UserClient' that could not be found.該錯(cuò)誤信息表明在OrderService類(lèi)中的userClient字段的類(lèi)型為cn.itcast.feign.clients.UserClient,但是Spring容器中找不到該類(lèi)型的Bean。

說(shuō)明我們?cè)谧詣?dòng)裝配UserClient時(shí)是找不到這個(gè)對(duì)象的實(shí)例的,原因是我們現(xiàn)在在order-service模塊中使用的UserClient是通過(guò)添加了feign-api依賴(lài)而導(dǎo)進(jìn)來(lái)的,在order-service模塊啟動(dòng)時(shí)spring只會(huì)對(duì)啟動(dòng)類(lèi)所在目錄及這個(gè)目錄里所有類(lèi)進(jìn)行掃描注冊(cè)到spring容器中的,而UserClient所在的包就沒(méi)有被掃描到,所在在order-service這個(gè)模塊中的spring容器中就找不到了對(duì)于的對(duì)象實(shí)例了。

解決辦法方式一:指定FeignClient所在包
@EnableFeignClients(basePackages = "cn.itcast.feign.clients")
解決辦法方式二:指定FeignClient字節(jié)碼
@EnableFeignClients(clients = {UserClient.class})
總結(jié)

不同包的FeignClient的導(dǎo)入有兩種方式

  1. 在@EnableFeignClients注解中添加basePackages,指定FeignClient所在的包
  2. 在@EnableFeignClients注解中添加clients,指定具體FeignClient的字節(jié)碼

七、Gateway服務(wù)網(wǎng)關(guān)

網(wǎng)關(guān)(Gateway)服務(wù)在微服務(wù)架構(gòu)中起著重要的作用。它是位于客戶(hù)端和后端微服務(wù)之間的中間層,用于處理和轉(zhuǎn)發(fā)請(qǐng)求。為什么要使用網(wǎng)關(guān)服務(wù)呢?以下是一些主要的原因:

  1. 統(tǒng)一入口:網(wǎng)關(guān)服務(wù)提供了一個(gè)統(tǒng)一的入口,客戶(hù)端只需要向網(wǎng)關(guān)發(fā)送請(qǐng)求,而不需要直接調(diào)用各個(gè)微服務(wù)。這樣簡(jiǎn)化了客戶(hù)端的調(diào)用邏輯,同時(shí)也方便地對(duì)請(qǐng)求進(jìn)行統(tǒng)一管理和處理。

  2. 路由和負(fù)載均衡:網(wǎng)關(guān)服務(wù)可以根據(jù)請(qǐng)求的URL路徑或其他條件將請(qǐng)求路由到相應(yīng)的微服務(wù)實(shí)例。它還可以配合負(fù)載均衡算法,確保請(qǐng)求被均勻地分發(fā)給不同的服務(wù)實(shí)例,提高了系統(tǒng)的可用性和性能。

  3. 安全控制:通過(guò)網(wǎng)關(guān)服務(wù),可以實(shí)現(xiàn)對(duì)請(qǐng)求進(jìn)行安全控制和認(rèn)證。網(wǎng)關(guān)可以驗(yàn)證請(qǐng)求的身份、權(quán)限以及合法性,確保只有授權(quán)的請(qǐng)求能夠訪問(wèn)相應(yīng)的微服務(wù)。

  4. 聚合和分解請(qǐng)求:網(wǎng)關(guān)服務(wù)可以聚合多個(gè)微服務(wù)的請(qǐng)求,將它們合并為一個(gè)請(qǐng)求返回給客戶(hù)端,從而減少了客戶(hù)端與后端服務(wù)之間的請(qǐng)求次數(shù),降低了網(wǎng)絡(luò)開(kāi)銷(xiāo)。

  5. 緩存:網(wǎng)關(guān)服務(wù)可以對(duì)請(qǐng)求的響應(yīng)進(jìn)行緩存,從而減少重復(fù)請(qǐng)求對(duì)后端服務(wù)的壓力,提高了系統(tǒng)的性能和響應(yīng)速度。

  6. 降級(jí)和容錯(cuò):網(wǎng)關(guān)服務(wù)可以實(shí)現(xiàn)對(duì)后端服務(wù)的降級(jí)和容錯(cuò)處理。當(dāng)某個(gè)微服務(wù)出現(xiàn)故障或不可用時(shí),網(wǎng)關(guān)可以提供默認(rèn)的響應(yīng)或調(diào)用備用服務(wù),避免了系統(tǒng)級(jí)的故障。

  7. 監(jiān)控和日志:通過(guò)網(wǎng)關(guān)服務(wù),可以實(shí)現(xiàn)對(duì)請(qǐng)求和響應(yīng)進(jìn)行監(jiān)控和日志記錄。這有助于實(shí)時(shí)追蹤請(qǐng)求的流程和性能,發(fā)現(xiàn)問(wèn)題并進(jìn)行及時(shí)的處理。

綜上所述,網(wǎng)關(guān)服務(wù)在微服務(wù)架構(gòu)中扮演了一個(gè)重要的角色,它提供了統(tǒng)一入口、路由和負(fù)載均衡、安全控制、聚合和分解請(qǐng)求、緩存、降級(jí)和容錯(cuò)、監(jiān)控和日志等功能,為整個(gè)系統(tǒng)提供了更高效、更安全、更穩(wěn)定的請(qǐng)求處理和管理能力。

1、網(wǎng)關(guān)技術(shù)

?在springcloud中網(wǎng)關(guān)的實(shí)現(xiàn)有兩種:gateway和zuul

Zuul和Spring Cloud Gateway都是常用的網(wǎng)關(guān)實(shí)現(xiàn),用于在微服務(wù)架構(gòu)中處理和轉(zhuǎn)發(fā)請(qǐng)求。它們都可以作為反向代理和請(qǐng)求路由器,但在設(shè)計(jì)和功能上有一些區(qū)別。

  1. Zuul:

    Zuul是Netflix提供的網(wǎng)關(guān)服務(wù),被稱(chēng)為Netflix Zuul。它是一個(gè)基于Servlet的網(wǎng)關(guān)實(shí)現(xiàn),構(gòu)建在傳統(tǒng)的Spring Cloud項(xiàng)目上。Zuul 1.x版本采用阻塞式I/O模型,Zuul 2.x版本采用非阻塞式I/O模型,基于Netty。

    特點(diǎn):

    • Zuul 1.x的阻塞式I/O模型限制了并發(fā)性能,雖然可以通過(guò)多實(shí)例部署來(lái)提高吞吐量,但對(duì)于高并發(fā)場(chǎng)景可能不夠高效。
    • Zuul 2.x基于非阻塞式I/O模型,可以提供更好的性能和吞吐量。
    • Zuul支持動(dòng)態(tài)路由和過(guò)濾器等功能,可以實(shí)現(xiàn)請(qǐng)求的動(dòng)態(tài)轉(zhuǎn)發(fā)和預(yù)處理。
    • 配置方式較為靈活,可以使用Groovy或Java DSL配置路由和過(guò)濾器。
  2. Spring Cloud Gateway:

    Spring Cloud Gateway是Spring Cloud項(xiàng)目中的網(wǎng)關(guān)服務(wù),從Spring Cloud 2.x版本開(kāi)始引入。它是基于Spring 5和Spring Boot 2構(gòu)建的,采用了WebFlux框架,支持響應(yīng)式編程。

    特點(diǎn):

    • Spring Cloud Gateway采用基于異步非阻塞的WebFlux框架,提供了更好的性能和響應(yīng)能力,適用于高并發(fā)場(chǎng)景。
    • 支持動(dòng)態(tài)路由和過(guò)濾器等功能,可以實(shí)現(xiàn)請(qǐng)求的動(dòng)態(tài)轉(zhuǎn)發(fā)和預(yù)處理。
    • 提供了豐富的過(guò)濾器,支持全局和局部過(guò)濾器的定義和使用。
    • 配置方式靈活,可以使用YAML或Java配置路由和過(guò)濾器。

綜合來(lái)說(shuō),Zuul和Spring Cloud Gateway都是成熟的網(wǎng)關(guān)實(shí)現(xiàn),各有優(yōu)勢(shì)。如果您在使用Spring Cloud項(xiàng)目,推薦使用Spring Cloud Gateway,特別是在需要高并發(fā)和響應(yīng)能力的場(chǎng)景下。而如果您在使用Netflix項(xiàng)目,可以選擇使用Netflix Zuul 2.x版本或更高的版本,或考慮遷移到Spring Cloud Gateway。選擇哪個(gè)網(wǎng)關(guān)取決于您的項(xiàng)目需求、技術(shù)棧和預(yù)期的性能要求。

總結(jié)

網(wǎng)關(guān)的作用:

  • 對(duì)用戶(hù)請(qǐng)求做身份認(rèn)證、權(quán)限校驗(yàn)
  • 將用戶(hù)請(qǐng)求路由到微服務(wù),并實(shí)現(xiàn)負(fù)載均衡
  • 對(duì)用戶(hù)請(qǐng)求做限流

2、搭建網(wǎng)關(guān)服務(wù)

2.1、搭建網(wǎng)關(guān)服務(wù)的步驟:
  1. 創(chuàng)建Gateway項(xiàng)目:首先,創(chuàng)建一個(gè)新的Spring Boot項(xiàng)目作為Gateway服務(wù)網(wǎng)關(guān)。

  2. 添加依賴(lài):在Gateway項(xiàng)目中,添加Spring Cloud Gateway和Nacos的依賴(lài),以便使用Gateway和Nacos的功能。在pom.xml文件中添加以下依賴(lài):

<dependencies><!-- Spring Cloud Gateway --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- Spring Cloud Nacos 作為服務(wù)注冊(cè)和發(fā)現(xiàn)中心 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- 其他依賴(lài) -->
</dependencies>

3、配置網(wǎng)關(guān)路由:在application.yml中配置網(wǎng)關(guān)的路由規(guī)則,將請(qǐng)求路由到對(duì)應(yīng)的微服務(wù)。例如:

server:port: 10009  # 配置服務(wù)端口spring:application:name: gateway  # 服務(wù)名稱(chēng)cloud:nacos:server-addr: localhost:8848  # 配置Nacos注冊(cè)中心的地址和端口gateway:routes:- id: userservice_route   # 路由規(guī)則的唯一標(biāo)識(shí),用于識(shí)別該路由規(guī)則。自定義的標(biāo)識(shí)可以方便管理和維護(hù)。uri: lb://userservice   # 指定目標(biāo)微服務(wù)的服務(wù)名。lb://前綴表示使用負(fù)載均衡器來(lái)選擇目標(biāo)微服務(wù)的實(shí)例。這里目標(biāo)微服務(wù)的服務(wù)名是userservice。predicates:    # 斷言條件列表,用于匹配請(qǐng)求是否符合該路由規(guī)則。- Path=/user/**      # 匹配的URL路徑,當(dāng)請(qǐng)求的URL路徑以/user/開(kāi)頭時(shí),該路由規(guī)則會(huì)匹配。**表示匹配任意后續(xù)路徑。- id: orderservice_route   # 另一個(gè)路由規(guī)則的唯一標(biāo)識(shí),用于識(shí)別該路由規(guī)則。uri: lb://orderservice  # 指定目標(biāo)微服務(wù)的服務(wù)名。這里目標(biāo)微服務(wù)的服務(wù)名是orderservice。predicates:             # 斷言條件列表,用于匹配請(qǐng)求是否符合該路由規(guī)則。- Path=/order/**      # 匹配的URL路徑,當(dāng)請(qǐng)求的URL路徑以/order/開(kāi)頭時(shí),該路由規(guī)則會(huì)匹配。**表示匹配任意后續(xù)路徑。

4、啟動(dòng)nacos服務(wù)

#Windows系統(tǒng)命令
startup.cmd -m standalone#Linux系統(tǒng)命令
sh startup.sh -m standalone

就可以直接使用gateway的ip+端口來(lái)訪問(wèn)數(shù)據(jù)了,可以直接讓gateway來(lái)將這些訪問(wèn)地址轉(zhuǎn)發(fā)到相應(yīng)的服務(wù)實(shí)例上,從而來(lái)訪問(wèn)數(shù)據(jù)(如訪問(wèn)地址:localhost:10009/order/101)

2.2、搭建網(wǎng)關(guān)服務(wù)流程圖

  1. 客戶(hù)端發(fā)起請(qǐng)求:客戶(hù)端(如Web應(yīng)用、移動(dòng)端應(yīng)用、或其他服務(wù))發(fā)起HTTP請(qǐng)求。

  2. 請(qǐng)求到達(dá)Gateway:請(qǐng)求首先到達(dá)Gateway服務(wù)網(wǎng)關(guān)。

  3. Gateway進(jìn)行路由匹配:Gateway根據(jù)預(yù)先配置的路由規(guī)則,匹配請(qǐng)求的URL路徑、請(qǐng)求頭等信息,找到對(duì)應(yīng)的微服務(wù)實(shí)例。

  4. 服務(wù)發(fā)現(xiàn):Gateway需要通過(guò)服務(wù)注冊(cè)中心(如Nacos)來(lái)獲取微服務(wù)實(shí)例的信息。它向Nacos發(fā)送服務(wù)發(fā)現(xiàn)請(qǐng)求,Nacos會(huì)返回目標(biāo)微服務(wù)的實(shí)例列表。

  5. 負(fù)載均衡:Gateway使用負(fù)載均衡算法從目標(biāo)微服務(wù)實(shí)例列表中選擇一個(gè)實(shí)例,將請(qǐng)求轉(zhuǎn)發(fā)給該微服務(wù)實(shí)例。

  6. 微服務(wù)接收請(qǐng)求:目標(biāo)微服務(wù)實(shí)例接收到請(qǐng)求。

  7. 微服務(wù)處理請(qǐng)求:微服務(wù)實(shí)例處理請(qǐng)求,并根據(jù)業(yè)務(wù)邏輯執(zhí)行相應(yīng)的操作。

  8. 微服務(wù)返回響應(yīng):微服務(wù)實(shí)例生成響應(yīng)結(jié)果,并將響應(yīng)返回給Gateway。

  9. Gateway接收響應(yīng):Gateway接收到微服務(wù)實(shí)例的響應(yīng)。

  10. Gateway處理響應(yīng):Gateway可以對(duì)微服務(wù)實(shí)例的響應(yīng)進(jìn)行處理,如添加響應(yīng)頭、日志記錄等。

  11. 響應(yīng)返回客戶(hù)端:Gateway將處理后的響應(yīng)返回給客戶(hù)端。

通過(guò)服務(wù)注冊(cè)中心(如Nacos)來(lái)進(jìn)行服務(wù)發(fā)現(xiàn),Gateway能夠動(dòng)態(tài)地獲取微服務(wù)的實(shí)例信息,從而實(shí)現(xiàn)請(qǐng)求的動(dòng)態(tài)轉(zhuǎn)發(fā)和負(fù)載均衡。這樣,Gateway就能找到相應(yīng)的服務(wù)并將請(qǐng)求轉(zhuǎn)發(fā)給它們。感謝您的指正,希望這次的回答更加準(zhǔn)確。

總結(jié)
網(wǎng)關(guān)搭建步驟
  1. 創(chuàng)建項(xiàng)目,引入nacos服務(wù)發(fā)現(xiàn)和gateway依賴(lài)

  2. 配置application.yml,包括服務(wù)基本信息、nacos地址、路由

路由配置包括
  1. 路由id:路由的唯一標(biāo)示
  2. 路由目標(biāo) (uri):路由的目標(biāo)地址,http代表固定地址,lb代表根據(jù)服務(wù)名負(fù)載均衡
  3. 路由斷言 (predicates): 判斷路由的規(guī)則
  4. 路由過(guò)濾器 (filters):對(duì)請(qǐng)求或響應(yīng)做處理

3、路由斷言工廠Route Predicate Factory

  • 路由斷言工廠(Route Predicate Factory)是Spring Cloud Gateway中的一種配置方式,用于根據(jù)請(qǐng)求的條件來(lái)進(jìn)行路由匹配。它可以根據(jù)請(qǐng)求的不同屬性(例如URL路徑、請(qǐng)求頭、請(qǐng)求方法等)來(lái)判斷請(qǐng)求是否匹配某個(gè)路由規(guī)則,如果匹配成功,則將請(qǐng)求轉(zhuǎn)發(fā)到相應(yīng)的目標(biāo)地址(服務(wù)實(shí)例)。
  • 例如:Path=/order/**是按照路徑匹配,這個(gè)規(guī)則是由org.springframework.cloud.gateway.handler.predicata.PathRoutePredicateFactory類(lèi)來(lái)處理
  • 像這種短語(yǔ)工廠在SpringCloudGateway還有十幾個(gè)
3.1、spring提供了11種基本的Predicate工廠

?當(dāng)使用其他的Predicate工廠時(shí),可到spring官網(wǎng)上看如何使用:spring route

?總結(jié)
  • PredicateFactory的作用是什么?

????????讀取用戶(hù)定義的斷言條件,對(duì)請(qǐng)求做出判斷

  • Path=/user/**是什么含義?

????????路徑是以/user開(kāi)頭的就認(rèn)為是符合的

4、路由過(guò)濾器(Route Filter)

路由過(guò)濾器(Route Filter)是Spring Cloud Gateway中的另一個(gè)重要組件,它用于在請(qǐng)求被路由到目標(biāo)服務(wù)之前或之后,對(duì)請(qǐng)求或響應(yīng)進(jìn)行一系列的處理操作。通過(guò)路由過(guò)濾器,您可以對(duì)請(qǐng)求和響應(yīng)進(jìn)行修改、增強(qiáng)或驗(yàn)證,從而實(shí)現(xiàn)更加靈活和強(qiáng)大的網(wǎng)關(guān)功能。

?例如:

假設(shè)我們有一個(gè)微服務(wù)架構(gòu),包含多個(gè)服務(wù),其中一個(gè)是認(rèn)證服務(wù)(Authentication Service),負(fù)責(zé)處理用戶(hù)的身份認(rèn)證。其他服務(wù)(如用戶(hù)服務(wù)、訂單服務(wù)等)需要保護(hù)某些資源,只允許經(jīng)過(guò)認(rèn)證的用戶(hù)訪問(wèn)。

在這種情況下,我們可以使用Spring Cloud Gateway作為網(wǎng)關(guān),通過(guò)路由過(guò)濾器來(lái)實(shí)現(xiàn)請(qǐng)求認(rèn)證和授權(quán):

  1. 全局過(guò)濾器(Global Filter):我們可以創(chuàng)建一個(gè)全局過(guò)濾器來(lái)攔截所有的請(qǐng)求,在這個(gè)過(guò)濾器中進(jìn)行用戶(hù)身份認(rèn)證的檢查。比如,我們可以檢查請(qǐng)求中是否包含有效的身份令牌(Token),以確定請(qǐng)求是否是經(jīng)過(guò)認(rèn)證的用戶(hù)發(fā)起的。

  2. 局部過(guò)濾器(Route-Specific Filter):對(duì)于特定需要授權(quán)訪問(wèn)的服務(wù),我們可以在路由配置中使用局部過(guò)濾器。在這個(gè)過(guò)濾器中,我們可以對(duì)請(qǐng)求進(jìn)行權(quán)限驗(yàn)證,檢查用戶(hù)是否有權(quán)限訪問(wèn)該服務(wù)提供的資源。如果用戶(hù)沒(méi)有合法的權(quán)限,則可以拒絕請(qǐng)求或返回相應(yīng)的錯(cuò)誤信息。

這樣,通過(guò)路由過(guò)濾器,我們可以實(shí)現(xiàn)全局的請(qǐng)求認(rèn)證,并對(duì)需要授權(quán)訪問(wèn)的服務(wù)進(jìn)行權(quán)限控制。用戶(hù)在發(fā)起請(qǐng)求時(shí),首先經(jīng)過(guò)全局過(guò)濾器進(jìn)行認(rèn)證,然后再經(jīng)過(guò)局部過(guò)濾器進(jìn)行權(quán)限驗(yàn)證。只有通過(guò)認(rèn)證和授權(quán)的請(qǐng)求才能繼續(xù)訪問(wèn)后端的微服務(wù)。

這種方式使得認(rèn)證和授權(quán)邏輯從業(yè)務(wù)服務(wù)中剝離出來(lái),統(tǒng)一交給網(wǎng)關(guān)進(jìn)行處理,簡(jiǎn)化了業(yè)務(wù)服務(wù)的實(shí)現(xiàn)和管理,同時(shí)提高了系統(tǒng)的安全性和可維護(hù)性。

4.1、過(guò)濾工廠 GratewayFilterFactory

在Spring Cloud Gateway中,過(guò)濾工廠(Filter Factory)是用于創(chuàng)建過(guò)濾器的工廠類(lèi),它用于生成過(guò)濾器實(shí)例并配置過(guò)濾器的行為。過(guò)濾工廠是一種更高級(jí)別的抽象,它將過(guò)濾器的創(chuàng)建和配置過(guò)程封裝在一起,使得配置網(wǎng)關(guān)過(guò)濾器更加簡(jiǎn)單和靈活。

過(guò)濾工廠與過(guò)濾器的區(qū)別在于:

  • 過(guò)濾器:是過(guò)濾器實(shí)際的執(zhí)行邏輯,它需要開(kāi)發(fā)者自己實(shí)現(xiàn)并繼承特定的Filter接口(如GlobalFilter或GatewayFilter),完成請(qǐng)求和響應(yīng)的處理。
  • 過(guò)濾工廠:是用于創(chuàng)建過(guò)濾器的工廠類(lèi),它將過(guò)濾器的創(chuàng)建和配置封裝起來(lái),通過(guò)配置工廠的參數(shù),可以快速創(chuàng)建不同類(lèi)型的過(guò)濾器,并指定過(guò)濾器的行為。

過(guò)濾工廠的優(yōu)勢(shì)在于,它提供了一些預(yù)定義的工廠,可以輕松地為常見(jiàn)的過(guò)濾器場(chǎng)景創(chuàng)建過(guò)濾器,而無(wú)需開(kāi)發(fā)者自己編寫(xiě)過(guò)濾器的實(shí)現(xiàn)。通過(guò)簡(jiǎn)單的配置,開(kāi)發(fā)者可以使用這些預(yù)定義的過(guò)濾工廠創(chuàng)建自定義的過(guò)濾器,從而實(shí)現(xiàn)特定的路由和請(qǐng)求處理邏輯。

spring提供了31種不同的路由過(guò)濾器工廠,一些常用的過(guò)濾工廠包括:

通過(guò)使用過(guò)濾工廠,您可以在網(wǎng)關(guān)中快速配置和管理過(guò)濾器,實(shí)現(xiàn)對(duì)請(qǐng)求和響應(yīng)的靈活處理。過(guò)濾工廠是Spring Cloud Gateway提供的一種高級(jí)配置方式,幫助開(kāi)發(fā)者更加方便地定制和擴(kuò)展網(wǎng)關(guān)的功能。

如果想使用其他的可以到過(guò)往進(jìn)行學(xué)習(xí):spring GatewayFilterFactory

4.1.1、案例
?給所有進(jìn)入userservice的請(qǐng)求添加一個(gè)請(qǐng)求頭

?默認(rèn)過(guò)濾器

總結(jié)
  • ?過(guò)濾器的作用是什么?

????????????????對(duì)路由的請(qǐng)求或響應(yīng)做加工處理,比如添加請(qǐng)求頭

????????????????配置在路由下的過(guò)濾器只對(duì)當(dāng)前路由的請(qǐng)求生效

  • defaultFilters的作用是什么?

????????????????對(duì)所有路由都生效的過(guò)濾器

5、全局過(guò)濾器 GlobalFilter

全局過(guò)濾器(Global Filter):我們可以創(chuàng)建一個(gè)全局過(guò)濾器來(lái)攔截所有的請(qǐng)求,在這個(gè)過(guò)濾器中進(jìn)行用戶(hù)身份認(rèn)證的檢查。比如,我們可以檢查請(qǐng)求中是否包含有效的身份令牌(Token),以確定請(qǐng)求是否是經(jīng)過(guò)認(rèn)證的用戶(hù)發(fā)起的。

全局過(guò)濾器的作用也是處理一切進(jìn)入網(wǎng)關(guān)的請(qǐng)求和微服務(wù)響應(yīng),與GatewayFilter的作用一樣。區(qū)別在于GatewayFilter通過(guò)配置定義,處理邏輯是固定的。而GlobalFilter的邏輯需要自己寫(xiě)代碼實(shí)現(xiàn)。定義方式是實(shí)現(xiàn)GlobalFilter接口。

5.1、實(shí)現(xiàn)步驟

自定義來(lái),實(shí)現(xiàn)GlobalFilter接口,添加@Order注解

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** 自定義全局過(guò)濾器:用于校驗(yàn)請(qǐng)求中的authorization參數(shù)是否合法*/
@Component
@Order(-1)
public class AuthorizeFilter implements GlobalFilter {/*** 過(guò)濾器方法,用于校驗(yàn)請(qǐng)求中的authorization參數(shù)是否合法* @param exchange 服務(wù)器WebExchange對(duì)象,包含請(qǐng)求和響應(yīng)信息* @param chain GatewayFilterChain對(duì)象,用于傳遞請(qǐng)求給下一個(gè)過(guò)濾器或路由處理器* @return Mono<Void>,表示請(qǐng)求的處理結(jié)果*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 獲取請(qǐng)求參數(shù)MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();// 獲取authorization參數(shù)String authorization = params.getFirst("authorization");// 校驗(yàn)authorization參數(shù)if ("ltc".equals(authorization)) {// 授權(quán)通過(guò),請(qǐng)求繼續(xù)傳遞給下一個(gè)過(guò)濾器或路由處理器return chain.filter(exchange);} else {// 授權(quán)不通過(guò),設(shè)置響應(yīng)狀態(tài)碼為403(禁止訪問(wèn)),并結(jié)束處理,返回禁止訪問(wèn)的響應(yīng)exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);return exchange.getResponse().setComplete();}}
}
總結(jié)

全局過(guò)濾器的作用是什么?

  • 對(duì)所有路由都生效的過(guò)濾器,并且可以自定義處理邏輯

實(shí)現(xiàn)全局過(guò)濾器的步驟?

  1. 實(shí)現(xiàn)GlobalFilter接口
  2. 添加@Order注解或?qū)崿F(xiàn)Ordered接口
  3. 編寫(xiě)處理邏輯

6、過(guò)濾器執(zhí)行順序

請(qǐng)求進(jìn)入網(wǎng)關(guān)會(huì)碰到三類(lèi)過(guò)濾器: 當(dāng)前路由的過(guò)濾器、DefaultFilter、GlobalFilter

請(qǐng)求路由后,會(huì)將當(dāng)前路由過(guò)濾器和DefaultFilter、GlobalFilter,合并到一個(gè)過(guò)濾器鏈(集合)中,排序后依次執(zhí)行每個(gè)過(guò)濾器。

這是我們就會(huì)想,這三個(gè)過(guò)濾器相同嗎?怎么就可以放在同一個(gè)集合中進(jìn)行排序了,別著急。

?對(duì)于當(dāng)前路由過(guò)濾器和DefaultFilter的配置方法是非常相似的,區(qū)別就是當(dāng)前路由過(guò)濾器放在路由內(nèi),而DefaultFilter是放在默認(rèn)的過(guò)濾器內(nèi)的。從java的底層來(lái)看他兩個(gè)本質(zhì)是一樣的,只是作用范圍不一樣而已。

?在配置文件中配置的當(dāng)前路由過(guò)濾器和DefaultFilter(默認(rèn)過(guò)濾器)都是由AddRequestHeaderGatewayFilterFactory過(guò)濾器工廠來(lái)讀取,然后生成了GatewayFilter過(guò)濾器,所以這兩個(gè)過(guò)濾器本質(zhì)都是同一類(lèi),他們兩個(gè)都叫GatewayFilter過(guò)濾器。

但是GlobalFilter全局過(guò)濾器為什么又可以和GatewayFilter來(lái)進(jìn)行配置執(zhí)行呢?

在網(wǎng)關(guān)中有一個(gè)適配器GatewayFilterAdapter,他就可以將GlobalFilter適配成GatewayFilter來(lái)用。

?GatewayFilterAdapter適配器這個(gè)類(lèi)就實(shí)現(xiàn)了GatewayFilter接口,他內(nèi)部還接收了GlobalFilter全局過(guò)濾器,如果我們給他傳入一個(gè)GlobalFilter全局過(guò)濾器,他就會(huì)將GlobalFilter適配成GatewayFilter來(lái)用。所以在網(wǎng)關(guān)中所有的過(guò)濾器都會(huì)被適配成Gateway來(lái)使用,所以這些過(guò)濾器就可以放到一個(gè)集合中來(lái)進(jìn)行排序了。

這時(shí)就會(huì)出現(xiàn)一個(gè)新的問(wèn)題了,那放到了一個(gè)集合后,有怎么進(jìn)行排序呢?

6.1、過(guò)濾器執(zhí)如何排序
  • ?每個(gè)過(guò)濾器都必須指定一個(gè)int類(lèi)型的order值,order值越小,優(yōu)先級(jí)越高,執(zhí)行順序越靠前。
  • GlobalFilter通過(guò)實(shí)現(xiàn)Order接口,或者添加@Order注解來(lái)指定order值,由我們自己指定。
  • 路由過(guò)濾器和defaultFilter的order由Spring指定,默認(rèn)是按照聲明順序從1遞增。

?多余多個(gè)路由過(guò)濾器 和多個(gè)默認(rèn)路由器:

  • 如果有多個(gè)路由過(guò)濾器,那他們是按照聲明的順序來(lái)遞增order的值的,來(lái)排序他們的執(zhí)行順序。
  • 多個(gè)默認(rèn)路由也是如此的,也是按聲明的順序來(lái)遞增order的值,來(lái)排序他們的執(zhí)行順序。

但是當(dāng)默認(rèn)過(guò)濾器、路由過(guò)濾器和GlobalFilter全局過(guò)濾器的order值相同呢,那又該怎么辦呢?

  • 當(dāng)過(guò)濾器的order值一樣時(shí),會(huì)按照defaultFilter > 路由過(guò)濾器 > GlobalFilter全局過(guò)濾器的順序執(zhí)行。

底層源碼中有兩個(gè)類(lèi)是用來(lái)加載這三種過(guò)濾器的:

當(dāng)服務(wù)啟動(dòng)后RouteDefinitionRouteLocator類(lèi)的getFilter()方法會(huì)首先執(zhí)行,會(huì)先去配置文件中加載defaultFilters,然后才會(huì)去加載某個(gè)路由的route的filter,然后合并。?

當(dāng)getFilter()方法執(zhí)行完后,FilteringWebHandler類(lèi)的handle()方法才會(huì)進(jìn)行加載全局過(guò)濾器,加載后會(huì)與之前加載的過(guò)濾器合并后更具order排序,組織過(guò)過(guò)濾器鏈

總結(jié)

路由過(guò)濾器、defaultFilter、全局過(guò)濾器的執(zhí)行順序?

  1. order值越小,優(yōu)先級(jí)越高
  2. 當(dāng)order值一樣時(shí),順序是defaultFilter最先,然后是局部的路由過(guò)濾器,最后是全局過(guò)濾器

7、跨域問(wèn)題處理

7.1、跨越問(wèn)題

跨域問(wèn)題(Cross-Origin Issue)是由瀏覽器的同源策略引起的。同源策略是一種安全機(jī)制,限制了網(wǎng)頁(yè)文檔或腳本從一個(gè)源(協(xié)議、域名、端口號(hào)的組合)加載或操作另一個(gè)源的內(nèi)容。如果兩個(gè)網(wǎng)頁(yè)的協(xié)議、域名和端口號(hào)都相同,它們就是同源的,否則就被認(rèn)為是跨域的。

跨域:域名不一致就是跨域,主要包括:

  • 域名不同:www.taobao.com和 www.taobao.org 和 wwwjd.com 和 miaoshajd.com
  • 域名相同,端口不同: localhost:8080和localhost8081

跨越問(wèn)題:瀏覽器禁止請(qǐng)求的發(fā)起者和服務(wù)端發(fā)生跨域Ajax請(qǐng)求,請(qǐng)求被瀏覽器攔截的問(wèn)題。

跨域問(wèn)題的出現(xiàn)是為了防止惡意網(wǎng)站利用客戶(hù)端的漏洞進(jìn)行攻擊,保護(hù)用戶(hù)的隱私和安全。瀏覽器會(huì)強(qiáng)制執(zhí)行同源策略,禁止網(wǎng)頁(yè)在不同源之間進(jìn)行以下操作:

  1. 通過(guò) XMLHttpRequest 或 Fetch API 發(fā)送跨域請(qǐng)求。
  2. 訪問(wèn)其他源的 Cookie、LocalStorage 和 IndexedDB。
  3. 獲取其他源的 DOM 元素。
  4. 在其他源的窗口中執(zhí)行腳本。

舉個(gè)例子來(lái)說(shuō)明跨域問(wèn)題:假設(shè)網(wǎng)站A的域名是 https://www.example.com,網(wǎng)站B的域名是 https://api.example.com。如果網(wǎng)站A的網(wǎng)頁(yè)中使用 XMLHttpRequest 或 Fetch API 向網(wǎng)站B發(fā)送請(qǐng)求,那么由于它們不是同源的,瀏覽器會(huì)阻止這個(gè)請(qǐng)求,返回一個(gè)錯(cuò)誤。這就是跨域問(wèn)題。

7.2、跨越問(wèn)題解決辦法 CORS

只需要在application.yml文件中添加下面的配置即可。

spring:cloud:gateway:globalcors:corsConfigurations:'[/**]': # 配置所有路徑的全局CORS設(shè)置allowedOrigins: "https://example.com" # 允許的跨域請(qǐng)求源,這里設(shè)置為https://example.comallowedMethods: "GET, POST, PUT, DELETE" # 允許的請(qǐng)求方法,這里設(shè)置為GET、POST、PUT、DELETEallowedHeaders: "*" # 允許的請(qǐng)求頭,這里設(shè)置為"*"表示允許任意請(qǐng)求頭allowCredentials: true # 是否允許發(fā)送憑證信息(如Cookie),這里設(shè)置為true表示允許發(fā)送憑證信息maxAge: 3600 # 預(yù)檢請(qǐng)求的緩存時(shí)間(單位:秒),這里設(shè)置為3600秒add-to-simple-url-handler-mapping: true  #處理option請(qǐng)求被攔截問(wèn)題

?配置詳細(xì)介紹:

  1. corsConfigurations: 這個(gè)屬性用于配置全局的CORS設(shè)置。[/**] 表示匹配所有路徑,也就是對(duì)所有請(qǐng)求生效的全局CORS配置。

  2. allowedOrigins: 允許的跨域請(qǐng)求源。這里設(shè)置為 https://example.com,表示只允許來(lái)自 https://example.com 域名的請(qǐng)求進(jìn)行跨域訪問(wèn)。你可以根據(jù)實(shí)際需求設(shè)置允許的域名,也可以使用通配符 * 表示允許所有域名的請(qǐng)求。

  3. allowedMethods: 允許的請(qǐng)求方法。這里設(shè)置為 GET, POST, PUT, DELETE,表示只允許這些HTTP方法的請(qǐng)求進(jìn)行跨域訪問(wèn)。你可以根據(jù)需要添加或刪除允許的方法。

  4. allowedHeaders: 允許的請(qǐng)求頭。這里設(shè)置為 *,表示允許任意請(qǐng)求頭。你也可以設(shè)置具體的請(qǐng)求頭名稱(chēng),比如 "Content-Type, Authorization",只允許這些請(qǐng)求頭進(jìn)行跨域訪問(wèn)。

  5. allowCredentials: 是否允許發(fā)送憑證信息(如Cookie)。這里設(shè)置為 true,表示允許發(fā)送憑證信息。如果設(shè)置為 false,則不允許發(fā)送憑證信息。

  6. maxAge: 預(yù)檢請(qǐng)求的緩存時(shí)間(單位:秒)。預(yù)檢請(qǐng)求是指瀏覽器在發(fā)送跨域請(qǐng)求前先發(fā)送一個(gè) OPTIONS 請(qǐng)求來(lái)檢查服務(wù)器是否允許跨域訪問(wèn)。這里設(shè)置為 3600 秒,表示預(yù)檢請(qǐng)求的結(jié)果在 3600 秒內(nèi)可以被緩存,減少預(yù)檢請(qǐng)求的次數(shù)。

  7. add-to-simple-url-handler-mapping: 這個(gè)屬性設(shè)置為 true,將CORS配置添加到簡(jiǎn)單URL處理程序映射中。這是一個(gè)內(nèi)部屬性,通常不需要手動(dòng)設(shè)置。

通過(guò)以上配置,Spring Cloud Gateway 將會(huì)在響應(yīng)中添加相應(yīng)的CORS響應(yīng)頭,允許來(lái)自 https://example.com 域名的跨域請(qǐng)求,允許的方法有 GET、POST、PUT、DELETE,允許任意請(qǐng)求頭,允許發(fā)送憑證信息(如 Cookie),并且預(yù)檢請(qǐng)求的緩存時(shí)間為 3600 秒。

總結(jié)

·CORS跨域要配置的參數(shù)包括哪幾個(gè)?

  • 允許哪些域名跨域?
  • 允許哪些請(qǐng)求頭?
  • 允許哪些請(qǐng)求方式?
  • 是否允許使用cookie?
  • 有效期是多久?

?此篇是在學(xué)習(xí)黑馬課springcloud程是做的詳細(xì)的筆記,內(nèi)容是自己總結(jié)過(guò)后,易懂,但是就是篇幅有點(diǎn)多,需要大家多花時(shí)間去看。


---------------------
作者:m0_62498006
來(lái)源:CSDN
原文:https://blog.csdn.net/m0_62498006/article/details/131927338
版權(quán)聲明:本文為作者原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
內(nèi)容解析By:CSDN,CNBLOG博客文章一鍵轉(zhuǎn)載插件

http://m.risenshineclean.com/news/65228.html

相關(guān)文章:

  • 濟(jì)南做網(wǎng)站公司哪家好如何做電商 個(gè)人
  • 上海網(wǎng)站建設(shè)工作東莞整站優(yōu)化排名
  • 甘肅政府網(wǎng)站建設(shè)seo如何優(yōu)化關(guān)鍵詞
  • 什么是功能型網(wǎng)站有沒(méi)有免費(fèi)的寫(xiě)文案的軟件
  • 百度外賣(mài)網(wǎng)站建設(shè)與維護(hù)方法seo推廣教學(xué)
  • 做古玩生意哪些網(wǎng)站好互聯(lián)網(wǎng)營(yíng)銷(xiāo)師證書(shū)怎么考
  • 宜興建設(shè)局 審圖中心 網(wǎng)站seo快速排名軟件案例
  • 做企業(yè)網(wǎng)站要大陸營(yíng)業(yè)執(zhí)照百度小說(shuō)搜索風(fēng)云榜總榜
  • 專(zhuān)業(yè)做營(yíng)銷(xiāo)網(wǎng)站百度推廣怎么推
  • 展示型網(wǎng)站設(shè)計(jì)方案百度域名收錄
  • 番禺人才網(wǎng)最新招聘信息網(wǎng)濰坊網(wǎng)站建設(shè)優(yōu)化
  • 國(guó)外免費(fèi)虛擬主機(jī)惠州seo整站優(yōu)化
  • 重慶市建設(shè)工程信息網(wǎng)質(zhì)量監(jiān)督網(wǎng)站seo策劃方案
  • 品牌建設(shè)完整版淄博seo
  • b2b門(mén)戶(hù)網(wǎng)站建設(shè)多少錢(qián)代寫(xiě)
  • 1免費(fèi)做網(wǎng)站seo搜索引擎優(yōu)化人才
  • 珊瑚絨毯移動(dòng)網(wǎng)站建設(shè)百度推廣頁(yè)面投放
  • 二級(jí)已備案域名免費(fèi)使用寧波搜索引擎優(yōu)化seo
  • 邯鄲做網(wǎng)站公司哪家好北京網(wǎng)站優(yōu)化多少錢(qián)
  • 專(zhuān)注高端網(wǎng)站設(shè)計(jì)百度百科官網(wǎng)
  • 怎樣看一個(gè)網(wǎng)站的瀏覽量太原seo網(wǎng)站排名
  • 旅游三級(jí)分銷(xiāo)網(wǎng)站google關(guān)鍵詞優(yōu)化排名
  • 廣州做網(wǎng)站建設(shè)的公司長(zhǎng)沙網(wǎng)絡(luò)推廣
  • 青島旅游網(wǎng)站建設(shè)徐州seo排名公司
  • 網(wǎng)站seo計(jì)劃書(shū)代發(fā)百度關(guān)鍵詞排名
  • 網(wǎng)站建設(shè)報(bào)價(jià) 福州seo外包品牌
  • 網(wǎng)站輸入字符 顯示出來(lái)怎么做問(wèn)答推廣
  • 做寫(xiě)字樓用哪個(gè)網(wǎng)站更好比較靠譜的推廣平臺(tái)
  • 廣州網(wǎng)站二級(jí)等保企業(yè)網(wǎng)站營(yíng)銷(xiāo)實(shí)現(xiàn)方式解讀
  • 英國(guó)人做愛(ài)無(wú)網(wǎng)站百度老舊版本大全