日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【檀越剑指大厂—SpringCloudNetflix】SpringCloudNetflix高阶篇

發布時間:2024/3/24 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【檀越剑指大厂—SpringCloudNetflix】SpringCloudNetflix高阶篇 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.基礎概念

1.架構演進

在系統架構與設計的實踐中,從宏觀上可以總結為三個階段;

單體架構 :就是把所有的功能、模塊都集中到一個項目中,部署在一臺服務器上,從而對外提供服務(單體架構、單體服務、單體應用)。直白一點:就是只有一個項目,只有一個 war;

分布式架構 :就是把所有的功能、模塊拆分成不同的子項目,部署在多臺不同的服務器上,這些子項目相互協作共同對外提供服務。直白一點:就是有很多項目,有很多 wr 包,這些項目相互協作完成需要的功能,不是一個 war 能完成的,一個 war 包完成不了;

微服務架構 :分布式強調系統的拆分,微服務也是強調系統的拆分,微服務架構屬于分布式架構的范疇;

并且到目前為止,微服務并沒有一個統一的標準的定義

2.分布式和微服務區別?

分布式,就是將巨大的一個系統劃分為多個模塊,這一點和微服務是一樣的,都是要把系統進行拆分,部署到不同機器上,因為一臺機器可能承受不了這么大的訪問壓力,或者說要支撐這么大的訪問壓力需要采購一臺性能超級好的服務器其財務成本非常高,有這些預算完全可以采購很多臺普通的服務器了,分布式系統各個模塊通過接口進行數據交互,其實分布式也是一種微服務,因為都是把模塊拆分變為獨立的單元,提供接口來調用

它們的本質的區別體現在“目標”上,何為目標,就是你采用分布式架構或者采用微服務架構,你最終是為了什么,要達到什么目的?分布式架構的目標是什么?就是訪問量很大一臺機器承受不了,或者是成本問題,不得不使用多臺機器來完成服務的部署;而微服務的目標是什么?只是讓各個模塊拆分開來,不會被互相影響,比如模塊的升級或者出現 BUG 或者是重構等等都不要影響到其他模塊,微服務它是可以在一臺機器上部署;

3.什么是微服務?

簡單的說,微服務架構就是將一個完整的應用從數據存儲開始垂直拆分成多個不同的服務,每個服務都能獨立部署、獨立維護、獨立擴展,服務與服務間通過諸如 RESTful API 的方式互相調用。

4.服務治理

服務治理可以說是微服務架構中最為核心和基礎的模塊, 它主要用來實現各個微服務實例的自動化注冊與發現。 為什么我們在微服務架構中那么需要服務治理模塊呢?微服務系統沒有它會有什么不好的地方嗎?

在最初開始構建微服務系統的時候可能服務并不多, 我們可以通過做一些靜態配置來 完成服務的調用。 比如,有兩個服務 A 和 B, 其中服務 A 需要調用服務 B 來完成一個業務 操作時,為了實現服務 B 的高可用, 不論采用服務端負載均衡還是客戶端負載均衡, 都需 要手工維護服務 B 的具體實例清單。 但是隨著業務的發展, 系統功能越來越復雜, 相應的 微服務應用也不斷增加, 我們的靜態配置就會變得越來越難以維護。 并且面對不斷發展的業務, 我們的集群規模、 服務的位置 、 服務的命名等都有可能發生變化, 如果還是通過手 工維護的方式, 那么極易發生錯誤或是命名沖突等問題。 同時, 對于這類靜態內容的維護 也必將消耗大量的人力。

為了解決微服務架構中的服務實例維護問題, 產生了大量的服務治理框架和產品。 這 些框架和產品的實現都圍繞著服務注冊與服務發現機制來完成對微服務應用實例的自動化 管理。

5.服務注冊

在服務治理框架中, 通常都會構建一個注冊中心, 每個服務單元向注冊 中心登記自己提供的服務, 將主機與端口號、 版本號、 通信協議等一些附加信息告 知注冊中心, 注冊中心按服務名分類組織服務清單。 比如, 我們有兩個提供服務 A 的進程分別運行于 192.168.0.100:8000 和 192.168.0.101:8000 位置上, 另外還有三個提供服務 B 的進程分別運行千 192.168.0.100:9000、 192.168.0.101:9000、 192.168.0.102:9000 位置上。 當這些進程均啟動, 并向注冊中心注冊自己的服務之后, 注冊中心就會維護類似下面的一個服務清單。 另外, 服務注冊中心還需要以心跳的方式去監測清單中的服務是否可用, 若不可用 需要從服務清單中剔除, 達到排除故障服務的效果。

Spring Cloud 支持得最好的是 Nacos,其次是 Eureka,其次是 Consul,再次是 Zookeeper。

6.服務發現

服務消費者向注冊中心請求已經登記的服務列表,然后得到某個服務

由于在服務治理框架下運作, 服務間的調用不再通過指定具體的實例地 址來實現, 而是通過向服務名發起請求調用實現。 所以, 服務調用方在調用服務提 供方接口的時候, 并不知道具體的服務實例位置。 因此, 調用方需要向服務注冊中 心咨詢服務, 并獲取所有服務的實例清單, 以實現對具體服務實例的訪問。 比如, 現有服務 C 希望調用服務 A, 服務 C 就需要向注冊中心發起咨詢服務請求,服務注 冊中心就會將服務 A 的位置清單返回給服務 C, 如按上例服務 A 的情況,C 便獲得 了服務 A 的兩個可用位置 192.168.0.100:8000 和 192.168.0.101:8000。 當服務 C 要發起調用的時候,便從該清單中以某種輪詢策略取出一個位置來進行服 務調用,這就是后續我們將會介紹的客戶端負載均衡。 這里我們只是列舉了一種簡 單的服務治理邏輯, 以方便理解服務治理框架的基本運行思路。 實際的框架為了性 能等因素, 不會采用每次都向服務注冊中心獲取服務的方式, 并且不同的應用場景 在緩存和服務剔除等機制上也會有一些不同的實現策略。

7.什么是 Spring Cloud?

Spring Cloud 是一個基于 Spring Boot 實現的云應用開發工具,它為基于 JVM 的云應用開發中的配置管理、服務發現、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、分布式會話和集群狀態管理等操作提供了一種簡單的開發方式。

