微服務(wù)總結(jié)(上)


title: 微服務(wù)總結(jié)
date: 2020/02/20 10:33
author: yujx


本項(xiàng)目代碼

前言:系統(tǒng)架構(gòu)演變

注:微服務(wù)架構(gòu)之前都是前后端未分離的時代。

單體應(yīng)用架構(gòu)

當(dāng)網(wǎng)站流量很小時彪杉,只需一個應(yīng)用花盐,將所有功能都部署在一起冠蒋,以減少部署節(jié)點(diǎn)和成本识脆。

比如說一個電商系統(tǒng)设江,里面會包含很多用戶管理暇屋,商品管理似袁,訂單管理,物流管理等等很多模塊咐刨,我們會把它們做成一個web項(xiàng)目昙衅,然后部署到一臺tomcat服務(wù)器上。

image

優(yōu)點(diǎn):

  1. 項(xiàng)目架構(gòu)簡單定鸟,小型項(xiàng)目的話鸳碧,開發(fā)成本低
  2. 項(xiàng)目部署在一個Tomcat上怀喉,易于部署

缺點(diǎn):

  1. 全部功能集成在一個工程中熏迹,對于大型項(xiàng)目來講不易開發(fā)和維護(hù)
  2. 項(xiàng)目模塊之間緊密耦合率翅,單點(diǎn)容錯率低,并發(fā)能力差(一個功能掛掉沸久,其它全部歇菜季眷。單個Tomcat的并發(fā)有限制)
  3. 無法針對不同模塊進(jìn)行針對性優(yōu)化和水平擴(kuò)展

垂直應(yīng)用架構(gòu)

當(dāng)訪問量逐漸增大,單一應(yīng)用無法滿足需求卷胯,單一應(yīng)用只能依靠增加節(jié)點(diǎn)來應(yīng)對子刮,但是這時候會發(fā)現(xiàn)并不是所有的模塊都會有比較大的訪問量。

還是以上面的電商為例子窑睁,用戶訪問量的增加可能影響的只是用戶和訂單模塊挺峡,但是對消息模塊的影響就比較小. 那么此時我們希望只多增加幾個訂單模塊,而不增加消息模塊担钮。此時單體應(yīng)用就做不到了橱赠,垂直應(yīng)用就應(yīng)運(yùn)而生了。

垂直應(yīng)用架構(gòu)箫津,就是將原來的一個應(yīng)用拆成互不相干的幾個應(yīng)用狭姨,以提升效率。

比如我們可 以將上面電商的單體應(yīng)用拆分成:

  1. 電商系統(tǒng)(商品管理苏遥、訂單管理)
  2. 后臺系統(tǒng)(用戶管理送挑、訂單管理、客戶管理)
  3. CMS系統(tǒng)(廣告管理暖眼、營銷管理)

這樣拆分完畢之后,一旦用戶訪問量變大纺裁,只需要增加電商系統(tǒng)的節(jié)點(diǎn)就可以了诫肠,而無需增加后臺和CMS的節(jié)點(diǎn)司澎。

image

優(yōu)點(diǎn):

  1. 系統(tǒng)拆分實(shí)現(xiàn)了流量分擔(dān),解決了并發(fā)問題
  2. 可以針對不同模塊進(jìn)行優(yōu)化和水平擴(kuò)展(集群)
  3. 一個系統(tǒng)的問題不會影響到其他系統(tǒng)蛤铜,提高容錯率

缺點(diǎn):系統(tǒng)間相互獨(dú)立,無法互相調(diào)用,從而導(dǎo)致會有很多重復(fù)開發(fā)工作

分布式架構(gòu)

當(dāng)垂直應(yīng)用越來越多诚些,重復(fù)的業(yè)務(wù)代碼就會越來越多椅您。這時候韭邓,我們就思考可不可以將重復(fù)的代碼抽取出來,做成統(tǒng)一的業(yè)務(wù)層作為獨(dú)立的服務(wù),然后由前端控制層調(diào)用不同的業(yè)務(wù)層服務(wù)呢?

這就產(chǎn)生了新的分布式系統(tǒng)架構(gòu)。它將把工程拆分成表現(xiàn)層和服務(wù)層兩個部分件甥,服務(wù)層中包含業(yè)務(wù) 邏輯捌议。表現(xiàn)層只需要處理和頁面的交互,業(yè)務(wù)邏輯都是調(diào)用服務(wù)層的服務(wù)來實(shí)現(xiàn)引有。

image

優(yōu)點(diǎn):抽取公共的功能為服務(wù)層瓣颅,提高代碼復(fù)用性

缺點(diǎn):系統(tǒng)間耦合度變高,調(diào)用關(guān)系錯綜復(fù)雜譬正,難以維護(hù)

注:由于當(dāng)時前后端還未分離宫补,所以一定要有一個web層進(jìn)行前端代碼的書寫。(我認(rèn)為的曾我,不一定對)

SOA架構(gòu)(面向服務(wù)架構(gòu))

在分布式架構(gòu)下粉怕,當(dāng)服務(wù)越來越多,容量的評估抒巢,小服務(wù)資源的浪費(fèi)等問題逐漸顯現(xiàn)贫贝,此時需增加一個調(diào)度中心對集群進(jìn)行實(shí)時管理。此時蛉谜,用于資源調(diào)度和治理中心是關(guān)鍵稚晚。

注1:資源就是指的我們的服務(wù)凤优。

注2:面向服務(wù)架構(gòu)引出了一個概念 —— 服務(wù)治理(SOA governance)

SOA是一種粗粒度、松耦合服務(wù)架構(gòu)蜈彼,服務(wù)之間通過簡單、精確定義接口進(jìn)行通訊俺驶,不涉及底層編程接口和通訊模型幸逆。SOA可以看作是B/S模型、Web Service技術(shù)之后的自然延伸暮现。

服務(wù)治理还绘,也稱為SOA治理,是指用來管理SOA的采用和實(shí)現(xiàn)的過程栖袋。以下是在2006年時IBM對于服務(wù)治理要點(diǎn)的總結(jié):

  • 服務(wù)定義(服務(wù)的范圍拍顷、接口和邊界)
  • 服務(wù)部署生命周期(各個生命周期階段)
  • 服務(wù)版本治理(包括兼容性)
  • 服務(wù)遷移(啟用和退役)
  • 服務(wù)注冊中心(依賴關(guān)系)
  • 服務(wù)消息模型(規(guī)范數(shù)據(jù)模型)
  • 服務(wù)監(jiān)視(進(jìn)行問題確定)
  • 服務(wù)所有權(quán)(企業(yè)組織)
  • 服務(wù)測試(重復(fù)測試)
  • 服務(wù)安全(包括可接受的保護(hù)范圍)

限于當(dāng)時的技術(shù)發(fā)展水平,廣大軟件設(shè)計(jì)與開發(fā)人員對于SOA和服務(wù)治理的技術(shù)認(rèn)知還主要停留在Web Service和ESB總線等技術(shù)和規(guī)范上塘幅,并沒有真正在軟件開發(fā)中得以充分落地昔案。

實(shí)現(xiàn)方式1

中心化:服務(wù)之間互相調(diào)用通過ESB實(shí)現(xiàn),這樣的缺點(diǎn)电媳,網(wǎng)上寫了很多踏揣,這里不贅述了。

實(shí)現(xiàn)方式2匾乓,通過注冊中心

去中心化:服務(wù)注冊到注冊中心捞稿,當(dāng)調(diào)用時,服務(wù)調(diào)用時拼缝,調(diào)用方通過注冊中心獲取要調(diào)用的地址娱局,進(jìn)行調(diào)用(當(dāng)然,還可以客戶端緩存下來)

優(yōu)點(diǎn):使用注冊中心\ESB解決了服務(wù)間調(diào)用關(guān)系的自動調(diào)節(jié)

缺點(diǎn):

  1. 服務(wù)間會有依賴關(guān)系咧七,一旦某個環(huán)節(jié)出錯會影響較大(服務(wù)雪崩)
  2. 服務(wù)關(guān)系復(fù)雜衰齐,運(yùn)維、測試部署困難

微服務(wù)

微服務(wù)是由以單一應(yīng)用程序構(gòu)成的小服務(wù)猪叙,自己擁有自己的行程與輕量化處理娇斩,服務(wù)依業(yè)務(wù)功能設(shè)計(jì),以全自動的方式部署穴翩,與其他服務(wù)使用 HTTP API 通信犬第。同時服務(wù)會使用最小的規(guī)模的集中管理 (例如 Docker) 能力,服務(wù)可以用不同的編程語言與數(shù)據(jù)庫等組件實(shí)現(xiàn)芒帕。(微服務(wù)使用不同的數(shù)據(jù)庫) —— WIKI

微服務(wù)實(shí)際上是SOA的一個子集歉嗓,微服務(wù)架構(gòu)強(qiáng)調(diào)的一個重點(diǎn)是“業(yè)務(wù)需要徹底的組件化和服務(wù)化”,原有的單個業(yè)務(wù)系統(tǒng)會拆分為多個可以獨(dú)立開發(fā)背蟆、設(shè)計(jì)鉴分、運(yùn)行的小應(yīng)用哮幢。這些小應(yīng)用之間通過服務(wù)完成交互和集成。

微服務(wù)的特點(diǎn):

  • 單一職責(zé):微服務(wù)中每一個服務(wù)都對應(yīng)唯一的業(yè)務(wù)能力志珍,做到單一職責(zé)
  • 微:微服務(wù)的服務(wù)拆分粒度很小橙垢,例如一個用戶管理就可以作為一個服務(wù)。每個服務(wù)雖小伦糯,但“五臟俱全”柜某。
  • 面向服務(wù):面向服務(wù)是說每個服務(wù)都要對外暴露服務(wù)接口API。并不關(guān)心服務(wù)的技術(shù)實(shí)現(xiàn)敛纲,做到與平臺和語言無關(guān)喂击,也不限定用什么技術(shù)實(shí)現(xiàn),只要提供Rest的接口即可淤翔。
  • 自治:自治是說服務(wù)間互相獨(dú)立翰绊,互不干擾
    • 團(tuán)隊(duì)獨(dú)立:每個服務(wù)都是一個獨(dú)立的開發(fā)團(tuán)隊(duì),人數(shù)不能過多旁壮。
    • 技術(shù)獨(dú)立:因?yàn)槭敲嫦蚍?wù)监嗜,提供Rest接口,使用什么技術(shù)沒有別人干涉
    • 前后端分離:采用前后端分離開發(fā)寡具,提供統(tǒng)一Rest接口秤茅,后端不用再為PC、移動段開發(fā)不同接口
    • 數(shù)據(jù)庫分離:每個服務(wù)都使用自己的數(shù)據(jù)源
    • 部署獨(dú)立童叠,服務(wù)間雖然有調(diào)用框喳,但要做到服務(wù)重啟不影響其它服務(wù)。有利于持續(xù)集成和持續(xù)交付厦坛。每個服務(wù)都是獨(dú)立的組件五垮,可復(fù)用,可替換杜秸,降低耦合放仗,易維護(hù)

微服務(wù)的設(shè)計(jì)原則

image

https://www.hotbak.net/key/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E6%BC%94%E5%8F%98SOA%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E7%9A%84%E5%8C%BA%E5%88%AB%E5%92%8C%E8%81%94%E7%B3%BB%E7%90%A6%E5%BD%A6CSDN%E5%8D%9A%E5%AE%A2.html

Spring Cloud架構(gòu)格式

微服務(wù)架構(gòu)的常見問題:

  1. 這么多小服務(wù),如何管理他們撬碟?(服務(wù)注冊與發(fā)現(xiàn) -> 注冊中心[服務(wù)注冊 發(fā)現(xiàn) 剔除])
  2. 這么多小服務(wù)诞挨,他們之間如何通訊?(rest\rpc)
  3. 這么多小服務(wù)呢蛤,客戶端怎么訪問他們?(服務(wù)網(wǎng)關(guān))
  4. 這么多小服務(wù)惶傻,一旦出現(xiàn)問題了,應(yīng)該如何自處理其障?(服務(wù)容錯)
  5. 這么多小服務(wù)银室,一旦出現(xiàn)問題了,應(yīng)該如何排錯?(鏈路追蹤)
image
image

總結(jié)

系統(tǒng)架構(gòu)實(shí)際上是由于現(xiàn)有架構(gòu)滿足不了需求從而對原有架構(gòu)進(jìn)行演變過來的蜈敢,所以在選擇的時候一定要選擇適合的辜荠。

微服務(wù)架構(gòu)是SOA架構(gòu)的子集,只不過微服務(wù)定義了服務(wù)劃分的粒度抓狭、通信方式伯病。

一、微服務(wù)架構(gòu)常見概念

1.1 服務(wù)注冊與發(fā)現(xiàn)

一般會通過注冊中心來實(shí)現(xiàn)服務(wù)的注冊與發(fā)現(xiàn)否过,服務(wù)注冊中心一般有下面3個功能:

  1. 服務(wù)注冊:服務(wù)實(shí)例將自身服務(wù)信息注冊到注冊中心狱从。
  2. 服務(wù)發(fā)現(xiàn):服務(wù)實(shí)例通過注冊中心,獲取到注冊到其中的服務(wù)實(shí)例的信息叠纹,通過這些信息去請求它們提供的服務(wù)。
  3. 服務(wù)剔除:服務(wù)注冊中心將出問題的服務(wù)自動剔除到可用列表之外敞葛,使其不會被調(diào)用到誉察。
image

1.2 服務(wù)調(diào)用

在微服務(wù)架構(gòu)中,通常存在多個服務(wù)之間的遠(yuǎn)程調(diào)用的需求惹谐。目前主流的遠(yuǎn)程調(diào)用技術(shù)有基于
HTTP的RESTful接口以及基于TCP的RPC協(xié)議持偏。

REST:這是一種HTTP調(diào)用的格式,更標(biāo)準(zhǔn)氨肌,更通用鸿秆,無論哪種語言都支持http協(xié)議

RPC:一種進(jìn)程間通信方式。允許像調(diào)用本地服務(wù)一樣調(diào)用遠(yuǎn)程服務(wù)怎囚。RPC框架的主要目標(biāo)就是讓遠(yuǎn)程服務(wù)調(diào)用更簡單卿叽、透明。RPC框架負(fù)責(zé)屏蔽底層的傳輸方式恳守、序列化方式和通信細(xì)節(jié)考婴。開發(fā)人員在使用的時候只需要了解誰在什么位置提供了什么樣的遠(yuǎn)程服務(wù)接口即可,并不需要關(guān)心底層通信細(xì)節(jié)和調(diào)用過程催烘。

區(qū)別:

REST RPC
通訊協(xié)議 HTTP 一般使用TCP
性能 略低 較高
靈活度
應(yīng)用 一般應(yīng)用于微服務(wù)架構(gòu) 一般應(yīng)用于SOA架構(gòu)

1.3 服務(wù)網(wǎng)關(guān)

隨著微服務(wù)的不斷增多沥阱,不同的微服務(wù)一般會有不同的網(wǎng)絡(luò)地址,而外部客戶端可能需要調(diào)用多個服務(wù)的接口才能完成一個業(yè)務(wù)需求伊群,如果讓客戶端直接與各個微服務(wù)通信可能出現(xiàn):

  • 客戶端需要調(diào)用不同的url地址考杉,增加難度
  • 在一定的場景下,存在跨域請求的問題
  • 每個微服務(wù)都需要進(jìn)行單獨(dú)的身份認(rèn)證

針對這些問題舰始,API網(wǎng)關(guān)順勢而生崇棠。

API網(wǎng)關(guān)直面意思是將所有API調(diào)用統(tǒng)一接入到API網(wǎng)關(guān)層,由網(wǎng)關(guān)層統(tǒng)一接入和輸出蔽午。一個網(wǎng)關(guān)的基本功能有:統(tǒng)一接入易茬、安全防護(hù)、協(xié)議適配、流量管控抽莱、長短鏈接支持范抓、容錯能力。有了網(wǎng)關(guān)之后食铐,各個API服務(wù)提供團(tuán)隊(duì)可以專注于自己的的業(yè)務(wù)邏輯處理匕垫,而API網(wǎng)關(guān)更專注于安全、流量虐呻、路由等問題象泵。

image

1.4 服務(wù)容錯

在微服務(wù)當(dāng)中,一個請求經(jīng)常會涉及到調(diào)用幾個服務(wù)斟叼,如果其中某個服務(wù)不可用偶惠,沒有做服務(wù)容錯的話,極有可能會造成一連串的服務(wù)不可用朗涩,這就是雪崩效應(yīng)忽孽。

我們沒法預(yù)防雪崩效應(yīng)的發(fā)生,只能盡可能去做好容錯谢床。服務(wù)容錯的三個核心思想是:

  • 不被外界環(huán)境影響(觀察服務(wù)的外界環(huán)境兄一,例如服務(wù)器CPU、內(nèi)存识腿,保證外界環(huán)境是良好的出革,不會影響應(yīng)用內(nèi)部)
  • 不被上游請求壓垮
  • 不被下游響應(yīng)拖垮
image

1.5 鏈路追蹤

隨著微服務(wù)架構(gòu)的流行,服務(wù)按照不同的維度進(jìn)行拆分渡讼,一次請求往往需要涉及到多個服務(wù)骂束。互聯(lián) 網(wǎng)應(yīng)用構(gòu)建在不同的軟件模塊集上成箫,這些軟件模塊栖雾,有可能是由不同的團(tuán)隊(duì)開發(fā)、可能使用不同的編程 語言來實(shí)現(xiàn)伟众、有可能布在了幾千臺服務(wù)器析藕,橫跨多個不同的數(shù)據(jù)中心。因此凳厢,就需要對一次請求涉及的多個服務(wù)鏈路進(jìn)行日志記錄账胧,性能監(jiān)控即鏈路追蹤。

二先紫、微服務(wù)架構(gòu)的常見解決方案

2.1 ServiceComb

Apache ServiceComb治泥,前身是華為云的微服務(wù)引擎 CSE (Cloud Service Engine) 云服務(wù),是全球首個Apache微服務(wù)頂級項(xiàng)目遮精。它提供了一站式的微服務(wù)開源解決方案居夹,致力于幫助企業(yè)败潦、用戶和開發(fā)者將企業(yè)應(yīng)用輕松微服務(wù)化上云,并實(shí)現(xiàn)對微服務(wù)應(yīng)用的高效運(yùn)維管理准脂。

2.2 SpringCloud

Spring Cloud是一系列框架的集合劫扒。它利用Spring Boot的開發(fā)便利性巧妙地簡化了分布式系統(tǒng)基 礎(chǔ)設(shè)施的開發(fā),如服務(wù)發(fā)現(xiàn)注冊狸膏、配置中心沟饥、消息總線、負(fù)載均衡湾戳、斷路器贤旷、數(shù)據(jù)監(jiān)控等,都可以用 Spring Boot的開發(fā)風(fēng)格做到一鍵啟動和部署砾脑。

Spring Cloud并沒有重復(fù)制造輪子幼驶,它只是將目前各家公司開發(fā)的比較成熟、經(jīng)得起實(shí)際考驗(yàn)的服 務(wù)框架組合起來韧衣,通過Spring Boot風(fēng)格進(jìn)行再封裝屏蔽掉了復(fù)雜的配置和實(shí)現(xiàn)原理县遣,最終給開發(fā)者留 出了一套簡單易懂、易部署和易維護(hù)的分布式系統(tǒng)開發(fā)工具包汹族。