Spring Cloud 包含了多個子項目(針對分布式系統中涉及的多個不同開源產品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI 等項目。

Spring Cloud 為開發人員提供了一些工具用來快速構建分布式系統中的一些常見模式和解決一些常見問題(例如配置管理、服務發現、斷路器智能路由、微代理、控制總線、一次性令牌、全局鎖、領導選舉、分布式會話、群集狀態)。

8.微服務與 Spring-Cloud?

微服務只是一種項目的架構方式、架構理念,或者說是一種概念,就如同我們的 MVC 架構一樣

Spring Cloud 便是對這種架構方式的技術落地實現;

9.Spring Cloud 版本

為了避免大家對版本號的誤解,避免與子項目版本號混淆,所以 Spring Cloud 發布的版本是一個按照字母順序的倫敦地鐵站的名字(“天使”是第一個版本,"布里克斯頓”是第二個),字母順序是從 A-Z,目前最新穩定版本 Greenwich

SR3,當 Spring Cloud 里面的某些子項目出現關鍵性 bug 或重大更新,則發布序列將推出名稱以“.SRX”結尾的版本,其中“X”是一個數字,比如:Greenwich SRl、Greenwich SR2、Greenwich SR3;

Spring Cloud 是微服務開發的一整套解決方案,采用 Spring Cloud 開發,每個項目依然是使用 Spring Boot

版本

  • Hoxton
  • Greenwich
  • Finchley
  • Edgware
  • Dalston
  • Camden
  • Brixton
  • Angel

10.Spring Cloud 整體架構?

11.Spring Cloud 組件

它主要提供的模塊包括:

  • 服務發現(Eureka)
  • 斷路器(Hystrix)
  • 智能路有(Zuul)
  • 客戶端負載均衡(Ribbon)

12.Spring Cloud注解

  • @EnableEurekaServer: 用在springboot啟動類上,表示這是一個eureka服務注冊中心;
  • @EnableDiscoveryClient:用在springboot啟動類上,表示這是一個服務,可以被注冊中心找到;
  • @LoadBalanced:開啟負載均衡能力;
  • @EnableCircuitBreaker:用在啟動類上,開啟斷路器功能;
  • @HystrixCommand(fallbackMethod=”backMethod”):用在方法上,fallbackMethod指定斷路回調方法;
  • @EnableConfigServer:用在啟動類上,表示這是一個配置中心,開啟Config Server;
  • @EnableZuulProxy:開啟zuul路由,用在啟動類上;
  • @SpringCloudApplication:
    @SpringBootApplication
    @EnableDiscovertyClient
    @EnableCircuitBreaker
    分別是SpringBoot注解、注冊服務中心Eureka注解、斷路器注解。對于SpringCloud來說,這是每一微服務必須應有的三個注解,所以才推出了@SpringCloudApplication這一注解集合。
  • @ConfigurationProperties:Spring源碼中大量使用了ConfigurationProperties注解,比如server.port就是由該注解獲取到的,通過與其他注解配合使用,能夠實現Bean的按需配置。

該注解有一個prefix屬性,通過指定的前綴,綁定配置文件中的配置,該注解可以放在類上,也可以放在方法上。

二.eureka

1.什么是 eureka?

Eureka 服務治理體系中的三個核心角色: 服務注冊中心、 服務提供者以及服務消費者。

Spring Cloud Eureka, 使用 Netflix Eureka 來實現服務注冊與發現, 它既包含了服務端組件,也包含了客戶端組件,并且服務端與客戶端均采用 Java 編寫,所以 Eureka 主要適用 于通過 Java 實現的分布式系統,或是與 NM 兼容語言構建的系統。但是,由于 Eureka 服 務端的服務治理機制提供了完備的 RESTfulAPL 所以它也支持將非 Java 語言構建的微服 務應用納入 Eureka 的服務治理體系中來。只是在使用其他語言平臺的時候,需要自己來實 現 Euerka 的客戶端程序。不過慶幸的是,在目前幾個較為流行的開發平臺上,都已經有了 一些針對 Eureka 注冊中心的客戶端實現框架,比如.NET 平臺的 Steeltoe、 Node.js 的 euerkaj-sc-lient 等。

Eureka 服務端,我們也稱為服務注冊中心。它同其他服務注冊中心一樣,支持高可用 配置。它依托于強一致性提供良好的服務實例可用性,可以應對多種不同的故障場景。如 果 Eureka 以集群模式部署,當集群中有分片出現故障時,那么 Eureka 就轉入自我保護模 式。它允許在分片故障期間繼續提供服務的發現和注冊,當故障分片恢復運行時,集群中 的其他分片會把它們的狀態再次同步回來。以在 AWS 上的實踐為例,Netflix 推薦每個可 用的區域運行一個 Eureka 服務端,通過它來形成集群。不同可用區域的服務注冊中心通過 異步模式互相復制各自的狀態,這意味著在任意給定的時間點每個實例關于所有服務的狀 態是有細微差別的。

Eureka 客戶端,主要處理服務的注冊與發現??蛻舳朔胀ㄟ^注解和參數配置的方式, 嵌入在客戶端應用程序的代碼中,在應用程序運行時,Euerka 客戶端向注冊中心注冊自身 提供的服務并周期性地發送心跳來更新它的服務租約。同時,它也能從服務端查詢當前注 冊的服務信息并把它們緩存到本地并周期性地刷新服務狀態。

2.eureka 架構

  • Service Provider:暴露服務的服務提供方。
  • Service Consumer:調用遠程服務的服務消費方。
  • EureKa Server:服務注冊中心和服務發現中心。

3.eureka 保護機制

在沒有 Eureka 自我保護的情況下,如果 Eureka Server 在一定時間內沒有接收到某個微服務實例的心跳 I Eureka Server 將會注銷該實例,但是當發生網絡分區故障時,那么微服務與 Eureka Server 之間將無法正常通信,以上行為可能變得非常危險了因為微服務本身其實是正常的此時不應該注銷這個微服務,如果沒有自我保護機制,那么 Eureka Server 就會將此服務注銷掉。

當 Eureka Server 節點在短時間內丟失過多客戶端時(可能發生了網絡分區故障),那么就會把這個微服務節點進行保護。一旦進入自我保護模式,Eureka Server 就會保護服務注冊表中的信息,不刪除服務注冊表中的數據(也就是不會注銷任何微服務)。當網絡故障恢復后,該 Eureka Server 節點會再自動退出自我保護模式。

所以,自我保護模式是一種應對網絡異常的安全保護措施,它的架構哲學是寧可同時保留所有微服務(健康的微服務和不健康的微服務都會保留),也不盲目注銷任何健康的微服務,使用自我保護模式,可以讓 Eureka 集群更加的健壯.穩定

#禁用eurekd目我保護 eureka.server.enable-self-preservation=false

4.Eureka 與 Zookeeper?

著名的 CAP 理論指出,一個分布式系統不可能同時滿足 C(一致性街)、A(可用性)和 P(分區容錯性)。

由于分區容錯性在是分布式系統中必須要保證的,因此我們只能在 A 和 C 之間進行權衡,在此 Zookeeper 保證的是 CP,而 Eureka 則是 AP。

Eureka保證AP

Eureka 優先保證可用性,Eureka 各個節點是平等的,某節點異常,剩余的節點依然可以提供注冊和服務查詢功能.

在向某個 Eureka 注冊時,如果發現連接失敗,則只要有一臺 Eureka 還在,就能保證注冊服務可用,但是數據可能不是最新的(不保證強一致性)。

Zookeeper保證CP

在 ZooKeeper 中,當 master 節點因為網絡故障與其他節點失去聯系時,剩余節點會重新進行 leader 選舉,但是問題在于,選舉 leader 需要一定時間,且選舉期間整個 ZooKeeper 集群都是不可用的,這就導致在選舉期間注冊服務癱瘓。在云部署的環境下,因網絡問題使得 ZooKeeper 集群失去 master 節點是大概率事件,雖然服務最終能夠恢復,但是在選舉時間內導致服務注冊長期不可用是難以容忍的。

5.Eureka 高可用集群?

相互注冊,去中心化

#端口號 server:port: 8769spring:application:name: eurka-servereureka:instance:hostname: eureka8769client:register-with-eureka: false #由于該應用為注冊中心,所以設置 為 false, 代表不向注冊中心注冊自己。fetch-registry: false #由于注冊中心的職責就是維護服務實例, 它并不需要去檢索服務, 所以也設置為 false。serviceUrl:defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/

6.eureka 三要素?

在 “服務治理”示例中, 我們的示例雖然簡單, 但是麻雀雖小、 五臟俱全。 它已經包含了整個 Eureka 服務治理基礎架構的三個核心要素。

  • 服務注冊中心: Eureka 提供的服務端, 提供服務注冊與發現的功能, 也就是我們實現的 eureka-server。
  • 服務提供者:提供服務的應用, 可以是 SpringBoot 應用, 也可以是其他技術平臺且遵循 Eureka 通信機制的應用。它將自己提供的服務注冊到 Eureka, 以供其他應用發現, 也就是我們實現的 spring-boot-service 應用。
  • 服務消費者:消費者應用從服務注冊中心獲取服務列表, 從而使消費者可以知道去何處調用其所需要的服務,在面我們使用了 Ribbon 來實現服務消費,另外后續還會介紹使用 Feign 的消費方式。 很多時候, 客戶端既是服務提供者也是服務消費者。

7.Eureka 本地緩存

8.服務提供者

1.服務注冊

將服務所在主機、端口、版本號、通信協議等信息登記到注冊中心上;

“服務提供者” 在啟動的時候會通過發送 REST 請求的方式將自己注冊到 EurekaServer 上, 同時帶上了自身服務的一些元數據信息。Eureka Server 接收到這個 REST 請求之后, 將元數據信息存儲在一個雙層結構 Map 中, 其中第一層的 key 是服務名, 第二層的 key 是 具體服務的實例名。(我們可以回想一下之前在實現 Ribbon 負載均衡的例子中, Eureka 信 息面板中一個服務有多個實例的清況, 這些內容就是以這樣的雙層 Map 形式存儲的)

在服務注冊時, 需要確認一下 eureka.client.register-with-eureka=true 參數是否正確, 該值默認為 true。若設置為 false 將不會啟動注冊操作。

boolean register() throws Throwable {logger.info("DiscoveryClient_{}: registering service...", this.appPathIdentifier);EurekaHttpResponse httpResponse;try {httpResponse = this.eurekaTransport.registrationClient.register(this.instanceInfo);} catch (Exception var3) {logger.warn("DiscoveryClient_{} - registration failed {}", new Object[]{this.appPathIdentifier, var3.getMessage(), var3});throw var3;}if (logger.isInfoEnabled()) {logger.info("DiscoveryClient_{} - registration status: {}", this.appPathIdentifier, httpResponse.getStatusCode());}return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode(); }

2.服務同步

如架構圖中所示, 這里的兩個服務提供者分別注冊到了兩個不同的服務注冊中心上, 也就是說, 它們的信息分別被兩個服務注冊中心所維護。 此時, 由于服務注冊中心之間因互相注冊為服務, 當服務提供者發送注冊請求到一個服務注冊中心時, 它會將該請求轉發給集群中相連的其他注冊中心,從而實現注冊中心之間的服務同步。通過服務同步,兩個服務提供者的服務信息就可以通過這兩臺服務注冊中心中的任意一臺獲取到。

3.服務續約

在注冊完服務之后,服務提供者會維護一個心跳用來持續告訴 Eureka Server: "我還活著”,以防止 Eureka Server 的 “剔除任務 ” 將該服務實例從服務列表中排除出去,我們稱該操作為服務續約(Renew)。

關千服務續約有兩個重要屬性,我們可以關注并根據需要來進行調整:

而 “服務獲取” 的邏輯在獨立的一個 W 判斷中, 其判斷依據就是我們之前所提到的 eureka.clien.fetch-registry=true 參數, 它默認為 true, 大部分情況下我們 不需要關心。 為了定期更新客戶端的服務清單, 以保證客戶端能夠訪問確實健康的服務實 例, “服務獲取” 的請求不會只限于服務啟動, 而是一個定時執行的任務, 從源碼中我們可 以看到任務運行中的 registryFetchintervalSeconds 參數對應的就是之前所提到的 eureka.client.registry-fetch-interval-seconds=30 配置參數, 它默認為 30 秒。

eureka.instance.lease-renewal-interval-in-seconds=30 eureka.instance.lease-expiration-duration-in-seconds=90 #參數用于定義服務續約任務的調用間隔時間,默認為30秒。 eureka.instance.lease-renewal-interval-in-seconds #參數用于定義服務失效的時間,默認為90秒。 eureka.instance.lease-expiration-duration-in-seconds private void initScheduledTasks() {int renewalIntervalInSecs;int expBackOffBound;if (this.clientConfig.shouldFetchRegistry()) {renewalIntervalInSecs = this.clientConfig.getRegistryFetchIntervalSeconds();expBackOffBound = this.clientConfig.getCacheRefreshExecutorExponentialBackOffBound();this.scheduler.schedule(new TimedSupervisorTask("cacheRefresh", this.scheduler, this.cacheRefreshExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.CacheRefreshThread()), (long)renewalIntervalInSecs, TimeUnit.SECONDS);}if (this.clientConfig.shouldRegisterWithEureka()) {renewalIntervalInSecs = this.instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();expBackOffBound = this.clientConfig.getHeartbeatExecutorExponentialBackOffBound();logger.info("Starting heartbeat executor: renew interval is: {}", renewalIntervalInSecs);this.scheduler.schedule(new TimedSupervisorTask("heartbeat", this.scheduler, this.heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.HeartbeatThread()), (long)renewalIntervalInSecs, TimeUnit.SECONDS);this.instanceInfoReplicator = new InstanceInfoReplicator(this, this.instanceInfo, this.clientConfig.getInstanceInfoReplicationIntervalSeconds(), 2);this.statusChangeListener = new StatusChangeListener() {public String getId() {return "statusChangeListener";}public void notify(StatusChangeEvent statusChangeEvent) {if (InstanceStatus.DOWN != statusChangeEvent.getStatus() && InstanceStatus.DOWN != statusChangeEvent.getPreviousStatus()) {DiscoveryClient.logger.info("Saw local status change event {}", statusChangeEvent);} else {DiscoveryClient.logger.warn("Saw local status change event {}", statusChangeEvent);}DiscoveryClient.this.instanceInfoReplicator.onDemandUpdate();}};if (this.clientConfig.shouldOnDemandUpdateStatusChange()) {this.applicationInfoManager.registerStatusChangeListener(this.statusChangeListener);}this.instanceInfoReplicator.start(this.clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());} else {logger.info("Not registering with Eureka server per configuration");}}

9.服務消費者

1.獲取服務

到這里,在服務注冊中心已經注冊了一個服務,并且該服務有兩個實例。 當我們啟動 服務消費者的時候,它會發送一個 REST 請求給服務注冊中心,來獲取上面注冊的服務清 單。為了性能考慮,EurekaServer 會維護一份只讀的服務清單來返回給客戶端,同時該緩 存清單會每隔 30 秒更新一次。

獲取服務是服務消費者的基礎,所以必須確保 eureka.client.fetch-registry= true 參數沒有被修改成 false, 該值默認為 true。若希望修改緩存清單的更新時間,可 以通過 eureka.client.registry-fetch-interval-seconds=30 參數進行修改, 該參數默認值為 30, 單位為秒。

2.服務調用

服務消費者在獲取服務清單后,通過服務名可以獲得具體提供服務的實例名和該實例的元數據信息。 因為有這些服務實例的詳細信息, 所以客戶端可以根據自己的需要決定具 體調用哪個實例,在 ribbon 中會默認采用輪詢的方式進行調用,從而實現客戶端的負載均衡。

對于訪問實例的選擇,Eureka 中有 Region 和 Zone 的概念, 一個 Region 中可以包含多個 Zone, 每個服務客戶端需要被注冊到一個 Zone 中, 所以每個客戶端對應一個 Region 和一個 Zone。 在進行服務調用的時候,優先訪問同處一個 Zone 中的服務提供方, 若訪問不到,就 訪問其他的 Zone, 更多關于 Region 和 Zone 的知識,我們會在后續的源碼解讀中介紹。

3.服務下線

在系統運行過程中必然會面臨關閉或重啟服務的某個實例的情況, 在服務關閉期間, 我們自然不希望客戶端會繼續調用關閉了的實例。 所以在客戶端程序中, 當服務實例進行正常的關閉操作時, 它會觸發一個服務下線的 REST 請求給 Eureka Server, 告訴服務注冊中心:“我要下線了”。服務端在接收到請求之后, 將該服務狀態置為下線(DOWN), 并把該下線事件傳播出去。

10.服務注冊中心

1.失效剔除

有些時候, 我們的服務實例并不一定會正常下線, 可能由于內存溢出、 網絡故障等原因使得服務不能正常工作, 而服務注冊中心并未收到 “服務下線” 的請求。 為了從服務列表中將這些無法提供服務的實例剔除,EurekaSrevre 在啟動的時候會創建一個定時任務, 默認每隔一段時間(默認為 60 秒) 將當前清單中超時(默認為 90 秒)沒有續約的服務剔除出去。

2.自我保護

當我們在本地調試基于 Eurkea 的程序時, 基本上都會碰到這樣一個問題, 在服務注冊中心的信息面板中出現類似下面的紅色警告信息:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

實際上, 該警告就是觸發了 EurekaServer 的自我保護機制。 之前我們介紹過, 服務注 冊到 EurekaSrevre 之后,會維護一個心跳連接,告訴 EurekaServer 自己還活著。EurkeaServer 在運行期間,會統計心跳失敗的比例在 15 分鐘之內是否低于 85%,如果出現低于的情況(在 單機調試的時候很容易滿足, 實際在生產環境上通常是由于網絡不穩定導致), Eureka Server 會將當前的實例注冊信息保護起來, 讓這些實例不會過期, 盡可能保護這些注冊信 息。 但是, 在這段保護期間內實例若出現問題, 那么客戶端很容易拿到實際已經不存在的 服務實例, 會出現調用失敗的清況, 所以客戶端必須要有容錯機制, 比如可以使用請求重 試、 斷路器等機制。

由于本地調試很容易觸發注冊中心的保護機制, 這會使得注冊中心維護的服務實例不那么準確。 所以, 我們在本地進行開發的時候, 可以使用參數來關閉保護機制, 以確保注冊中心可以將不可用的實例正確剔除。

eureka.server.enableself-preservation =false

11.eureka 源碼

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({EnableDiscoveryClientImportSelector.class}) public @interface EnableDiscoveryClient {boolean autoRegister() default true; } //服務發現的核心類 package com.netflix.discovery;

package org.springframework.cloud.netflix.eureka;

org.springframework.cloud.client.discovery.DiscoveryClient 是 SpringCloud 的接口, 它定義了用來發現服務的常用抽象方法, 通過該接口可以有效地 屏蔽服務治理的實現細節, 所以使用 SpringCloud 構建的微服務應用可以方便地切換不同服務治理框架, 而不改動程序代碼, 只需要另外添加一些針對服務治理框架的配置即可。 org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient 是對該接口的實現, 從命名來判斷, 它實現的是對 Eureka 發現服務的封裝。 所以 EurekaDiscoveryClient 依賴了 Netflix Eureka 的 com.netflix.discovery. EurekaClient 接口, EurekaClient 繼承了 LookupService 接口, 它們都是 Netflix 開源包中的內容, 主要定義了針對 Eureka 的發現服務的抽象方法, 而真正實現發現服務的 則是 Netflix 包中的 com.netftx.discovery.DiscoveryClient 類。

12.DiscoveryClient

DiscoveryClient 這個類用于幫助與 Eureka Server 互相協作。
EurekaClient 負責下面的任務:

  • 向 Eureka Server 注冊服務實例

  • 向 Eureka Server 服務租約

  • 當服務關閉期間, 向 Eureka Server 取消租約

  • 查詢 Eureka Server 中的服務實例列表

13.什么是 Region?

客戶端依次加載了兩個內容, 第一個是 Region, 第二個 是 Zone, 從其加載邏輯上我們可以判斷它們之間的關系:

通過 getRegion 函數, 我們可以看到它從配置中讀取了一個 Region 返回, 所以 一 個微服務應用只可以屬于一個 Region, 如果不特別配置, 默認為 defaul。若我們要 自己設置, 可以通過 eureka.client.region 屬性來定義。

public static String getRegion(EurekaClientConfig clientConfig) {String region = clientConfig.getRegion();if (region == null) {region = "default";}region = region.trim().toLowerCase();return region; }

14.什么是 Zone?

通過 getAvailabilityZones 函數, 可以知道當我們沒有特別為 Region 配置 Zone 的時候, 將默認采用 defaultZone, 這也是我們之前配置參數 eureka.client.serviceUrl.defaultZone 的由來。 若要為應用指定 Zone, 可以通過 eureka.client.availability-zones 屬性來進行設置。從該函數的 return 內容, 我們可以知道 Zone 能夠設置多個, 并且通過逗號分隔來配置。 由此, 我們可以判斷 Region 與 Zone 是一對多的關系

public String[] getAvailabilityZones(String region) {String value = (String)this.availabilityZones.get(region);if (value == null) {value = "defaultZone";}return value.split(",");}

當我們在微服務應用中使用 Ribbon 來實現服務調用時,對于 Zone 的設置可以在負載 均衡時實現區域親和特性: Ribbon 的默認策略會優先訪問同客戶端處于一個 Zone 中的服 務端實例,只有當同一個 Zone 中沒有可用服務端實例的時候才會訪問其他 Zone 中的實例。 所以通過 Zone 屬性的定義,配合實際部署的物理結構,我們就可以有效地設計出對區域性 故障的容錯集群。

15.服務消費基礎

服務消費基礎實現方式,不是傳統實現方式

@RestController public class DcController {@AutowiredLoadBalancerClient loadBalancerClient;@AutowiredRestTemplate restTemplate;@GetMapping("/consumer")public String dc() {ServiceInstance serviceInstance = loadBalancerClient.choose("eureka-server");String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/dc";System.out.println(url);return restTemplate.getForObject(url, String.class);} }

可以看到這里,我們注入了LoadBalancerClient和RestTemplate,并在/consumer接口的實現中,先通過loadBalancerClient的choose函數來負載均衡的選出一個eureka-client的服務實例,這個服務實例的基本信息存儲在ServiceInstance中,然后通過這些對象中的信息拼接出訪問/dc接口的詳細地址,最后再利用RestTemplate對象實現對服務提供者接口的調用。

16.什么是 consul?

consul 特性:

  • 服務發現
  • 健康檢查
  • Key/Value 存儲
  • 多數據中心

服務發現的接口DiscoveryClient是 Spring Cloud 對服務治理做的一層抽象,所以可以屏蔽 Eureka 和 Consul 服務治理的實現細節,我們的程序不需要做任何改變,只需要引入不同的服務治理依賴,并配置相關的配置屬性就能輕松的將微服務納入 Spring Cloud 的各個服務治理框架中。

由于 Consul 自身提供了服務端,所以我們不需要像之前實現 Eureka 的時候創建服務注冊中心,直接通過下載 consul 的服務端程序就可以使用。

三.Ribbon 和 feign

1.什么是負載均衡?

載均和分為硬件負載均衡和軟件負載均衡:

  • 硬件負載均衡:比如 F5、深信服、Array 等;
  • 軟件負載均衡:比如 Nginx、LVS、HAProxy 等;

2.服務端負載均衡

3.什么是 Ribbon?

Ribbon 是 Netfliⅸ 公司發布的開源項目(組件、框架、jar 包),主要功能是提供客戶端的軟件負載均衡算法,它會從 eureka 中獲取一個可用的服務端清單通過心跳檢測來易剔除故的服務端節點以保證清單中都是可以正常訪問的服務端節點。

當客戶端發送請求,則 ribbon 負載均衡器按某種算法(比如輪詢、權重、最小連接數等從維護的可用服務端清單中取出一臺服務端的地址然后進行請求

Ribbon 是一個基于 HTTP 和 TCP 客戶端的負載均衡器。Ribbon 非常簡單,可以說就是一個 jar 包,這個 jar 包實現了負載均衡算法,Spring Cloud 對 Ribbon 做了二次封裝,可以讓我們使用 RestTemplate 的服務請求,自動轉換成客戶端負載均衡的服務調用。

Ribbon 可以在通過客戶端中配置的 ribbonServerList 服務端列表去輪詢訪問以達到均衡負載的作用。當 Ribbon 與 Eureka 聯合使用時,ribbonServerList 會被 DiscoveryEnabledNIWSServerList 重寫,擴展成從 Eureka 注冊中心中獲取服務端列表。同時它也會用 NIWSDiscoveryPing 來取代 IPing,它將職責委托給 Eureka 來確定服務端是否已經啟動。

Ribbon 支持多種負載均衡算法,還支持自定義的負載均衡算法。

使用 Ribbon 實現負載均衡的調用(spring cloud -> 封裝 ribbon + eureka + restTemplate)

Ribbon 默認是采用懶加載,即第一次訪問時才會去創建 LoadBalanceClient,請求時間會很長。

而饑餓加載則會在項目啟動時創建,降低第一次訪問的耗時,通過下面配置開啟饑餓加載:

ribbon:eager-load:enabled: trueclients: user

4.IRule

public interface IRule {Server choose(Object var1);void setLoadBalancer(ILoadBalancer var1);ILoadBalancer getLoadBalancer(); }

5.ILoadBalancer

一個服務對應一個 LoadBalancer,一個 LoadBalancer 只有一個 Rule,LoadBalancer 記錄服務的注冊地址,Rule 提供從服務的注冊地址中找出一個地址的規則。

通過 LoadBalancerIntercepor 攔截器,可以攔截請求 url 和服務 id,然后結合 IRule 進行路由處理

public interface ILoadBalancer {void addServers(List<Server> var1);Server chooseServer(Object var1);void markServerDown(Server var1);/** @deprecated */@DeprecatedList<Server> getServerList(boolean var1);List<Server> getReachableServers();List<Server> getAllServers(); }

6.負載均衡策略

Ribbon 提供七種負載均衡策略,默認的負載均衡策略是輪訓策略。RoundRobinRule

public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {private static final IRule DEFAULT_RULE = new RoundRobinRule(); }

通過 choose 方法選擇指定的算法。完整的算法包含如下:

策略名稱解釋描述
RandomRule隨機算法實現
RoundRobinRule輪詢負載均衡策略,依次輪詢所有可用服務器列表
RetryRule先按照 RoundRobinRule 策略獲取服務,如果獲取服務失敗會在指定時間內重試
AvaliabilityFilteringRule過濾掉那些因為一直連接失敗的被標記為 circuit tripped 的后端 server,并過濾掉那些高并發的的后端 server(active connections 超過配置的閾值)
BestAvailableRule會先過濾掉由于多次訪問故障二處于斷路器跳閘狀態的服務,然后選擇一個并發量最小的服務
WeightedResponseTimeRule根據響應時間分配一個 weight,響應時間越長,weight 越小,被選中的可能性越低
ZoneAvoidanceRule復合判斷 server 所在區域的性能和 server 的可用性選擇 server,新版本默認的負載均衡策略
  • RoundRobinRule: 輪詢策略。Ribbon 默認采用的策略。若經過一輪輪詢沒有找到可用的 provider,其最多輪詢 10 輪(代碼中寫死的,不能修改)。若還未找到,則返回 null。

  • RandomRule: 隨機策略,從所有可用的 provider 中隨機選擇一個。。

  • RetryRule: 重試策略。先按照 RoundRobinRule 策略獲取 server,若獲取失敗,則在指定的時限內重試。默認的時限為 500 毫秒。

  • BestAvailableRule: 最可用策略。選擇并發量最小的 provider,即連接的消費者數量最少的 provider。其會遍歷服務列表中的每一個 server,選擇當前連接數量 minimalConcurrentConnections 最小的 server。

  • AvailabilityFilteringRule: 可用過濾算法。該算法規則是:過濾掉處于熔斷狀態的 server 與已經超過連接極限的 server,對剩余 server 采用輪詢策略。

7.負載均衡原理

Ribbon 負載均衡基本原理:
1、Ribbon 會攔截 Eureka Client 客戶端發出的 http 請求,獲得服務名(userservice)
2、從 Eureka 中拉取動態服務列表(8081、8082。。。。。)
3、從里面選一個服務(如 8081)出來(輪詢、隨機等算法)
4、去調用這個服務

8.ribbon組件

主要有以下組件:

  • IRule,定義如何選擇規則和策略
  • IPing,接口定義了我們如何“ping”服務器檢查是否活著
  • ServerList,定義了獲取服務器的列表接口,存儲服務列表
  • ServerListFilter,接口允許過濾配置或動態獲得的候選列表服務器
  • ServerListUpdater,接口使用不同的方法來做動態更新服務器列表
  • IClientConfig,定義了各種api所使用的客戶端配置,用來初始化ribbon客戶端和負載均衡器,默認實現是DefaultClientConfigImpl ILoadBalancer, 接口定義了各種軟負載,動態更新一組服務列表及根據指定算法從現有服務器列表中選擇一個服務

@LoadBalanced注解,開啟客戶端的負載均衡:

  • RestTemplate
  • LoadBalancerAutoConfiguration
    • @ConditionalOnClass(RestTemplate.class)
    • @ConditionalOnBean(LoadBalancerClient.class)
  • SmartInitializingSingleton 加載@LoadBalanced注解的RestTemplate到RestTemplateCustomizer
  • LoadBalancerInterceptor攔截器攔截RestTemplate請求

9.遠程調用有哪些?

  • Httpclient(apache)
  • Httpurlconnection (jdk)
  • restTemplate (spring)
  • OkHttp(android)
  • feign(Spring cloud)

10.什么是 Feign?

Feign 是一個聲明式的 Web Service 客戶端,它使得編寫 Web Serivce 客戶端變得更加簡單。我們只需要使用 Feign 來創建一個接口并用注解來配置它既可完成。它具備可插拔的注解支持,包括 Feign 注解和 JAX-RS 注解。Feign 也支持可插拔的編碼器和解碼器。Spring Cloud 為 Feign 增加了對 Spring MVC 注解的支持,還整合了 Ribbon 和 Eureka 來提供均衡負載的 HTTP 客戶端實現。

Feign 在Ribbon+RestTemplate 的基礎上做了進一步封裝,在Feign 封裝之后,我們只需創建一個接口并使用注解的方式來配置,即可完成對服務提供方的接口綁定簡化了使用 Ribbon + RestTemplate 的調用,自動封裝服務調用客戶端.

Feign 中也使用 Ribbon,自動集成了 ribbon

11.feignclient 冪等性

Retryer是重試器,其實現方法有兩種,第一種是系統默認實現方式,第二種是可以自定義重試器,一般少用,通過默認實現重試類Default可以看到其構造函數中的重試次數為5。

public Default() {this(100, SECONDS.toMillis(1), 5); }public Default(long period, long maxPeriod, int maxAttempts) {this.period = period;this.maxPeriod = maxPeriod;this.maxAttempts = maxAttempts;this.attempt = 1; }

因此解決Feign調用的冪等性問題最簡單也就最常用的就是讓Feign不重試。

12.ip 不能訪問

使用了@LoadBalanced 注解后不能再使用 192.168.28.1(ip)調用,必須要使用注冊中心中注冊的服務名稱

所以在使用 RestTemplate 的時候,有些場景下我們只是單純的用 ip 進行調用(如調用第三方接口服務),此時的 RestTemplate 就不能夠加@LoadBanlanced 注解。還有一種辦法是直接在需要使用 RestTemplate 的地方,直接 new 一個新的 RestTemplate 對象。如下

public void test(){RestTemplate restTemplate = new RestTemplate();//這里的接口地址就可以直接放協議+ip+端口,原理與上面一樣restTemplate.exchange("接口地址",xxx,xxx,xxx); }

13.feign 超時

Spring Cloud 中 Feign 客戶端是默認開啟支持 Ribbon 的,最重要的兩個超時就是連接超時 ConnectTimeout 和讀超時 ReadTimeout,在默認情況下,也就是沒有任何配置下,Feign 的超時時間會被 Ribbon 覆蓋,兩個超時時間都是 1 秒。

#ribbon配置 ribbon:#建立連接超時時間ConnectTimeout: 5000#建立連接之后,讀取響應資源超時時間ReadTimeout: 5000#Feign配置 feign:client:config:#這里填具體的服務名稱(也可以填default,表示對所有服務生效)app-order:#connectTimeout和readTimeout這兩個得一起配置才會生效connectTimeout: 5000readTimeout: 5000

四.hystrix

1.什么是 Hystrix?

在 Spring Cloud 中使用了 Hystrix 來實現斷路器的功能。Hystrix 是 Netflix 開源的微服務框架套件之一,該框架目標在于通過控制那些訪問遠程系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。Hystrix 具備擁有回退機制和斷路器功能的線程和信號隔離,請求緩存和請求打包,以及監控和配置等功能。

Hystrix 原理是命令模式,在遇到不同的情況下,請求 fallback,降級處理

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @EnableCircuitBreaker public @interface EnableHystrix { }

2.Hystrix 有哪些功能?

核心功能:

  • 超時
  • 異常
  • 限流

斷路器的作用

  • 防止單個服務的故障導致器依賴和相關的服務容器的線程資源被耗盡:
  • 減少負載,并負責通過請求的快速失敗功能而不是讓請求進行排隊.
  • 盡可能提供服務降級的功能,以免用戶免受故障影響
  • 使用隔離技術來限制某個服務出現問題所帶來的影響
  • 盡可能提供實時監控信息,提供監控和警報來優化發現故障的時間
  • 允許使用配置修改相關的參數(如請求超時時可以觸發熔斷)
  • 對服務調用消費者內部的故障進行保護,而不僅僅是在網絡流量上進行保護降級,限流
  • 一個簡單的場景就是家里的保險絲,當電流過大時保險絲熔斷,使得家里的其他電器不至于造成大規模的損壞:
    在微服務中,當大量請求到達產品微服務,這會導致其服務響應變得緩慢,或者因為內存不足等原因使得服務器出現宕機或者數據庫出現問題;

    另一個原因,當一個微服務中有很多請求時,會導致他調用其他微服務的時候(正常的服務線程)造成積壓,產生雪崩;

    3.Hystrix 超時配置

    #開啟feign開始hystrix的支持 feign:hystrix:enabled: truehystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 5000 #hystrix超時時間timeout:enabled: true #開啟hystrix超時管理 ribbon:ReadTimeout: 2000 #請求超時時間http:client:enabled: true #開啟ribbon超時管理ConnectTimeout: 2000 #連接超時時間
    • Dalston 版本之后默認關閉,注意開啟 feign 的 hystrix 的功能
    • ribbon 和 hystrix 都要設置,誰小以誰為準

    4.熔斷降級

    • 可以監聽你的請求有沒有超時;(默認是 1 秒,時間可以改)
    • 異?;驁箦e了可以快速讓請求返回,不會一直等待;(避免線程累積)
    • 當的系統馬上迎來大量的并發(雙十一秒殺這種或者促銷活動)

    此時如果系統承載不了這么大的并發時,可以考慮先關閉一些不重要的微服務(在降級方法中返回一個比較友好的信息),把資源讓給核心微服務,待高峰流量過去,再開啟回來。

    5.服務限流

    通過 2 種方式進行限流

    • 線程數限制
    • 信號量限制

    限流配置,通過限制線程數進行限流,限流就是限制你某個微服務的使用量(可用線程),

    hystriⅸ 通過線程池的方式來管理微服務的調用,它默認是一個線程池(大小 10 個)管理你的所有微服務,你可以給某個微服務開辟新的線程池.

    @HystrixCommand(fallbackMethod = "addServiceFallback",commandProperties = {@HystrixProperty(name = "execution.timeout.enabled", value = "true"),@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "6000")},threadPoolProperties = {@HystrixProperty(name = "coreSize", value = "2"),@HystrixProperty(name = "maxQueueSize", value = "1"),@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")} )
    • commandProperties 可以配置 hystrix 的各種配置
    • hreadPoolProperties 屬性用于控制線程池的行為,要求為我們建立一個大小為 coreSize 的,且在之前創建一個隊列的線程池,隊列大小為 maxQueueSize 對應的 value 的值
    • 這個隊列的作用是:控制在線程池中線程繁忙時允許堵塞的請求數(即 value 值),一旦請求數超過了隊列大小,對線程池的任何請求都將失敗,直到隊列中有空間為止。此外,對于 maxQueueSize 的值也有說明,當 value=-1 時,則將使用 Java SynchronousQueue 來保存所有傳入的請求,同步隊列本質上會強制要求正在處理中的請求數量永遠不要超過線程池中的可用數量;將 maxQueueSize 設置為大于 1 的值將導致 Hystrix 使用 Java LinkedBlockingQueue。這使得即使所有的線程都忙于處理請求,也能對請求進行排隊。

    6.commandProperties

    Command 屬性主要用來控制 HystrixCommand 命令的行為,它主要分下面的類別:

    • Execution:用來控制 HystrixCommand.run()的執行
      • execution.isolation.strategy:該屬性用來設置 HystrixCommand.run()執行的隔離策略。默認為 THREAD
      • execution.isolation.thread.timeoutInMilliseconds:該屬性用來配置 HystrixCommand 執行的超時時間,單位為毫秒。
      • execution.timeout.enabled:該屬性用來配置 HystrixCommand.run()的執行是否啟用超時時間。默認為 true。
      • execution.isolation.thread.interruptOnTimeout:該屬性用來配置當 HystrixCommand.run()執行超時的時候是否要它中斷。
      • execution.isolation.thread.interruptOnCancel:該屬性用來配置當 HystrixCommand.run()執行取消時是否要它中斷。
      • execution.isolation.semaphore.maxConcurrentRequests:當 HystrixCommand 命令的隔離策略使用信號量時,該屬性用來配置信號量的大小。當最大并發請求達到該設置值時,后續的請求將被拒絕。
    • Fallback:用來控制 HystrixCommand.getFallback()的執行
      • fallback.isolation.semaphore.maxConcurrentRequests:該屬性用來設置從調用線程中允許 HystrixCommand.getFallback()方法執行的最大并發請求數。當達到最大并發請求時,后續的請求將會被拒絕并拋出異常。
      • fallback.enabled:該屬性用來設置服務降級策略是否啟用,默認是 true。如果設置為 false,當請求失敗或者拒絕發生時,將不會調用 HystrixCommand.getFallback()來執行服務降級邏輯。
    • Circuit Breaker:用來控制 HystrixCircuitBreaker 的行為。
      • circuitBreaker.enabled:確定當服務請求命令失敗時,是否使用斷路器來跟蹤其健康指標和熔斷請求。默認為 true。
      • circuitBreaker.requestVolumeThreshold:用來設置在滾動時間窗中,斷路器熔斷的最小請求數。例如,默認該值為 20 的時候,如果滾動時間窗(默認 10 秒)內僅收到 19 個請求,即使這 19 個請求都失敗了,斷路器也不會打開。
      • circuitBreaker.sleepWindowInMilliseconds:用來設置當斷路器打開之后的休眠時間窗。休眠時間窗結束之后,會將斷路器設置為“半開”狀態,嘗試熔斷的請求命令,如果依然時候就將斷路器繼續設置為“打開”狀態,如果成功,就設置為“關閉”狀態。
      • circuitBreaker.errorThresholdPercentage:該屬性用來設置斷路器打開的錯誤百分比條件。默認值為 50,表示在滾動時間窗中,在請求值超過 requestVolumeThreshold 閾值的前提下,如果錯誤請求數百分比超過 50,就把斷路器設置為“打開”狀態,否則就設置為“關閉”狀態。
      • circuitBreaker.forceOpen:該屬性默認為 false。如果該屬性設置為 true,斷路器將強制進入“打開”狀態,它會拒絕所有請求。該屬性優于 forceClosed 屬性。
      • circuitBreaker.forceClosed:該屬性默認為 false。如果該屬性設置為 true,斷路器強制進入“關閉”狀態,它會接收所有請求。如果 forceOpen 屬性為 true,該屬性不生效。
    • Metrics:該屬性與 HystrixCommand 和 HystrixObservableCommand 執行中捕獲的指標相關。
      • metrics.rollingStats.timeInMilliseconds:該屬性用來設置滾動時間窗的長度,單位為毫秒。該時間用于斷路器判斷健康度時需要收集信息的持續時間。斷路器在收集指標信息時會根據設置的時間窗長度拆分成多個桶來累計各度量值,每個桶記錄了一段時間的采集指標。例如,當為默認值 10000 毫秒時,斷路器默認將其分成 10 個桶,每個桶記錄 1000 毫秒內的指標信息。
      • metrics.rollingStats.numBuckets:用來設置滾動時間窗統計指標信息時劃分“桶”的數量。默認值為 10。
      • metrics.rollingPercentile.enabled:用來設置對命令執行延遲是否使用百分位數來跟蹤和計算。默認為 true,如果設置為 false,那么所有的概要統計都將返回-1。
      • metrics.rollingPercentile.timeInMilliseconds:用來設置百分位統計的滾動窗口的持續時間,單位為毫秒。
      • metrics.rollingPercentile.numBuckets:用來設置百分位統計滾動窗口中使用桶的數量。
      • metrics.rollingPercentile.bucketSize:用來設置每個“桶”中保留的最大執行數。
      • metrics.healthSnapshot.intervalInMilliseconds:用來設置采集影響斷路器狀態的健康快照的間隔等待時間。
    • Request Context:涉及 HystrixCommand 使用 HystrixRequestContext 的設置。
      • requestCache.enabled:用來配置是否開啟請求緩存。
      • requestLog.enabled:用來設置 HystrixCommand 的執行和事件是否打印到日志的 HystrixRequestLog 中。

    7.threadPoolProperties

    threadPoolProperties = {@HystrixProperty(name = "coreSize",value = "2"),@HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize",value="true"),@HystrixProperty(name = "maximumSize",value="2"),@HystrixProperty(name = "maxQueueSize",value="2")},
    • 如果請求量少,達不到 coreSize,通常會使用核心線程來執行任務。

    • 如果設置了 maxQueueSize,當請求數超過了 coreSize, 通常會把請求放到 queue 里,待核心線程有空閑時消費。

    • 如果 queue 長度無法滿足存儲請求,則會創建新線程執行直到達到 maximumSize 最大線程數,多出核心線程數的線程會在空閑時回收。

    8.常用限流方式?

    • Hystriⅸ 限流
    • Nginx
    • Redis+Lua
    • Sentinel
    • 基于限流算法自己實現(令牌桶、漏桶慎法)

    9.熔斷器什么場景下會失效

  • feign 未開啟 hystrix 功能
  • 超時時間配置不正確
  • 未開啟熔斷器的功能,false
  • 超時時間沒有考慮 ribbon 的情況
  • 10.什么是 Dashboard?

    Hystrix Dashboard 是一個通過收集 actuator 端點提供的 Hystrix 流數據,因此在這些被斷路器保護的應用中需要開啟 Hystrix 流的 Actuator 端點,并將其圖表化的客戶端。如果需要通過圖表化的界面查看被斷路器保護的方法相關調用信息、或者實時監控這些被斷路器保護的應用的健康情況,就可以使用 Hystrix Dashboard。

    11.Dashboard 使用

    #監控鏈接 http://localhost:8080/hystrix.stream http://localhost:8080/actuator/hystrix.stream#請求下hystrix的接口 http://localhost:8080/portal/hystrix/1

    #訪問鏈接 http://localhost:9909/hystrix

    portal中需要加入

    @Bean public ServletRegistrationBean getServlet() {HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean; }

    dashboard中需要加入

    hystrix:dashboard:proxy-stream-allow-list: "localhost"

    12.儀表盤解讀

    • 實心圓:共有兩種含義。它通過顏色的變化代表了實例的健康程度

    • 該實心圓除了顏色的變化之外,它的大小也會根據實例的請求流量發生變化,流量越大該實心圓就越大。所以通過該實心圓的展示,就可以在大量的實例中快速的發現故障實例和高壓力實例。

    • 曲線:用來記錄 2 分鐘內流量的相對變化,可以通過它來觀察到流量的上升和下降趨勢。

    在圖表中,左上角的圓圈代表了該方法的流量和狀態:

    • 圓圈越大代表方法流量越大
    • 圓圈為綠色代表斷路器健康、黃色代表斷路器偶發故障、紅色代表斷路器故障

    右上角的計數器(三列數字):

    第一列從上到下

    • 綠色代表當前成功調用的數量

    • 藍色代表短路請求的數量

    • 藍綠色代表錯誤請求的數量

    第二列從上到下

    • 黃色代表超時請求的數量

    • 紫色代表線程池拒絕的數量

    • 紅色代表失敗請求的數量

    第三列

    • 過去 10s 的錯誤請求百分比

    Thread Pools:

    Hystrix 會針對一個受保護的類創建一個對應的線程池,這樣做的目的是 Hystrix 的命令被調用的時候,不會受方法請求線程的影響(或者說 Hystrix 的工作線程和調用者線程相互之間不影響)

    左下角從上至下:

    • Active 代表線程池中活躍線程的數量

    • Queued 代表排隊的線程數量,該功能默認禁止,因此默認情況下始終為 0

    • Pool Size 代表線程池中線程的數量(上面圖我搞錯了,困得死 MMP

    右下角從上至下:

    • Max Active 代表最大活躍線程,這里展示的數據是當前采用周期中,活躍線程的最大值

    • Execcutions 代表線程池中線程被調用執行 Hystrix 命令的次數

    • Queue Size 代表線程池隊列的大小,默認禁用,無意義

    13.turbine 的作用

    監控數據聚合

    Turbine 是聚合服務器發送事件流數據的一個工具,Hystrix 的監控中,只能監控單個節點,實際生產中都為集群,因此可以通過 Turbine 來監控集群下 Hystrix 的 metrics 情況,同一個服務負載均衡情況下,可以監控多個實例.hosts>1

    14.turbine 使用

    http://localhost:8081/portal/hystrix/1 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-turbine</artifactId> </dependency> @EnableTurbine @EnableEurekaClient @EnableHystrixDashboard @SpringBootApplication public class HystrixTurbineApplication {public static void main(String[] args) {SpringApplication.run(HystrixTurbineApplication.class, args);}}

    #端口號 server:port: 9999spring:application:name: hystrix-turbine-service #服務名稱#服務提供者 eureka:client:service-url:defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/instance:lease-renewal-interval-in-seconds: 2 #每間隔2s,向服務端發送一次心跳,證明自己依然"存活”lease-expiration-duration-in-seconds: 10 #告訴服務端,如果我10s之內沒有給你發心跳,就代表我故障了,將我踢出掉prefer-ip-address: true #告訴服務端,服務實例以IP作為鏈接,而不是取機器名instance-id: springcloud-service-turbine-9999 #告訴服務端,服務實例的id,id要是唯一的# 開啟Feign對Hystrix的支持 feign:hystrix:enabled: trueclient:config:default:connectTimeout: 5000 # 指定Feign連接提供者的超時時限readTimeout: 5000 # 指定Feign從請求到獲取提供者響應的超時時限# 開啟actuator的所有web終端 management:endpoints:web:exposure:include: "*"# 設置服務熔斷時限 hystrix:dashboard:proxy-stream-allow-list: "localhost"command:default:execution:isolation:thread:timeoutInMilliseconds: 3000turbine:app-config: portal-servicecluster-name-expression: new String("default")combine-host-port: trueinstanceUrlSuffix: /actuator/hystrix.stream #turbine默認監控actuator/路徑下的端點,修改直接監控hystrix.stream#cluster-name-expression: metadata['cluster']#aggregator:# cluster-config: ribbon#instanceUrlSuffix: /hystrix.stream #turbine默認監控actuator/路徑下的端點,修改直接監控hystrix.stream

    15.@SpringCloudApplication

    @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker public @interface SpringCloudApplication { }
    • @SpringBootApplication
    • @EnableDiscoveryClient
    • @EnableCircuitBreaker

    組合注解,SpringBootApplication,注冊中心客戶端 EnableDiscoveryClient,支持 hystrix 的 EnableCircuitBreaker

    16.超時時間

    Ribbon 和 Hystrix和Feign 的超時時間配置的關系

    • 在 Spring Cloud 中使用 Feign 進行微服務調用分為兩層:Hystrix 的調用和 Ribbon 的調用,Feign 自身的配置會被覆蓋。
    • Hystrix 的超時時間和 ribbon 的超時時間存在一定的關系
    • 說明下,如果不啟用 Hystrix,Feign 的超時時間則是 Ribbon 的超時時間,Feign 自身的配置也會被覆蓋
    Hystrix的超時時間=Ribbon的重試次數(包含首次) * (ribbon.ReadTimeout + ribbon.ConnectTimeout)Ribbon重試次數(包含首次)= 1 + ribbon.MaxAutoRetries + ribbon.MaxAutoRetriesNextServer + (ribbon.MaxAutoRetries * ribbon.MaxAutoRetriesNextServer)

    五.zuul

    1.微服務網關?

    服務網關是微服務架構中一個不可或缺的部分。通過服務網關統一向外系統提供 REST API 的過程中,除了具備服務路由、均衡負載功能之外,它還具備了權限控制等功能。Spring Cloud Netflix 中的 Zuul 就擔任了這樣的一個角色,為微服務架構提供了前門保護的作用,同時將權限控制這些較重的非業務邏輯內容遷移到服務路由層面,使得服務集群主體能夠具備更高的可復用性和可測試性。

    Zuu 包含了對請求的路由和過濾 兩個最主要的功能:

    其中路由功能負責將外部請求轉發到具體的微服務實例上是實現外部訪問統一入口的基礎,過濾功能則負責對請求的處理過程進行干預,是實現請求校驗、服務聚合等功能的基礎;

    Zuul 和 Eureka 進行整合,將 Zuul 自身注冊為 Eureka 服務治理下的應用,同時從 Eureka 中獲得其他微服務的信息,也即以后的訪問微服務都是通過 Zuul.

    2.Zuul 網關的作用

    網關有以下幾個作用:

    • 統一入口:未全部為服務提供一個唯一的入口,網關起到外部和內部隔離的作用,保障了后臺服務的安全性。
    • 鑒權校驗:識別每個請求的權限,拒絕不符合要求的請求。
    • 動態路由:動態的將請求路由到不同的后端集群中。
    • 減少客戶端與服務端的耦合:服務可以獨立發展,通過網關層來做映射。

    3.zuul 的功能?

    使用 Zuul 的過濾器, 可以對請求的一些列信息進行安全認證/權限認證/身份識別/限流/記錄日志等功能。只需要自定義 Filter 后繼承 ZuulFilter 類即可。重寫其 filterType、filterOrder、shouldFilter 以及 run 方法。 filterType 表示 filter 執行的時機:

    其 value 值含義如下所示:

    • pre:在請求被路由之前調用 比如:登錄驗證
    • routing: 在請求被路由之中調用
    • post: 在請求被路由之后調用
    • error: 處理請求發生錯誤時調用
    • filterOrder 表示執行的優先級,值越小表示優先級越高
    • shouldFilter 則表示該 filter 是否需要執行

    4.路由配置

    zuul:sensitiveHeaders: Cookie,Set-Cookie,Authorizationroutes:portal:path: /portal-service/** #訪問路徑:http:/localhost:8888/portal-service/portal/1service-id: portal-servicegoods:path: /goods-service/** #http:/localhost:8888/goods-service/kwanGoodsInfo/1service-id: goods-servicehost:connect-timeout-millis: 5000 #超時時間prefix: /api #訪問路徑:http:/localhost:8888/api/portal-service/portal/1 http:/localhost:8888/api/goods-service/kwanGoodsInfo/1retryable: trueignored-services: portal-service #感略某個服務名,禁止通過該服務名訪可# ignored-services: * #禁止通過所有的服務名訪間ignored-patterns: /**/feign/** #不給匹配此棋式的路徑進行路由·那么你到時候訪間不到LogFilter:route:disable: true #用LogFilter過濾器

    4.過濾器

    filter 是 zuul 的核心組件,zuul 大部分功能都是通過過濾器來實現的。zuul 中定義了 4 種標準過濾器類型,這些過濾器類型對應于清求的典型生命周期。

    • PRE:這種過濾器在請求被路由之前調用??衫眠@種過濾器實現身份驗證、在集群中選擇請求的微服務、記錄調試信息等。
    • ROUTING:這種過濾器將請求路由到微服務。這種過濾器用于構建發送給微服務的請求,并使用 Apache HttpClient:或 Netfilx Ribbon 請求微服務
    • POST:這種過濾器在路由到微服務以后執行。這種過濾器可用來為響應添加標準的 HTTP Header 收集統計信息和指標、將響應從微服務發送給客戶端等。
    • ERROR:在其他階段發生錯誤時執行該過濾器。

    5.過濾器禁用

    zuul 過濾器的禁用,Spring Cloud 默認為 Zuul 編寫并啟用了一些過濾器,例妝如 DebugFilter,

    FormBodyWrapperFilter 等,這些過濾器都存放在 spring-cloud-netflix-zuul 這個 jr 包里,一些場景下,想要禁用掉部分過濾器,該怎么辦呢?只需在 application.properties 里設置 zuul…disable=true 例如,要禁用上面我們寫的過濾器,這樣配置就行了:

    zuul.LogFilter.route.disable=true

    6.Zuul 的熔斷降級

    zuul 是一個代理服務,但如果被代理的服務突然斷了,這個時候 zuul 上面會有出錯信息,例如,停止了被調用的微服務;一般服務方自己會進行服務的熔斷降級,但對于 zuul 本身,也應該進行 zuul 的降級處理:

    Zuul 的 fallback 容錯處理邏輯,只針對 timeout 異常處理,當請求被 Zuul 路由后,只要服務有返回(包括異常),都不會觸發Zuul的fallback容錯邏輯。

    因為對于 Zuul 網關來說,做請求路由分發的時候,結果由遠程服務運算的。那么遠程服務反饋了異常信息,Zuul 網關不會處理異常,因為無法確定這個錯誤是否是應用真實想要反饋給客戶端的。

    六.config

    1.分布式配置中心

    Spring Cloud Config 為服務端和客戶端提供了分布式系統的外部化配置支持。

    配置服務器默認采用 git 來存儲配置信息,這樣就有助于對環境配置進行版本管理,并且可以通過 git 客戶端工具來方便的管理和訪問配置內容。當然他也提供本地化文件系統的存儲方式

    配置中心用途 :

    • 變量獲取
    • 加解密
    • 自動刷新
    • 高可用
    • 安全認證

    2.為什么需要分布式配置中心

    在分布式微服務體系中,服務的數量以及配置信息日益增多,比如各種服務器參數配置、各種數據庫訪問參數配置、各種環境下配置信息的不同、配置信息修改之后實時生效等等,傳統的配置文件方式或者將配置信息存放于數據庫中的方式已無法滿足開發人員對配置管理的要求,如:

    • 安全性:配置跟隨源代碼保存在代碼庫中,容易造成配置泄漏
    • 時效性:修改配置,需要重啟服務才能生效
    • 局限性:無法支持動態調整:例如日志開關、功能開關

    3.常用分布式配置中心框架

    • Apollo(阿波羅):攜程框架部門研發的分布式配置中心,能夠集中化管理應用不同環境、不同集群的配置,配置修改后能夠實時推送到應用端,并且具備規范的權限、流程治理等特性,適用于微服務配置管理場景
    • diamond:淘寶開源的持久配置中心,支持各種持久信息(比如各種規則,數據庫配置等)的發布和訂閱
    • XDiamond:全局配置中心,存儲應用的配置項,解決配置混亂分散的問題,名字來源于淘寶的開源項目 diamond,前面加上一個字母 X 以示區別。
    • Qconf:奇虎 360 內部分布式配置管理工具,用來替代傳統的配置文件,使得配置信息和程序代碼分離,同時配置變化能夠實時同步到客戶端,而且保證用戶高效讀取配置,這使的工程師從瑣碎的配置修改、代碼提交、配置上線流程中解放出來,極大地簡化了配置管理工作;
    • Disconf:百度的分布式配置管理平臺,專注于各種分布式系統配置管理的通用組件和通用平臺,提供統一的配置管理服務;
    • Spring Cloud Config:Spring Cloud 微服務開發的配置中心,提供服務端和客戶端支持;

    4.什么是 Spring Cloud Config?

    Spring Cloud Config 是一個解決分布式系統的配置管理方案。它包含 Client 和 Server 兩個部分,Server 提供配置文件的存儲、以接口的形式將配置文件的內容提供出去,Client 通過接口獲取數據、并依據此數據初始化自己的應用。

    Spring cloud 使用 git 或 svn、也可以是本地存放配置文件,默認情況下使用 git。

    5.配置路由規則

    /{application)-{profile}.properties

    http://localhost:8888/application-dev.properties

    /{label}/{application}-{profile}.properties

    http://localhost:8888/master/application-dev.properties

    /[application}-{profile}.yml

    http://localhost:8888/master/application-dev.yml

    /{label}/{application}-{profile}.yml

    http://localhost:8888/master/application-dev.properties

    其中:

    {application}表示配置文件的名字,對應的配置文件即 application,

    {profile}表示環境,有dev、test、online 及默認,

    {label}表示分支,默認我們放在 master 分支上,

    通過瀏覽器上訪問http:/localhost:8888/application,/dev/master

    6.加解密

    加解密是借助 JCE 實現的,默認情況下我們的 JRE 中自帶了 JCE(Java Cryptography Extension),但是默認是一個有限長度的版本,我們這里需要一個不限長度的 JCE,JCE 是對稱加密,安全性相對非對稱加密低一點,但是使用更加方便一點

    下載完成之后解壓,把得到到兩個 Jar 包復制到$JAVA_HOME\jre\lib\security 目錄下。

    在我們的 configserver 項目中的 bootstrap.yml 配置文件中加入如下配置項:

    encrypt:key: Thisismysecretkey

    訪問下面連接進行單個數據加密,這里是 post 請求,不是 get

    #加密 http://localhost:7001/encrypt#解密 http:/192.168.6.817001/decrypt

    可能會報錯,需要添加賬號密碼

    username='{cipher)516269d5f6af298bf843b31c847ad705d8305e784c394c7395a55a0742d8b69d'

    需要使用{cipher}的密文形式,單引號不要忘記了。然后 push 到遠程。

    加解密在 config-server 服務中進行的,解密過程不需要在客戶端進行配置

    7.加密過程安全認證

    1.添加依賴

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

    2.config 配置

    在 config 的配置文件中配置

    spring:security:user:password: user123 #配置登陸的密碼是user123name: user #配置登陸的賬戶是user

    或者

    顯式指定賬號密碼,指定賬戶密碼的優先級要高于 URI

    spring:cloud:config:label: ${spring.profiles.active} #指定Git倉庫的分支,對應config server 所獲取的配置文件的{label}discovery:enabled: true #表示使用服務發現組件中的configserver ,而不是自己指定config server的uri,默認為falseservice-id: microservice-config-server #服務發現中configserver的serverIdfail-fast: true #失敗快速響應username: userpassword: user123

    3.客戶端配置

    spring:cloud:config:uri: http://user:user123@localhost:7001/

    7.局部刷新

    Spring Boot 的 actuator 提供了一個刷新端點/refresh,添加依賴

    spring-boot-starter-actuator,可用于配置的刷新;

    <!--springboot的一個監控actuator--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>

    在 Controller 上添加注解@RefreshScope,添加這個注解的類會在配置更新時得到特殊的處理;

    打開 web 訪問端點

    management,endpoints.web.exposure.include=“*”

    訪問http:/localhost:8080/actuator/refresh 進行手動刷新配置;必須要 post 方式訪問這個接口

    8.詳解@RefreshScope

    8.全局刷新

    全局刷新需要使用到消息總線

    前面使用/actuator/refresh 端點手動刷新配置雖然可以實現刷新,但所有微服務節點的配置都需要手動去刷新,如果微服務非常多,其工作量非常龐大。因此實現配置的自動刷新是志在必行,Spring Cloud Bus 就可以用來實現配置的自動刷新;

    Spring Cloud Bus 使用輕量級的消息代理(例如 RabbitMQ、Kafka 等)廣播傳播狀態的更改(例如配置的更新)或者其他的管理指令,可以將 Spring Clou Bus 想象成一個分布式的 Sprina Boot Actuator;

    #形置rabbitmq spring.rabbitmq.host=192.168.10.128 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password-guest #開啟spring cloud bus默認是開啟的,也可以省略速形置 spring.cloud.bus.enabled=true 打開所有的web訪問端點 management.endpoints.web.exposure.include=*

    各個微服務(客戶端),其他各個微服務用于接收消息,那么也需要有 spring cloud bus 的依賴和 RabbitMQ 的連接信息;I

    然后 post 方式請求地址,如果返回成功,則 RabbitMQ 將收到消息,然后微服務會消費消息,config 的所有客戶端的微服務配置都會動態刷新;

    http:/localhost::8888/actuator//bus-refresh

    2.什么是總線

    在微服務架構的系統中,通常會使用輕量級的消息代理來構建一個共用的消息主題,并讓系統中所有微服務實例都連接上來。由于該主題中產生的消息會被所有實例監聽和消費,所以稱它為消息總線。在總線上的各個實例,都可以方便地廣播一些需要讓其他連接在該主題上的實例都知道的消息。

    3.消息總線原理

    ConfigClient 實例都監聽 MQ 中同一個 topic(默認是 springCloudBus)。當一個服務刷新數據的時候,它會把這個信息放入到 Topic 中,這樣其它監聽同一 Topic 的服務就能得到通知,然后去更新自身的配置。

    通過使用 Spring Cloud Bus 與 Spring Cloud Config 的整合,并以 RabbitMQ 作為消息代理,實現了應用配置的動態更新。

    4.SpringCloudBus

    Spring Cloud Bus 是用來將分布式系統的節點與輕量級消息系統鏈接起來的框架,它整合了 Java 的事件處理機制和消息中間件的功能。
    Spring Clud Bus 目前支持 RabbitMQ 和 Kafka。

    Spring Cloud Bus 能管理和傳播分布式系統間的消息,就像一個分布式執行器,可用于廣播狀態更改、事件推送等,也可以當作微服務間的通信通道。

    利用消息總線觸發一個服務端 ConfigServer 的/bus/refresh 端點,而刷新所有客戶端的配置

    當我們將系統啟動起來之后,“Service A”的三個實例會請求 Config Server 以獲取配置信息,Config Server 根據應用配置的規則從 Git 倉庫中獲取配置信息并返回。

    此時,若我們需要修改“Service A”的屬性。首先,通過 Git 管理工具去倉庫中修改對應的屬性值,但是這個修改并不會觸發“Service A”實例的屬性更新。我們向“Service A”的實例 3 發送 POST 請求,訪問/bus/refresh接口。此時,“Service A”的實例 3 就會將刷新請求發送到消息總線中,該消息事件會被“Service A”的實例 1 和實例 2 從總線中獲取到,并重新從 Config Server 中獲取他們的配置信息,從而實現配置信息的動態更新。

    而從 Git 倉庫中配置的修改到發起/bus/refresh的 POST 請求這一步可以通過 Git 倉庫的 Web Hook 來自動觸發。由于所有連接到消息總線上的應用都會接受到更新請求,所以在 Web Hook 中就不需要維護所有節點內容來進行更新,從而解決了通過 Web Hook 來逐個進行刷新的問題。

    通過destination參數來指定需要更新配置的服務或實例。

    七.Sleuth

    1.什么是 Sleuth?

    Spring Cloud Sleuth 是 Spring Cloud 提供的分布式系統服務鏈追蹤組件,它大量借用了 Google 的 Dapper,Twitter 的 Zipkin。學習 Spring Cloud Sleuth,最好先對 Zipkin 有一些了解,對 span、trace 這些概念有相應的認識。

    2.為什么需要 Sleuth?

    鏈路追蹤:通過 Sleuth 可以很清楚的看出一個請求都經過了那些服務,可以很方便的理清服務間的調用關系等。

    性能分析:通過 Sleuth 可以很方便的看出每個采樣請求的耗時,分析哪些服務調用耗時,當服務調用的耗時隨著請求量的增大而增大時, 可以對服務的擴容提供一定的提醒。

    數據分析,優化鏈路:對于頻繁調用一個服務,或并行調用等,可以針對業務做一些優化措施。

    可視化錯誤:對于程序未捕獲的異常,可以配合 Zipkin 查看。

    • 快速發現問題
    • 判斷故障影響范圍
    • 梳理服務依賴以及依賴的合理性
    • 分析鏈路性能問題以及實時容量規劃

    單純的理解鏈路追蹤,就是將一次分布式請求還原成調用鏈路,進行日志記錄,性能監控并將一次分布式請求的調用情況集中展示。比如各個服務節點上的耗時、請求具體到達哪臺機器上、每個服務節點的請求狀態等等。

    3.鏈路追蹤相關產品

    常見的鏈路追蹤技術有下面這些 :

    cat:由大眾點評開源,基于 Java 開發的實時應用監控平臺,包括實時應用監控,業務監控 。 集成方案是通過代碼埋點的方式來實現監控,比如: 攔截器,過濾器等。 對代碼

    的侵入性很大,集成成本較高。風險較大。

    zipkin:由 Twitter 公司開源,開放源代碼分布式的跟蹤系統,用于收集服務的定時數據,以解決微服務架構中的延遲問題,包括:數據的收集、存儲、查找和展現。該產品結合

    spring-cloud-sleuth 使用較為簡單, 集成很方便, 但是功能較簡單。

    pinpoint:Pinpoint 是韓國人開源的基于字節碼注入的調用鏈分析,以及應用監控分析工具。特點是支持多種插件, UI 功能強大,接入端無代碼侵入。

    skywalking:本土開源的基于字節碼注入的調用鏈分析,以及應用監控分析工具。特點是支持多種插件, UI 功能較強,接入端無代碼侵入。目前已加入 Apache 孵化器。

    Sleuth:SpringCloud 提供的分布式系統中鏈路追蹤解決方案。

    注意: SpringCloud alibaba 技術棧中并沒有提供自己的鏈路追蹤技術的,我們可以采用Sleuth +Zinkin來做鏈路追蹤解決方案

    4.基本術語?

    Sleuth 基本概念涉及到三個專業術語: span、Trace、Annotations。

    span :基本工作單位,每次發送一個遠程調用服務就會產生一個 Span。Span 是一個 64 位的唯一 ID。通過計算 Span 的開始和結束時間,就可以統計每個服務調用所花費的時間。。

    Trace :一系列 Span 組成的樹狀結構,一個 Trace 認為是一次完整的鏈路,內部包含 n 多個 Span。Trace 和 Span 存在一對多的關系,Span 與 Span 之間存在父子關系。

    Annotations :用來及時記錄一個事件的存在,一些核心 annotations 用來定義一個請求的開始和結束。

    開始與結束:

    • cs(Client Sent) :客戶端發起一個請求,這個 annotation 描述了這個 span 的開始;
    • sr(Server Received) :服務端獲得請求并準備開始處理它,如果 sr 減去 cs 時間戳便可得到網絡延遲;
    • ss(Server Sent) :請求處理完成(當請求返回客戶端),如果 ss 減去 sr 時間戳便可得到服務端處理請求需要的時間;
    • cr(Client Received) :表示 span 結束,客戶端成功接收到服務端的回復,如果 cr 減去 cs 時間戳便可得到客戶端從服務端獲取回復的所有所需時間。

    核心: 為什么能夠進行整條鏈路的追蹤? 其實就是一個 Trace ID 將 一連串的 Span 信息連起來了。根據 Span 記錄的信息再進行整合就可以獲取整條鏈路的信息。

    5.什么是 zipkin

    Zipkin 是一種分布式跟蹤系統。它有助于收集解決微服務架構中的延遲問題所需的時序數據。它管理這些數據的收集和查找。Zipkin 的設計基于 Google Dapper 論文。應用程序用于向 Zipkin 報告時序數據。Zipkin UI 還提供了一個依賴關系圖,顯示了每個應用程序通過的跟蹤請求數。如果要解決延遲問題或錯誤,可以根據應用程序,跟蹤長度,注釋或時間戳對所有跟蹤進行篩選或排序。選擇跟蹤后,您可以看到每個跨度所需的總跟蹤時間百分比,從而可以識別有問題的應用程序。

    6.zipkin 的坑

    SpringBoot2.2.x 以后的版本 集成 zipkin 的方式改變了,原來是通過@EnablezipkinServer注解,現在這個注解不起作用了。

    服務端應該通過下載 jar 包,然后 運行 jar 包來集成 。 可以選擇版本下載,要選擇后綴為 -exec.jar 的,之后切換到 jar 包在的路徑,然后用 java -jar 的方式啟動就可以了(默認端口號是 9411 ,所以如果提供了 zipkin client,需要把它的配置文件中的端口號改成 9411,對應的配置應該是 zipkin: base-url: http://localhost:9411)

    spring:cloud:config:fail-fast: false #客戶端連接失敗時開啟重試,需要結合spring-retry、spring-aoplabel: main #獲取配置文件的分支名name: application-portal8081 #獲取的文件名profile: portal8081 #文件后綴uri: http://localhost:7001 #配置中心服務端地址zipkin:base-url: http://localhost:9411

    7.zipkin 下載安裝

    1.下載地址

    https://repo1.maven.org/maven2/io/zipkin/zipkin-server/

    2.下載 jar 包

    可以使用迅雷下載,或者科學上網

    3.啟動服務端

    啟動報錯,看看端口是否被占用

    java -jar zipkin-server-2.23.9-exec.jar

    4.訪問控制臺

    http://127.0.0.1:9411/zipkin

    8.客戶端配置

    1.pom 依賴

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

    2.配置文件

    #端口號,指定端口,不然默認是8080,會出現沖突 server:port: 8081spring:cloud:config:fail-fast: false #客戶端連接失敗時開啟重試,需要結合spring-retry、spring-aoplabel: main #獲取配置文件的分支名name: application-portal8081 #獲取的文件名profile: portal8081 #文件后綴uri: http://localhost:7001 #配置中心服務端地址zipkin:base-url: http://localhost:9411 #zipkin地址 默認值就是0.1,代表收集10%的請求追蹤信息。discovery-client-enabled: falsesender:type: websleuth:sampler:percentage: 0.1 #收集百分比 eureka:client:service-url:defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/

    9.控制臺

    需要調用一下服務,才能在控制臺查詢到

    • 可以看到請求過的鏈路信息
    • 包含的微服務
    • 耗時信息
    • 還能通過篩選條件進行查詢
    • 可以通過 trace id 進行查詢
    http://127.0.0.1:9411/zipkin

    詳細面板可以看到 :

    • 具體的統計信息
    • 統計耗時信息,開始時間以及結束時間,以及每一段的耗時信息
    • 標簽信息,接口信息
    • 請求方式,請求方法
    • Span ID
    • Trace ID
    • 服務名
    • 服務數
    • 深度
    • 跨度總數

    10.依賴關系圖

    11.采樣數據

    zikpin 日志采樣率設置為 0.1,就是 10 次只能有一次被記錄下來。當時看到這個問題很郁悶,那 9 次的請求咋辦,日志不完整怎么排查錯誤呢?

    日志其實是完整的,日志可以用 logback 收集并保存成文件。所有的請求信息 都會被這個文件所記錄,只是 zikpin 側重于鏈路追蹤,并不是排查錯誤,更多的是我們知道服務直接調用耗時和服務直接依賴關系而已。所以不需要完整日志,只需要 0.1 比例就夠了

    sleuth:sampler:probability: 0.1

    而這個采樣其實只是對 zipkin 有效,只是在 zipkin 界面顯示 0.1 的日志而已,并不是后臺日志也都是只收集 0.1。

    而 logback 會把我們所有請求信息全部記錄下來,不會遺漏,這樣的話就可以順利排錯。

    12.數據持久化

    zipkin 中的數據默認是保存在內存中的,重啟 sleuth 服務,數據會被清空,這顯然是不合適的.

    zipkin 可以集成 elasticsearch,或者 mysql 進行數據的持久化,這樣服務重啟,數據不丟失.

    總結

    以上是生活随笔為你收集整理的【檀越剑指大厂—SpringCloudNetflix】SpringCloudNetflix高阶篇的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 少妇厨房愉情理伦bd在线观看 | 大陆一级片 | 国产精品免费精品一区 | 久久精品欧美日韩 | 国产欧美一区二区三区在线看蜜臀 | 91精品在线免费观看 | 草草网址 | 亚洲成a人v欧美综合天堂麻豆 | 51国产偷自视频区视频 | 五月天av网站 | 91高潮大合集爽到抽搐 | 91成人免费| 国产精品99久久 | 久色99| 情侣在线视频 | 国产精选网站 | 亚洲国产电影在线观看 | 亚洲毛片在线免费观看 | 国产午夜一区二区 | 亚洲视频一区二区三区在线观看 | 精品国产乱码久久久人妻 | 激情成人综合 | 成人午夜影视在线观看 | 91成人免费电影 | www.啪| 亚洲一区二区在线免费 | 丰满人妻中伦妇伦精品app | 国产精品一区二区三区高潮 | 你懂的在线观看网站 | 久久99国产视频 | 亚洲图片在线视频 | 免费看裸体视频网站 | 国产午夜福利一区二区 | 色综合天天综合网天天狠天天 | 久久久久久中文 | 日韩av片在线免费观看 | 越南毛茸茸的少妇 | 成人国产免费 | 操操操网 | 亚洲AV成人无码久久精品巨臀 | 亚洲欧美强伦一区二区 | 黄色大片av | 69网址 | 免费瑟瑟网站 | 玖玖爱在线精品视频 | 一本色道久久综合狠狠躁 | 亚洲丁香网 | 青青草手机视频 | 91抖音在线观看 | 中文字幕国产 | 凹凸福利视频 | 人妻无码久久一区二区三区免费 | 一边摸一边做爽的视频17国产 | 亚洲精品高潮久久久久久久 | 婷婷伊人综合中文字幕 | 激情亚洲色图 | 清冷学长被爆c躁到高潮失禁 | 国产国语性生话播放 | 国产在线喷水 | 777精品伊人久久久久大香线蕉 | 涩久久| 伊人快播 | 久久久无码精品亚洲无少妇 | 在线碰| 毛片2| 青青色在线视频 | 国产肉体ⅹxxx137大胆 | 蜜桃传媒一区二区亚洲av | 91新视频 | 国产激情对白 | 国产精品九九九 | 欧美三级韩国三级日本三斤在线观看 | 精品影片一区二区入口 | 日韩xx视频| 久久久男人天堂 | 日韩精品2区 | 樱花电影最新免费观看国语版 | 国产美女啪啪 | 91精品福利| 免费黄色美女网站 | 欧美壮男野外gaytube | av黄页| 亚洲激情五月婷婷 | 亚洲第一色图 | 爱情岛论坛永久入址测速 | 欧美激情久久久久久 | 亚洲精品久久久久久 | 亚洲三级久久 | 五月99久久婷婷国产综合亚洲 | 在线观看黄网站 | 免费在线观看小视频 | 中文字幕va| 五月av| 91精品一区二区三区在线观看 | 黄色动漫在线免费观看 | 波多野结衣导航 | 青青青草视频在线观看 | 激情吧| 日韩综合区 |