SpringCloud現(xiàn)有實(shí)現(xiàn)

注:上面的組件都是可以任意組合的。

其中SpringCloud Netflix已經(jīng)停止開發(fā)其兴,所以我們只能使用SpringCloud Alibaba了顶瞒。

2.2.1 SpringCloud Alibaba

Spring Cloud Alibaba 致力于提供微服務(wù)開發(fā)的一站式解決方案。此項(xiàng)目包含開發(fā)分布式應(yīng)用微服務(wù)的必需組件元旬,方便開發(fā)者通過 Spring Cloud 編程模型輕松使用這些組件來開發(fā)分布式應(yīng)用服務(wù)榴徐。

依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置匀归,就可以將 Spring Cloud 應(yīng)用接入阿里微服務(wù)解決方案坑资,通過阿里中間件來迅速搭建分布式應(yīng)用系統(tǒng)。

主要功能

服務(wù)限流降級:默認(rèn)支持 WebServlet穆端、WebFlux, OpenFeign袱贮、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ限流降級功能的接入体啰,可以在運(yùn)行時通過控制臺實(shí)時修改限流降級規(guī)則攒巍,還支持查看限流降級 Metrics 監(jiān)控。

服務(wù)注冊與發(fā)現(xiàn):適配Spring Cloud 服務(wù)注冊與發(fā)現(xiàn)標(biāo)準(zhǔn)荒勇,默認(rèn)集成了 Ribbon 的支持柒莉。
分布式配置管理:支持分布式系統(tǒng)中的外部化配置,配置更改時自動刷新沽翔。 消息驅(qū)動能力:基于 Spring Cloud Stream為微服務(wù)應(yīng)用構(gòu)建消息驅(qū)動能力兢孝。

分布式事務(wù):使用 @GlobalTransactional 注解,高效并且對業(yè)務(wù)零侵入地解決分布式事務(wù)問題。

阿里云對象存儲:阿里云提供的海量跨蟹、安全雳殊、低成本、高可靠的云存儲服務(wù)喷市。支持在任何應(yīng)用相种、任何時間、任何地點(diǎn)存儲和訪問任意類型的數(shù)據(jù)品姓。

分布式任務(wù)調(diào)度:提供秒級寝并、精準(zhǔn)、高可靠腹备、高可用的定時(基于 Cron
表達(dá)式)任務(wù)調(diào)度服務(wù)衬潦。同時提供分布式的任務(wù)執(zhí)行模型,如網(wǎng)格任務(wù)植酥。網(wǎng)格任務(wù)支持海量子任務(wù)均勻分配到所有 Worker(schedulerx-client)上執(zhí)行镀岛。

阿里云短信服務(wù):覆蓋全球的短信服務(wù),友好友驮、高效漂羊、智能的互聯(lián)化通訊能力,幫助企業(yè)迅速搭建客戶觸達(dá)通道卸留。

組件

Sentinel:把流量作為切入點(diǎn)走越,從流量控制、熔斷降級耻瑟、系統(tǒng)負(fù)載保護(hù)等多個維度保護(hù)服務(wù)的穩(wěn)定性旨指。

Nacos:一個更易于構(gòu)建云原生應(yīng)用的動態(tài)服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)管理平臺喳整。

RocketMQ:一款開源的分布式消息系統(tǒng)谆构,基于高可用分布式集群技術(shù),提供低延時的框都、高可靠的消息發(fā)布與訂閱服務(wù)搬素。

Dubbo:Apache Dubbo? 是一款高性能 Java RPC 框架。

Seata:阿里巴巴開源產(chǎn)品魏保,一個易于使用的高性能微服務(wù)分布式事務(wù)解決方案摄狱。

Alibaba Cloud ACM:一款在分布式架構(gòu)環(huán)境中對應(yīng)用配置進(jìn)行集中管理和推送的應(yīng)用配置中心產(chǎn)品脆荷。

Alibaba Cloud OSS: 阿里云對象存儲服務(wù)(Object Storage Service,簡稱 OSS),是阿里云提供的海量墓律、安全桅锄、低成本赘阀、高可靠的云存儲服務(wù)。您可以在任何應(yīng)用戒傻、任何時間、任何地點(diǎn)存儲和訪問任意類型的數(shù)據(jù)蜂筹。

Alibaba Cloud SchedulerX: 阿里中間件團(tuán)隊(duì)開發(fā)的一款分布式任務(wù)調(diào)度產(chǎn)品需纳,提供秒級、精準(zhǔn)艺挪、高可靠不翩、高可用的定時(基于 Cron 表達(dá)式)任務(wù)調(diào)度服務(wù)。

Alibaba Cloud SMS: 覆蓋全球的短信服務(wù)麻裳,友好口蝠、高效、智能的互聯(lián)化通訊能力津坑,幫助企業(yè)迅速搭建客戶觸達(dá)通道妙蔗。

三、服務(wù)注冊與發(fā)現(xiàn) Nacos Discovery

3.1 簡介

服務(wù)注冊:在服務(wù)治理框架中疆瑰,都會構(gòu)建一個注冊中心眉反,每個服務(wù)單元向注冊中心登記自己提供服務(wù)的詳細(xì)信息。并在注冊中心形成一張服務(wù)的清單穆役,服務(wù)注冊中心需要以心跳的方式去監(jiān)測清單中的服務(wù)是否可用寸五,如果不可用,需要在服務(wù)清單中剔除不可用的服務(wù)耿币。

服務(wù)發(fā)現(xiàn):服務(wù)調(diào)用方向服務(wù)注冊中心咨詢服務(wù)梳杏,并獲取所有服務(wù)的實(shí)例清單,實(shí)現(xiàn)對具體服務(wù)實(shí)例的訪問掰读。

image

常見的注冊中心

Zookeeper

zookeeper是一個分布式服務(wù)框架,是Apache Hadoop 的一個子項(xiàng)目叭莫,它主要是用來解決分布式應(yīng)用中經(jīng)常遇到的一些數(shù)據(jù)管理問題蹈集,如:統(tǒng)一命名服務(wù)、狀態(tài)同步服務(wù)雇初、集群管理拢肆、分布式應(yīng)用配置項(xiàng)的管理等。

Eureka

Eureka是Springcloud Netflix中的重要組件靖诗,主要作用就是做服務(wù)注冊和發(fā)現(xiàn)郭怪。

Consul

Consul是基于GO語言開發(fā)的開源工具,主要面向分布式刊橘,服務(wù)化的系統(tǒng)提供服務(wù)注冊鄙才、服務(wù)發(fā)現(xiàn)和配置管理的功能。Consul的功能都很實(shí)用促绵,其中包括:服務(wù)注冊/發(fā)現(xiàn)攒庵、健康檢查嘴纺、Key/Value 存儲、多數(shù)據(jù)中心和分布式一致性保證等特性浓冒。Consul本身只是一個二進(jìn)制的可執(zhí)行文件栽渴,所以安裝和部署都非常簡單,只需要從官網(wǎng)下載后稳懒,在執(zhí)行對應(yīng)的啟動腳本即可闲擦。

Nacos

Nacos是一個更易于構(gòu)建云原生應(yīng)用的動態(tài)服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)管理平臺场梆。它是 Spring Cloud Alibaba 組件之一墅冷,負(fù)責(zé)服務(wù)注冊發(fā)現(xiàn)和服務(wù)配置,可以這樣認(rèn)為nacos=eureka+config辙谜。

3.2 Nacos 實(shí)戰(zhàn)

3.2.1 安裝

docker pull nacos/nacos-server
docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server

瀏覽器訪問 http://localhost:8848/nacos 就可以訪問服務(wù)俺榆,默認(rèn)密碼為nacos/nacos。

3.2.2 將微服務(wù)注冊到nacos

1装哆、在pom.xml中添加依賴

<!--nacos客戶端-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2罐脊、在application.yml中添加nacos服務(wù)的地址

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

3、啟動微服務(wù)蜕琴,查看是否注冊到nacos

image

3.2.3 示例:訂單微服務(wù)調(diào)用商品微服務(wù)

1萍桌、在訂單微服務(wù)的主啟動類上添加@EnableDiscoveryClient注解

2、將RestTemplate注入容器

@EnableDiscoveryClient
@EntityScan("cn.x5456.common")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class);
    }

    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

3凌简、創(chuàng)建OrderController

@RestController
@Slf4j
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    // 我們可以通過它獲取到注冊到注冊中心的所有服務(wù)
    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private OrderDao orderDao;


    //下單
    @RequestMapping("/order/prod/{pid}")
    public Order order(@PathVariable("pid") Integer pid) {
        log.info("接收到{}號商品的下單請求,接下來調(diào)用商品微服務(wù)查詢此商品信息", pid);

        // 通過discoveryClient獲取服務(wù)的實(shí)例信息
        List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
        ServiceInstance instance = instances.get(0);

        //調(diào)用商品微服務(wù)上炎,查詢商品信息
        Product product = restTemplate.getForObject("http://" + instance.getHost() + ":" + instance.getPort() + "/product/" + pid, Product.class);

        log.info("查詢到{}號商品的信息,內(nèi)容是:{}", pid, JSON.toJSONString(product));

        //下單(創(chuàng)建訂單)
        Order order = new Order();
        order.setUid(1);
        order.setUsername("測試用戶");
        order.setPid(pid);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);

        orderDao.save(order);

        return order;
    }

}

4、啟動訂單和商品微服務(wù)雏搂,訪問 http://127.0.0.1:8091/order/prod/1

image

注:一般情況下藕施,我們都會將一個微服務(wù)部署好多份,目的就是為了可以對請求進(jìn)行負(fù)載凸郑,像我們上面那樣寫裳食,每次調(diào)用都會使用同一個服務(wù)。

3.2.4 配置服務(wù)調(diào)用采用負(fù)載均衡

負(fù)載均衡就是將負(fù)載(工作任務(wù)芙沥,訪問請求)進(jìn)行分?jǐn)偟蕉鄠€操作單元(服務(wù)器,組件)上進(jìn)行執(zhí)行诲祸。

根據(jù)負(fù)載均衡發(fā)生位置的不同,一般分為服務(wù)端負(fù)載均衡和客戶端負(fù)載均衡而昨。

服務(wù)端負(fù)載均衡指的是發(fā)生在服務(wù)提供者一方救氯,比如常見的nginx負(fù)載均衡。

而客戶端負(fù)載均衡指的是發(fā)生在服務(wù)請求的一方歌憨,也就是在發(fā)送請求之前已經(jīng)選好了由哪個實(shí)例處理請求。

image

我們在微服務(wù)調(diào)用關(guān)系中一般會選擇客戶端負(fù)載均衡享扔,也就是在服務(wù)調(diào)用的一方來決定服務(wù)由哪個提供者執(zhí)行暮顺。

使用Netflix Ribbon 實(shí)現(xiàn)

1捶码、再啟動一個商品微服務(wù)

image

2、在注入的RestTemplate上加上@LoadBalanced注解

@EnableDiscoveryClient  // 這個注解可以刪除
@EntityScan("cn.x5456.common")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class);
    }

    @Bean
    @LoadBalanced // 添加這個注解
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

3或链、修改order方法

// 可以刪掉
@Autowired
private DiscoveryClient discoveryClient;

//下單--自定義負(fù)載均衡
@RequestMapping("/order/prod/{pid}")
public Order order(@PathVariable("pid") Integer pid) {
  log.info("接收到{}號商品的下單請求,接下來調(diào)用商品微服務(wù)查詢此商品信息", pid);

  Product product = restTemplate.getForObject("http://service-product/product/" + pid, Product.class);

  log.info("查詢到{}號商品的信息,內(nèi)容是:{}", pid, JSON.toJSONString(product));

  //下單(創(chuàng)建訂單)
  Order order = new Order();
  order.setUid(1);
  order.setUsername("測試用戶");
  order.setPid(pid);
  order.setPname(product.getPname());
  order.setPprice(product.getPprice());
  order.setNumber(1);

  orderDao.save(order);

  log.info("創(chuàng)建訂單成功,訂單信息為{}", JSON.toJSONString(order));

  return order;
}

4惫恼、多訪問幾遍 http://127.0.0.1:8091/order/prod/1 ,查看日志澳盐。

Ribbon支持的負(fù)載均衡策略

Ribbon內(nèi)置了多種負(fù)載均衡策略,內(nèi)部負(fù)載均衡的頂級接口為 com.netflix.loadbalancer.IRule祈纯,具體的負(fù)載策略如下表所示:

策略名 策略聲明 策略描述 實(shí)現(xiàn)說明
BestAvailableRule public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule 選擇一個最小的并發(fā)請求的server 逐個考察Server,如果Server被tripped了叼耙,則忽略腕窥,在選擇其中ActiveRequestsCount最小的server
AvailabilityFilteringRule public class AvailabilityFilteringRule extends PredicateBasedRule 過濾掉那些因?yàn)橐恢边B接失敗的被標(biāo)記為circuit tripped的后端server,并過濾掉那些高并發(fā)的的后端server(active connections 超過配置的閾值) 使用一個AvailabilityPredicate來包含過濾server的邏輯筛婉,其實(shí)就就是檢查status里記錄的各個server的運(yùn)行狀態(tài)
WeightedResponseTimeRule public class WeightedResponseTimeRule extends RoundRobinRule 根據(jù)響應(yīng)時間分配一個weight簇爆,響應(yīng)時間越長,weight越小爽撒,被選中的可能性越低入蛆。 一個后臺線程定期的從status里面讀取評價(jià)響應(yīng)時間,為每個server計(jì)算一個weight硕勿。Weight的計(jì)算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權(quán)重哨毁。當(dāng)剛開始運(yùn)行,沒有形成status時首尼,使用roubine策略選擇server挑庶。
RetryRule public class RetryRule extends AbstractLoadBalancerRule 對選定的負(fù)載均衡策略機(jī)上重試機(jī)制言秸。 在一個配置時間段內(nèi)當(dāng)選擇server不成功软能,則一直嘗試使用subRule的方式選擇一個可用的server
RoundRobinRule public class RoundRobinRule extends AbstractLoadBalancerRule roundRobin方式輪詢選擇server 輪詢index,選擇index對應(yīng)位置的server
RandomRule public class RandomRule extends AbstractLoadBalancerRule 隨機(jī)選擇一個server 在index上隨機(jī)举畸,選擇index對應(yīng)位置的server
ZoneAvoidanceRule public class ZoneAvoidanceRule extends PredicateBasedRule 復(fù)合判斷server所在區(qū)域的性能和server的可用性選擇server 使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server查排,前一個判斷判定一個zone的運(yùn)行性能是否可用,剔除不可用的zone(的所有server)抄沮,AvailabilityPredicate用于過濾掉連接數(shù)過多的Server跋核。

我們可以通過修改配置來調(diào)整Ribbon的負(fù)載均衡策略岖瑰,具體代碼如下:

service-product: # 調(diào)用的提供者的名稱
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

四、服務(wù)調(diào)用 Open Feign

Feign是Spring Cloud提供的一個聲明式的偽Http客戶端砂代,它使得調(diào)用遠(yuǎn)程服務(wù)就像調(diào)用本地服務(wù)一樣簡單蹋订,只需要創(chuàng)建一個接口并添加一個注解即可。

Nacos很好的兼容了Feign刻伊,F(xiàn)eign默認(rèn)集成了 Ribbon露戒,所以在Nacos下使用Fegin默認(rèn)就實(shí)現(xiàn)了負(fù)載均衡的效果。

4.1 使用

1捶箱、在order微服務(wù)中引入Feign的依賴

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

2智什、在主啟動類上添加@EnableFeignClients注解,由于Feign會自動采用Ribbon做負(fù)載丁屎,所以就可以不用RestTemplate了荠锭。

@EnableFeignClients
@EntityScan("cn.x5456.common")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class);
    }

//    @Bean
//    @LoadBalanced
//    public RestTemplate getRestTemplate() {
//        return new RestTemplate();
//    }
}

3、創(chuàng)建一個接口

//value用于指定調(diào)用nacos下哪個微服務(wù)
@FeignClient(value = "service-product")
public interface ProductClient {
    //@FeignClient的value +  @RequestMapping的value值  其實(shí)就是完成的請求地址  "http://service-product/product/" + pid
    //指定請求的URI部分
    @RequestMapping("/product/{pid}")
    Product findByPid(@PathVariable("pid") Integer pid);
}

4晨川、修改order方法证九,使用Feign進(jìn)行調(diào)用

@Autowired
private ProductClient productClient;

//下單--fegin
@RequestMapping("/order/prod/{pid}")
public Order order(@PathVariable("pid") Integer pid) {
    log.info("接收到{}號商品的下單請求,接下來調(diào)用商品微服務(wù)查詢此商品信息", pid);

    //調(diào)用商品微服務(wù),查詢商品信息
    Product product = productClient.findByPid(pid);
    log.info("查詢到{}號商品的信息,內(nèi)容是:{}", pid, JSON.toJSONString(product));

    //下單(創(chuàng)建訂單)
    Order order = new Order();
    order.setUid(1);
    order.setUsername("測試用戶");
    order.setPid(pid);
    order.setPname(product.getPname());
    order.setPprice(product.getPprice());
    order.setNumber(1);

    orderDao.save(order);

    log.info("創(chuàng)建訂單成功,訂單信息為{}", JSON.toJSONString(order));
    return order;
}

五、服務(wù)容錯 Sentinel

5.1 服務(wù)雪崩效應(yīng)

在微服務(wù)架構(gòu)中础爬,我們將業(yè)務(wù)拆分成一個個的服務(wù)甫贯,服務(wù)與服務(wù)之間可以相互調(diào)用,但是由于網(wǎng)絡(luò)原因或者自身的原因看蚜,服務(wù)并不能保證服務(wù)的100%可用叫搁,如果單個服務(wù)出現(xiàn)問題,調(diào)用這個服務(wù)就會出現(xiàn)網(wǎng)絡(luò)延遲供炎,此時若有大量的網(wǎng)絡(luò)涌入渴逻,會形成任務(wù)堆積,最終導(dǎo)致服務(wù)癱瘓音诫。

由于服務(wù)與服務(wù)之間的依賴性惨奕,故障會傳播,會對整個微服務(wù)系統(tǒng)造成災(zāi)難性的嚴(yán)重后果竭钝,這就是服務(wù)故障的“雪崩效應(yīng)” 梨撞。

image

雪崩發(fā)生的原因多種多樣,有不合理的容量設(shè)計(jì)香罐,或者是高并發(fā)下某一個方法響應(yīng)變慢卧波,亦或是某臺機(jī)器的資源耗盡。我們無法完全杜絕雪崩源頭的發(fā)生庇茫,只有做好足夠的容錯港粱,保證在一個服務(wù)發(fā)生問題,不會影響到其它服務(wù)的正常運(yùn)行旦签。也就是"雪落而不雪崩"查坪。

5.2 常見的容錯方案

容錯說白了就是保護(hù)自己不被豬隊(duì)友拖垮的一些措施寸宏,下面介紹常見的服務(wù)容錯思路和組件。

常見的容錯思路

1偿曙、隔離

它是指將系統(tǒng)按照一定的原則劃分為若干個服務(wù)模塊氮凝,各個模塊之間相對獨(dú)立,無強(qiáng)依賴望忆。當(dāng)有故障發(fā)生時覆醇,能將問題和影響隔離在某個模塊內(nèi)部,而不擴(kuò)散風(fēng)險(xiǎn)炭臭,不波及其它模塊永脓,不影響整體的系統(tǒng)服務(wù)。常見的隔離方式有:線程池隔離和信號量隔離鞋仍。

image

Hystrix線程隔離技術(shù)解析-線程池

Hystrix線程隔離技術(shù)解析-信號量

2常摧、超時

在上游服務(wù)調(diào)用下游服務(wù)的時候,設(shè)置一個最大響應(yīng)時間威创,如果超過這個時間落午,下游未作出反應(yīng),就斷開請求肚豺,釋放掉線程溃斋。

image
3、限流

限流就是限制系統(tǒng)的輸入和輸出流量已達(dá)到保護(hù)系統(tǒng)的目的吸申。為了保證系統(tǒng)的穩(wěn)固運(yùn)行梗劫,一旦達(dá)到的需要限制的閾值,就需要限制流量并采取少量措施以完成限制流量的目的截碴。

image
4梳侨、熔斷

在互聯(lián)網(wǎng)系統(tǒng)中,當(dāng)下游服務(wù)因訪問壓力過大而響應(yīng)變慢或失敗日丹,上游服務(wù)為了保護(hù)系統(tǒng)整 體的可用性走哺,可以暫時切斷對下游服務(wù)的調(diào)用。這種犧牲局部哲虾,保全整體的措施就叫做熔斷丙躏。

image

服務(wù)熔斷一般有三種狀態(tài):

  • 熔斷關(guān)閉狀態(tài)(Closed) :服務(wù)沒有故障時,熔斷器所處的狀態(tài)束凑,對調(diào)用方的調(diào)用不做任何限制
  • 熔斷開啟狀態(tài)(Open) :后續(xù)對該服務(wù)接口的調(diào)用不再經(jīng)過網(wǎng)絡(luò)晒旅,直接執(zhí)行本地的fallback方法
  • 半熔斷狀態(tài)(Half-Open):嘗試恢復(fù)服務(wù)調(diào)用,允許有限的流量調(diào)用該服務(wù)湘今,并監(jiān)控調(diào)用成功率敢朱。如果成功率達(dá)到預(yù)期剪菱,則說明服務(wù)已恢復(fù)摩瞎,進(jìn)入熔斷關(guān)閉狀態(tài)拴签;如果成功率仍舊很低,則重新進(jìn)入熔斷關(guān)閉狀態(tài)旗们。
5蚓哩、降級

降級其實(shí)就是為服務(wù)提供一個托底方案,一旦服務(wù)無法正常調(diào)用上渴,就使用托底方案岸梨。

image

常見的容錯組件

Hystrix:

Hystrix是由Netflix開源的一個延遲和容錯庫,用于隔離訪問遠(yuǎn)程系統(tǒng)稠氮、服務(wù)或者第三方庫曹阔,防止級聯(lián)失敗,從而提升系統(tǒng)的可用性與容錯性隔披。

Resilience4J:

Resilicence4J一款非常輕量赃份、簡單,并且文檔非常清晰奢米、豐富的熔斷工具抓韩,這也是Hystrix官方推薦的替代產(chǎn)品。不僅如此鬓长,Resilicence4j還原生支持Spring Boot 1.x/2.x谒拴,而且監(jiān)控也支持和 prometheus等多款主流產(chǎn)品進(jìn)行整合。

Sentinel:

Sentinel 是阿里巴巴開源的一款斷路器實(shí)現(xiàn)涉波,本身在阿里內(nèi)部已經(jīng)被大規(guī)模采用英上,非常穩(wěn)定。

Sentinel Hystrix resilience4j
隔離策略 信號量隔離(并發(fā)線程數(shù)限流) 線程池隔離/信號量隔離 信號量隔離
熔斷降級策略 基于響應(yīng)時間啤覆、異常比率善延、異常數(shù)等 異常比率模式、超時熔斷 基于異常比率城侧、響應(yīng)時間
實(shí)時統(tǒng)計(jì)實(shí)現(xiàn) 滑動窗口(LeapArray) 滑動窗口(基于 RxJava) Ring Bit Buffer
動態(tài)規(guī)則配置 支持多種配置源 支持多種數(shù)據(jù)源 有限支持
擴(kuò)展性 豐富的 SPI 擴(kuò)展接口 插件的形式 接口的形式
基于注解的支持 支持 支持 支持
限流 基于 QPS易遣,支持基于調(diào)用關(guān)系的限流 有限的支持 Rate Limiter
集群流量控制 支持 不支持 不支持
流量整形 支持預(yù)熱模式、勻速排隊(duì)模式等多種復(fù)雜場景 不支持 簡單的 Rate Limiter 模式
系統(tǒng)自適應(yīng)保護(hù) 支持 不支持 不支持
控制臺 提供開箱即用的控制臺嫌佑,可配置規(guī)則豆茫、查看秒級監(jiān)控、機(jī)器發(fā)現(xiàn)等 簡單的監(jiān)控查看 不提供控制臺屋摇,可對接其它監(jiān)控系統(tǒng)
多語言支持 Java / C++ Java Java
開源社區(qū)狀態(tài) 活躍 停止維護(hù) 較活躍

5.3 Sentinel簡介&安裝

Sentinel (分布式系統(tǒng)的流量防衛(wèi)兵) 是阿里開源的一套用于服務(wù)容錯的綜合性解決方案揩魂。它以流量為切入點(diǎn),從流量控制炮温、熔斷降級火脉、系統(tǒng)負(fù)載保護(hù)等多個維度來保護(hù)服務(wù)的穩(wěn)定性。

Sentinel 具有以下特征:

豐富的應(yīng)用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發(fā)流量控制在系統(tǒng)容量可以承受的范圍)倦挂、消息削峰填谷畸颅、集群流量控制、實(shí)時熔斷下游不可用應(yīng)用等方援。

完備的實(shí)時監(jiān)控:Sentinel 提供了實(shí)時的監(jiān)控功能没炒。通過控制臺可以看到接入應(yīng)用的單臺機(jī)器秒級數(shù)據(jù),甚至 500 臺以下規(guī)模的集群的匯總運(yùn)行情況犯戏。

廣泛的開源生態(tài):Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊送火,例如與 Spring Cloud、Dubbo先匪、gRPC 的整合种吸。只需要引入相應(yīng)的依賴并進(jìn)行簡單的配置即可快速地接入Sentinel。

完善的 SPI 擴(kuò)展點(diǎn):Sentinel 提供簡單易用呀非、完善的 SPI 擴(kuò)展接口骨稿。您可以通過實(shí)現(xiàn)擴(kuò)展接口來快速地定制邏輯。例如定制規(guī)則管理姜钳、適配動態(tài)數(shù)據(jù)源等坦冠。

Sentinel 分為兩個部分:

  • 核心庫(Java 客戶端)不依賴任何框架/庫,能夠運(yùn)行于所有 Java 運(yùn)行時環(huán)境哥桥,同時對 Dubbo / Spring Cloud 等框架也有較好的支持辙浑。

  • 控制臺(Dashboard)基于 Spring Boot 開發(fā),打包后可以直接運(yùn)行拟糕,不需要額外的 Tomcat 等應(yīng)用容器判呕。

安裝Sentinel控制臺

見項(xiàng)目的docker文件夾中。

安裝完成后送滞,訪問http://127.0.0.1:8099/侠草,默認(rèn)密碼為sentinel/sentinel

image

Sentinel的控制臺其實(shí)就是一個SpringBoot編寫的程序。我們需要將我們的微服務(wù)程序注冊到控制臺上犁嗅,即在微服務(wù)中指定控制臺的地址边涕,并且還要開啟一個跟控制臺傳遞數(shù)據(jù)的端口,控制臺也可以通過此端口調(diào)用微服務(wù)中的監(jiān)控程序獲取微服務(wù)的各種信息褂微。

image

將order微服務(wù)注冊到Sentinel控制臺 & 簡單使用

1功蜓、引入依賴

<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2、編寫OrderController2

@RestController
@Slf4j
public class OrderController2 {
    @RequestMapping("/order/message1")
    public String message1() {
        return "message1";
    }

    @RequestMapping("/order/message2")
    public String message2() {
        return "message2";
    }
}

3宠蚂、在application.yml添加配置

spring:
  cloud:
    sentinel:
      transport:
        port: 9999 #跟控制臺交流的端口,隨意指定一個未使用的端口即可
        dashboard: localhost:8099 # 指定控制臺服務(wù)的地址

4式撼、啟動訂單微服務(wù),訪問http://127.0.0.1:8091/order/message1求厕,刷新控制臺頁面

image

5著隆、為/order/message1接口添加一個流控規(guī)則

image
image

6扰楼、快速訪問http://127.0.0.1:8091/order/message1

image

5.4 Sentinel的基本概念&功能

基本概念

資源:資源是 Sentinel 的關(guān)鍵概念。它可以是 Java 應(yīng)用程序中的任何內(nèi)容美浦,可以是一個服務(wù)弦赖,也可以是一個方法,甚至可以是一段代碼抵代。換句話說資源就是Sentinel要保護(hù)的東西

注:上面那個demo中message1方法就可以認(rèn)為是一個資源

規(guī)則:規(guī)則作用在資源之上忘嫉,定義以什么樣的方式保護(hù)資源荤牍,主要包括流量控制規(guī)則、熔斷降級規(guī)則以及系統(tǒng)保護(hù)規(guī)則庆冕。

注:上面那個demo中就是為message1資源設(shè)置了一種流控規(guī)則康吵,限制了進(jìn)入message1的流量

功能(可以聯(lián)系5.2閱讀)

image
流量控制:

流量控制在網(wǎng)絡(luò)傳輸中是一個常用的概念,它用于調(diào)整網(wǎng)絡(luò)包的數(shù)據(jù)访递。任意時間到來的請求往往是隨機(jī)不可控的晦嵌,而系統(tǒng)的處理能力是有限的。我們需要根據(jù)系統(tǒng)的處理能力對流量進(jìn)行控制拷姿。

熔斷降級:

當(dāng)檢測到調(diào)用鏈路中某個資源出現(xiàn)不穩(wěn)定的表現(xiàn)惭载,例如請求響應(yīng)時間長或異常比例升高的時候,則對這個資源的調(diào)用進(jìn)行限制响巢,讓請求快速失敗描滔,避免影響到其它的資源而導(dǎo)致級聯(lián)故障。

Sentinel 對這個問題采取了兩種手段:

  • 通過并發(fā)線程數(shù)進(jìn)行限制:

    • Sentinel 通過限制資源并發(fā)線程的數(shù)量踪古,來減少不穩(wěn)定資源對其它資源的影響含长。當(dāng)某個資源出現(xiàn)不穩(wěn)定的情況下,例如響應(yīng)時間變長伏穆,對資源的直接影響就是會造成線程數(shù)的逐步堆積拘泞。當(dāng)線程數(shù)在特定資源上堆積到一定的數(shù)量之后,對該資源的新請求就會被拒絕枕扫。堆積的線程完成任務(wù)后才開始繼續(xù)接收請求陪腌。
  • 通過響應(yīng)時間對資源進(jìn)行降級:

    • 除了對并發(fā)線程數(shù)進(jìn)行控制以外,Sentinel 還可以通過響應(yīng)時間來快速降級不穩(wěn)定的資源烟瞧。當(dāng)依賴的資源出現(xiàn)響應(yīng)時間過長后偷厦,所有對該資源的訪問都會被直接拒絕,直到過了指定的時間窗口之后才重新恢復(fù)燕刻。

注:Sentinel 和 Hystrix 的區(qū)別只泼?

兩者的原則是一致的,都是當(dāng)一個資源出現(xiàn)問題時卵洗,讓其快速失敗请唱,不要波及到其它服務(wù)弥咪。

但是在限制的手段上,確采取了完全不一樣的方法:

Hystrix 采用的是線程池隔離的方式十绑,優(yōu)點(diǎn)是做到了資源之間的隔離诚镰,缺點(diǎn)是增加了線程切換的成本。

Sentinel 采用的是通過并發(fā)線程的數(shù)量和響應(yīng)時間來對資源做限制切平。(信號量隔離)

系統(tǒng)負(fù)載保護(hù)

Sentinel 同時提供系統(tǒng)維度自適應(yīng)保護(hù)能力锅减。當(dāng)系統(tǒng)負(fù)載較高的時候,如果還持續(xù)讓請求進(jìn)入可能會導(dǎo)致系統(tǒng)崩潰甚亭,無法響應(yīng)贷币。在集群環(huán)境下,會把本應(yīng)這臺機(jī)器承載的流量轉(zhuǎn)發(fā)到其它的機(jī)器上去亏狰。如果這個時候其它的機(jī)器也處在一個邊緣狀態(tài)的時候役纹,Sentinel 提供了對應(yīng)的保護(hù)機(jī)制,讓系統(tǒng)的入口流量和系統(tǒng)的負(fù)載達(dá)到一個平衡暇唾,保證系統(tǒng)在能力范圍之內(nèi)處理最多的請求促脉。

注:系統(tǒng)的負(fù)載能力,與其所在的服務(wù)器內(nèi)存和CPU等外界環(huán)境有關(guān)策州。

5.5 Sentinel規(guī)則

5.5.1 流控規(guī)則

流量控制瘸味,其原理是監(jiān)控應(yīng)用流量的QPS(每秒查詢率) 或并發(fā)線程數(shù)等指標(biāo),當(dāng)達(dá)到指定的閾值時對流量進(jìn)行控制够挂,以避免被瞬時的流量高峰沖垮硫戈,從而保障應(yīng)用的高可用性。

image

資源名:唯一名稱下硕,默認(rèn)是請求路徑丁逝,可自定義

針對來源;指定對哪個微服務(wù)進(jìn)行限流梭姓,默認(rèn)指default霜幼,意思是不區(qū)分來源,全部限制

閾值類型/單機(jī)閾值:

  • QPS(每秒請求數(shù)量):當(dāng)調(diào)用該接口的QPS達(dá)到閾值的時候誉尖,進(jìn)行限流
  • 線程數(shù):當(dāng)調(diào)用該接口的線程數(shù)達(dá)到閾值的時候罪既,進(jìn)行限流

是否集群:暫不需要集群

配置好后,瘋狂請求/order/message1接口時铡恕,就會出現(xiàn)下面的情況:

image
3種流控模式
image
1琢感、直接流控模式

直接流控模式是最簡單的模式,當(dāng)指定的接口達(dá)到限流條件時開啟限流探熔。就是我們上面演示的例子驹针。

2、關(guān)聯(lián)流控模式

關(guān)聯(lián)流控模式指的是诀艰,當(dāng)指定接口關(guān)聯(lián)的接口達(dá)到限流條件時柬甥,開啟對指定接口開啟限流饮六。

image

當(dāng)/order/message2接口的OPS大于1的時候,/order/message1就會被限流苛蒲。

image
3卤橄、鏈路流控模式

鏈路流控模式指的是,當(dāng)從某個接口過來的資源達(dá)到限流條件時臂外,開啟限流窟扑。它的功能有點(diǎn)類似于針對來源配置項(xiàng),區(qū)別在于:針對來源是針對上級微服務(wù)漏健,而鏈路流控是針對上級接口嚎货,也就是說它的粒度更細(xì)。

1)編寫OrderService

@Service
public class OrderServiceImpl {

    // 定義資源 value是資源的名稱
    @SentinelResource("message")
    public void message() {
        System.out.println("message");
    }
}

2)修改OrderController2中的2個方法漾肮,調(diào)用service層的message方法厂抖。

@RestController
@Slf4j
public class OrderController2 {

    @Autowired
    private OrderServiceImpl orderService;

    @RequestMapping("/order/message1")
    public String message1() {
        orderService.message();
        return "message1";
    }

    @RequestMapping("/order/message2")
    public String message2() {
        orderService.message();
        return "message2";
    }
}

3)禁止收斂URL的入口 context

從1.6.3 版本開始茎毁,Sentinel Web filter默認(rèn)收斂所有URL的入口context克懊,因此鏈路限流不生效。

1.7.0 版本開始(對應(yīng)SCA的2.1.1.RELEASE)七蜘,官方在CommonFilter 引入了 WEB_CONTEXT_UNIFY 參數(shù)谭溉,用于控制是否收斂context。將其配置為 false 即可根據(jù)不同的URL 進(jìn)行鏈路限流橡卤。

SCA 2.1.1.RELEASE之后的版本,可以通過配置spring.cloud.sentinel.web-context-unify=false即可關(guān)閉收斂我們當(dāng)前使用的版本是SpringCloud Alibaba 2.1.0.RELEASE扮念,無法實(shí)現(xiàn)鏈路限流。

目前官方還未發(fā)布SCA 2.1.2.RELEASE碧库,所以我們只能使用2.1.1.RELEASE柜与,需要寫代碼的形式實(shí)現(xiàn)

下面的修改,測試完畢之后要改回來嵌灰;生產(chǎn)環(huán)境最好還是等2.1.2.RELEASE版本發(fā)布弄匕,配合Cloud Hoxton使用。

(1)將SpringCloud Alibaba的版本調(diào)整為2.1.1.RELEASE

<spring-cloud-alibaba.version>2.1.1.RELEASE</spring-cloud-alibaba.version>

(2)配置文件中關(guān)閉sentinel的CommonFilter實(shí)例化

spring:
  cloud:
    sentinel:
      filter:
        enabled: false

(3)手動注入CommonFilter的實(shí)例

@Configuration
public class FilterContextConfig {

    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        // 入口資源關(guān)閉聚合
        registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
        registration.setName("sentinelFilter");
        registration.setOrder(1);
        return registration;
    }
}

4)重啟order微服務(wù)沽瞭,訪問http://127.0.0.1:8091/order/message1

5)配置鏈路限流

image

6)狂點(diǎn)刷新

image
3種流控效果

快速失敗(默認(rèn)):直接失敗迁匠,拋出異常,不做任何額外的處理驹溃,是最簡單的效果

Warm Up:它從開始閾值到最大QPS閾值會有一個緩沖階段城丧,一開始的閾值是最大QPS閾值的1/3,然后慢慢增長豌鹤,直到最大閾值亡哄,適用于將突然增大的流量轉(zhuǎn)換為緩步增長的場景

排隊(duì)等待:讓請求以均勻的速度通過布疙,單機(jī)閾值為每秒通過數(shù)量磺平,其余的排隊(duì)等待; 它還會讓設(shè)置一個超時時間魂仍,當(dāng)請求超過超時間時間還未處理,則會被丟棄拣挪。

5.5.2 降級規(guī)則

降級規(guī)則就是設(shè)置當(dāng)滿足什么條件的時候擦酌,對服務(wù)進(jìn)行降級。Sentinel提供了三個衡量條件:

平均響應(yīng)時間(RT)

當(dāng)資源的平均響應(yīng)時間超過閾值(以 ms 為單位)之后菠劝,資源進(jìn)入準(zhǔn)降級狀態(tài)赊舶。如果接下來 1s 內(nèi)持續(xù)進(jìn)入 5 個請求,它們的 RT都持續(xù)超過這個閾值赶诊,那么在接下的時間窗口(以 s 為單位))之內(nèi)笼平,就會對這個方法進(jìn)行服務(wù)降級。

image

注:注意 Sentinel 默認(rèn)統(tǒng)計(jì)的 RT 上限是 4900 ms舔痪,超出此閾值的都會算作 4900 ms寓调,若需要變更此上限可以通過啟動配置項(xiàng) -Dcsp.sentinel.statistic.max.rt=xxx 來配置。

異常比例

當(dāng)資源的每秒異吵耄總數(shù)占通過量的比值超過閾值之后夺英,資源進(jìn)入降級狀態(tài),即在接下的時間窗口(以 s 為單位)之內(nèi)滋捶,對這個方法的調(diào)用都會自動地返回痛悯。異常比率的閾值范圍是[0.0, 1.0]。

異常數(shù)

當(dāng)資源近 1 分鐘的異常數(shù)目超過閾值之后會進(jìn)行服務(wù)降級重窟。注意由于統(tǒng)計(jì)時間窗口是分鐘級別的载萌,若時間窗口小于 60s,則結(jié)束熔斷狀態(tài)后仍可能再進(jìn)入熔斷狀態(tài)巡扇。

5.5.3 熱點(diǎn)規(guī)則

熱點(diǎn)參數(shù)流控規(guī)則是一種更細(xì)粒度的流控規(guī)則扭仁,它允許將規(guī)則具體到參數(shù)上。

1厅翔、在OrderController2中新增一個方法乖坠,記得添加@SentinelResource注解

@RequestMapping("/order/message3")
@SentinelResource("message3")
public String message3(String name, Integer age) {
    return "message3" + name + age;
}

2、配置熱點(diǎn)規(guī)則

image

單機(jī)閥值:每秒訪問量進(jìn)行限流

統(tǒng)計(jì)窗口時長:超過多長時間知给,恢復(fù)訪問

image

5.5.4 授權(quán)規(guī)則

很多時候瓤帚,我們需要根據(jù)調(diào)用來源來判斷該次請求是否允許放行,例如知網(wǎng)會根據(jù)請求的refer來判斷是爬蟲還是正常的用戶訪問涩赢,從而返回不同的頁面戈次,這時候可以使用 Sentinel 的來源訪問控制的功能。來源訪問控制根據(jù)資源的請求來源(origin)限制資源是否通過:

  • 若配置白名單筒扒,則只有請求來源位于白名單內(nèi)時才可通過;
  • 若配置黑名單怯邪,則請求來源位于黑名單時不通過,其余的請求通過花墩。

1悬秉、OrderController中新增一個方法

@RequestMapping("/order/message4")
public String message4() {
    return "message4";
}

2澄步、實(shí)現(xiàn)RequestOriginParser,定義解析規(guī)則

@Component
public class RequestOriginParserDefinition implements RequestOriginParser {

    //定義區(qū)分來源: 本質(zhì)作用是通過request域獲取到來源標(biāo)識
    //app  pc
    //然后 交給流控應(yīng)用 位置進(jìn)行匹配
    @Override
    public String parseOrigin(HttpServletRequest request) {
        return request.getParameter("serviceName");
    }
}

3和泌、重啟系統(tǒng)村缸,訪問 http://127.0.0.1:8091/order/message4

4、授權(quán)

image

5武氓、當(dāng)訪問 http://127.0.0.1:8091/order/message4?serviceName=pc 可以正常訪問梯皿,訪問其他的會失敗。

image

5.5.5 系統(tǒng)規(guī)則(一般運(yùn)維配置)

系統(tǒng)保護(hù)規(guī)則是從應(yīng)用級別的入口流量進(jìn)行控制县恕,從單臺機(jī)器的總體 Load东羹、RT、入口 QPS 忠烛、CPU 使用率和線程數(shù)五個維度監(jiān)控應(yīng)用數(shù)據(jù)属提,讓系統(tǒng)盡可能跑在最大吞吐量的同時保證系統(tǒng)整體的穩(wěn)定性。

系統(tǒng)保護(hù)規(guī)則是應(yīng)用整體維度的美尸,而不是資源維度的冤议,并且僅對入口流量 (進(jìn)入應(yīng)用的流量)生效。

  • Load(僅對 Linux/Unix-like 機(jī)器生效):當(dāng)系統(tǒng) load1(1min閾值)超過閾值火惊,且系統(tǒng)當(dāng)前的并發(fā)線程數(shù)超過系統(tǒng)容量時才會觸發(fā)系統(tǒng)保護(hù)求类。系統(tǒng)容量由系統(tǒng)的 maxQps * minRt 計(jì)算得出奔垦。設(shè)定參考值一般 是 CPU cores * 2.5屹耐。
  • RT:當(dāng)單臺機(jī)器上所有入口流量的平均 RT 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù),單位是毫秒椿猎。
  • 線程數(shù):當(dāng)單臺機(jī)器上所有入口流量的并發(fā)線程數(shù)達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)惶岭。
  • 入口 QPS:當(dāng)單臺機(jī)器上所有入口流量的 QPS 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)。
  • CPU使用率:當(dāng)單臺機(jī)器上所有入口流量的 CPU使用率達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)犯眠。

擴(kuò)展:自定義異常返回

問題:流控規(guī)則和降級規(guī)則返回的異常頁面是一樣的按灶,我們怎么來區(qū)分到底是什么原因?qū)е碌哪?

//自定義異常返回頁面
@Component
public class ExceptionHandlerPage implements UrlBlockHandler {
    // BlockException是五種規(guī)則異常的父類
    @Override
    public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
        response.setContentType("application/json;charset=utf-8");

        ResponseData responseData = null;
        //BlockException  異常接口,包含Sentinel的五個異常
        //  FlowException  限流異常
        //  DegradeException  降級異常
        //  ParamFlowException  參數(shù)限流異常
        //  AuthorityException  授權(quán)異常
        //  SystemBlockException  系統(tǒng)負(fù)載異常
        if (e instanceof FlowException) {
            responseData = new ResponseData(-1, "接口被限流了...");
        } else if (e instanceof DegradeException) {
            responseData = new ResponseData(-2, "接口被降級了...");
        }
        response.getWriter().write(JSON.toJSONString(responseData));
    }
}

@Data
@AllArgsConstructor//全參構(gòu)造
@NoArgsConstructor
//無參構(gòu)造
class ResponseData {
    private int code;
    private String message;
}

5.6 @SentinelResource的使用

在定義了資源點(diǎn)之后,我們可以通過Dashboard來設(shè)置限流和降級策略來對資源點(diǎn)進(jìn)行保護(hù)筐咧。同時還能通過@SentinelResource來指定出現(xiàn)異常時的處理策略鸯旁。

屬性 作用 是否必須
value 資源名稱
entryType entry類型,標(biāo)記流量的方向量蕊,取值IN/OUT铺罢,默認(rèn)是OUT
blockHandler 處理BlockException的函數(shù)名稱。函數(shù)要求: 1. 必須是 public 2.返回類型與原方法一致 3. 參數(shù)類型需要和原方法相匹配残炮,并在最后加 BlockException 類型的參數(shù)韭赘。 4. 默認(rèn)需和原方法在同一個類中。若希望使用其他類的函數(shù)势就,可配置 blockHandlerClass 泉瞻,并指定blockHandlerClass里面的方法脉漏。
blockHandlerClass 存放blockHandler的類。對應(yīng)的處理函數(shù)必須static修飾袖牙,否則無法解析侧巨,其他要求:同blockHandler。
fallback 用于在拋出異常的時候提供fallback處理邏輯鞭达。fallback函數(shù)可以針對所有類型的異常(除了 exceptionsToIgnore 里面排除掉的異常類型)進(jìn)行處理刃泡。函數(shù)要求: 1. 返回類型與原方法一致 2. 參數(shù)類型需要和原方法相匹配,Sentinel 1.6開始碉怔,也可在方法最后Throwable 類型的參數(shù)烘贴。 3.默認(rèn)需和原方法在同一個類中。若希望使用其他類的函數(shù)撮胧,可配置 fallbackClass 桨踪,并指定fallbackClass里面的方法。
fallbackClass【1.6】 存放fallback的類芹啥。對應(yīng)的處理函數(shù)必須static修飾锻离,否則無法解析,其他要求:同fallback墓怀。
defaultFallback【1.6】 用于通用的 fallback 邏輯汽纠。默認(rèn)fallback函數(shù)可以針對所有類型的異常(除了 exceptionsToIgnore 里面排除掉的異常類型)進(jìn)行處理。若同時配置了 fallback 和 defaultFallback傀履,以fallback為準(zhǔn)虱朵。函數(shù)要求: 1. 返回類型與原方法一致 2. 方法參數(shù)列表為空,或者有一個 Throwable 類型的參數(shù)钓账。 3. 默認(rèn)需要和原方法在同一個類中碴犬。若希望使用其他類的函數(shù),可配置 fallbackClass 梆暮,并指定 fallbackClass 里面的方法服协。
exceptionsToIgnore【1.6】 指定排除掉哪些異常。排除的異常不會計(jì)入異常統(tǒng)計(jì)啦粹,也不會進(jìn)入fallback邏輯偿荷,而是原樣拋出。
exceptionsToTrace 需要trace的異常 Throwable

5.6.1 示例

1唠椭、修改OrderServiceImpl中message方法上的注解跳纳,添加幾個參數(shù)

@Slf4j
@Service
public class OrderServiceImpl {

    //定義一個資源
    //定義當(dāng)資源內(nèi)部發(fā)生異常的時候的處理邏輯
    //blockHandler  定義當(dāng)資源內(nèi)部發(fā)生了BlockException應(yīng)該進(jìn)入的方法[捕獲的是Sentinel定義的異常]
    //fallback      定義當(dāng)資源內(nèi)部發(fā)生了Throwable應(yīng)該進(jìn)入的方法
    @SentinelResource(
            value = "message",
            blockHandler = "blockHandler",
            fallback = "fallback"
    )
    public String message() {
        return "message";
    }

    //blockHandler
    //要求:
    //1 當(dāng)前方法的返回值和參數(shù)要跟原方法一致
    //2 但是允許在參數(shù)列表的最后加入一個參數(shù)BlockException, 用來接收原方法中發(fā)生的異常
    public String blockHandler(BlockException e) {
        //自定義異常處理邏輯
        log.error("觸發(fā)了BlockException,內(nèi)容為{}", e);
        return "BlockException";
    }

    //fallback
    //要求:
    //1 當(dāng)前方法的返回值和參數(shù)要跟原方法一致
    //2 但是允許在參數(shù)列表的最后加入一個參數(shù)BlockException, 用來接收原方法中發(fā)生的異常
    public String fallback(Throwable e) {
        //自定義異常處理邏輯
        log.error("觸發(fā)了Throwable,內(nèi)容為{}", e);
        return "Throwable";
    }

}

2、修改OrderController2中的message1()方法

@RequestMapping("/order/message1")
public String message1() {
    return orderService.message();
}

3泪蔫、去控制臺添加流控規(guī)則

image

4棒旗、快速訪問 http://127.0.0.1:8091/order/message1

image

5.6.2 將限流和降級方法外置到單獨(dú)的類中

@Slf4j
@Service
public class OrderServiceImpl {

    //定義一個資源
    //定義當(dāng)資源內(nèi)部發(fā)生異常的時候的處理邏輯
    //blockHandler  定義當(dāng)資源內(nèi)部發(fā)生了BlockException應(yīng)該進(jìn)入的方法[捕獲的是Sentinel定義的異常]
    //fallback      定義當(dāng)資源內(nèi)部發(fā)生了Throwable應(yīng)該進(jìn)入的方法
    @SentinelResource(
            value = "message",
            blockHandlerClass = OrderServiceImpl3BlockHandler.class,
            blockHandler = "blockHandler",
            fallbackClass = OrderServiceImpl3Fallback.class,
            fallback = "fallback"
    )
    public String message() {
        return "message";
    }


    public static class OrderServiceImpl3BlockHandler {

        //blockHandler
        //要求:
        //1 當(dāng)前方法的返回值和參數(shù)要跟原方法一致
        //2 但是允許在參數(shù)列表的最后加入一個參數(shù)BlockException, 用來接收原方法中發(fā)生的異常
        public static String blockHandler(BlockException e) {
            //自定義異常處理邏輯
            log.error("觸發(fā)了BlockException,內(nèi)容為{}", e);
            return "BlockException";
        }
    }

    public static class OrderServiceImpl3Fallback {

        //fallback
        //要求:
        //1 當(dāng)前方法的返回值和參數(shù)要跟原方法一致
        //2 但是允許在參數(shù)列表的最后加入一個參數(shù)BlockException, 用來接收原方法中發(fā)生的異常
        public static String fallback(Throwable e) {
            //自定義異常處理邏輯
            log.error("觸發(fā)了Throwable,內(nèi)容為{}", e);
            return "Throwable";
        }
    }
}

注:類中的方法必須是static的

5.7 Sentinel規(guī)則持久化

Sentinel規(guī)則默認(rèn)是存放在內(nèi)存中,極不穩(wěn)定,所以需要將其持久化铣揉。

本地文件數(shù)據(jù)源會定時輪詢文件的變更饶深,讀取規(guī)則。這樣我們既可以在應(yīng)用本地直接修改文件來更新規(guī)則逛拱,也可以通過 Sentinel 控制臺推送規(guī)則敌厘。以本地文件數(shù)據(jù)源為例,推送過程如下圖所示:

pull模式

首先 Sentinel 控制臺通過 API 將規(guī)則推送至客戶端并更新到內(nèi)存中朽合,接著注冊的寫數(shù)據(jù)源會將新的規(guī)則保存到本地的文件中俱两。

1、編寫處理類

參見cn.x5456.order.config.FilePersistence

2曹步、添加配置

在resources下創(chuàng)建配置目錄 META-INF/services宪彩,然后添加文件
com.alibaba.csp.sentinel.init.InitFunc,文件內(nèi)容為配置類的全路徑

image

Push模式看這

5.8 Feign整合Sentinel

1讲婚、開啟Feign對Sentinel的支持

# 開啟feign對sentinel的支持
feign:
  sentinel:
    enabled: true

2尿孔、創(chuàng)建容錯類

//這是一個容錯類
//它要求實(shí)現(xiàn)Feign所在接口,并實(shí)現(xiàn)里面的方法
//當(dāng)feign調(diào)用出現(xiàn)問題的時候,就會進(jìn)入到當(dāng)前類中同名方法中
@Component
public class ProductServiceFallback implements ProductClient {
    @Override
    public Product findByPid(Integer pid) {
        Product product = new Product();
        product.setPid(-100);
        product.setPname("商品微服務(wù)調(diào)用出現(xiàn)異常了,已經(jīng)進(jìn)入到了容錯方法中");
        return product;
    }
}

3、修改ProductClient上的注解

//value用于指定調(diào)用nacos下哪個微服務(wù)
@FeignClient(value = "service-product", fallback = ProductServiceFallback.class)
public interface ProductClient {
    //@FeignClient的value +  @RequestMapping的value值  其實(shí)就是完成的請求地址  "http://service-product/product/" + pid
    //指定請求的URI部分
    @RequestMapping("/product/{pid}")
    Product findByPid(@PathVariable("pid") Integer pid);
}

4筹麸、修改OrderController的order方法

//下單--fegin
@RequestMapping("/order/prod/{pid}")
public Order order(@PathVariable("pid") Integer pid) {
  log.info("接收到{}號商品的下單請求,接下來調(diào)用商品微服務(wù)查詢此商品信息", pid);

  //調(diào)用商品微服務(wù),查詢商品信息
  Product product = productClient.findByPid(pid);

  if (product.getPid() == -100) {
      Order order = new Order();
      order.setOid(-100L);
      order.setPname("下單失敗");
      return order;
  }

  log.info("查詢到{}號商品的信息,內(nèi)容是:{}", pid, JSON.toJSONString(product));

  //下單(創(chuàng)建訂單)
  Order order = new Order();
  order.setUid(1);
  order.setUsername("測試用戶");
  order.setPid(pid);
  order.setPname(product.getPname());
  order.setPprice(product.getPprice());
  order.setNumber(1);

  orderDao.save(order);

  log.info("創(chuàng)建訂單成功,訂單信息為{}", JSON.toJSONString(order));

  return order;
}

5活合、啟動服務(wù),訪問 http://127.0.0.1:8091/order/prod/1物赶,由于商品微服務(wù)未開白指,所以會報(bào)錯

image

6、采用這種方式酵紫,異常信息被隱藏了告嘲,所以可以采用另外一種方式

1)新建ProductServiceFallbackFactory類

//這是容錯類,他要求我們要是實(shí)現(xiàn)一個FallbackFactory<要為哪個接口產(chǎn)生容錯類>
@Slf4j
@Service
public class ProductServiceFallbackFactory implements FallbackFactory<ProductClient> {

    //Throwable  這就是fegin在調(diào)用過程中產(chǎn)生異常
    @Override
    public ProductClient create(Throwable throwable) {
        return new ProductClient() {
            @Override
            public Product findByPid(Integer pid) {
                log.error("{}",throwable);
                Product product = new Product();
                product.setPid(-100);
                product.setPname("商品微服務(wù)調(diào)用出現(xiàn)異常了,已經(jīng)進(jìn)入到了容錯方法中");
                return product;
            }
        };
    }
}

2)修改ProductClient上的注解

//value用于指定調(diào)用nacos下哪個微服務(wù)
@FeignClient(value = "service-product", fallbackFactory = ProductServiceFallbackFactory.class)
public interface ProductClient {
    //@FeignClient的value +  @RequestMapping的value值  其實(shí)就是完成的請求地址  "http://service-product/product/" + pid
    //指定請求的URI部分
    @RequestMapping("/product/{pid}")
    Product findByPid(@PathVariable("pid") Integer pid);
}

注:fallback和fallbackFactory只能使用其中一種方式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市憨闰,隨后出現(xiàn)的幾起案子状蜗,更是在濱河造成了極大的恐慌需五,老刑警劉巖鹉动,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宏邮,居然都是意外死亡泽示,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門蜜氨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來械筛,“玉大人,你說我怎么就攤上這事飒炎÷裼矗” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赤赊。 經(jīng)常有香客問我闯狱,道長,這世上最難降的妖魔是什么抛计? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任哄孤,我火速辦了婚禮,結(jié)果婚禮上吹截,老公的妹妹穿的比我還像新娘瘦陈。我一直安慰自己,他們只是感情好波俄,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布晨逝。 她就那樣靜靜地躺著,像睡著了一般懦铺。 火紅的嫁衣襯著肌膚如雪咏花。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天阀趴,我揣著相機(jī)與錄音昏翰,去河邊找鬼。 笑死刘急,一個胖子當(dāng)著我的面吹牛棚菊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叔汁,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼统求,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了据块?” 一聲冷哼從身側(cè)響起码邻,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎另假,沒想到半個月后像屋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡边篮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年己莺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戈轿。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡凌受,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出思杯,到底是詐尸還是另有隱情胜蛉,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站誊册,受9級特大地震影響奈梳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜解虱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一攘须、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧殴泰,春花似錦于宙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至离咐,卻和暖如春谱俭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宵蛀。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工昆著, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人术陶。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓凑懂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親梧宫。 傳聞我的和親對象是個殘疾皇子接谨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345