日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本文主要介紹的微服務是spring cloud,它一個服務治理框架和一系列框架的由序集合,其利用springboot的開發便利性巧妙的簡化了分布式系統基礎設施的開發,如服務發現注冊、負載均衡、斷路器、數據監控等,都可以用springboot的開發風格做到一鍵啟動和部署。學習和了解微服務對快速熟悉和掌握不同項目的服務架構大有益處

分為以下幾個部分進行介紹:

一、微服務應用的簡單業務場景

二、Spring Cloud核心組件:Eureka

三、Spring Cloud核心組件:Feign

四、Spring Cloud核心組件:Ribbon

五、Spring Cloud核心組件:Hystrix

六、Spring Cloud核心組件:Zuul

七、高并發場景下配置優化

八、總結


一、業務場景介紹

先來給大家說一個都熟悉的支付訂單的功能,大體的流程如下:

  • 用戶創建一個訂單并支付,需要將訂單狀態更新為“已支付”
  • 更新商品庫存
  • 通知物流發貨
  • 增加用戶購物積分

上述業務場景的流程涉及到訂單服務、庫存服務、物流服務、用戶積分服務。其調用關系如下圖:

 

當時高并發項目差點讓我丟了工作!看我如何配置優化

 

二、Spring Cloud核心組件:Eureka

考慮一個問題:訂單服務想要調用庫存服務、物流服務,或者是積分服務,怎么調用?

  • 傳統方式:通過傳統的ip:port的方式調用各種服務,如果訂單服務依賴的其他服務地址更改了,就需要修改訂單服務配置,然后重新部署。阿西吧!
  • eureka出場,eureka是微服務架構的注冊中心,專門負責服務的注冊和發現。Eureka有兩個組件組成:Eureka server和Eureka client,一張圖認識一下:
當時高并發項目差點讓我丟了工作!看我如何配置優化

 

  • 上面的圖描述了Eureka的基本架構,有3個角色組成
  1. Eureka Server:提供服務注冊和發現
  2. Service Provider:服務提供方,將自身服務注冊到Eureka Server,從而使消費方能夠找到
  3. Service Consumer:服務消費方,定時從Eureka獲取注冊服務列表,消費服務
  • 再來看一下業務場景中,這些服務上都有Eureka Client組件,Service Provider啟動時將自己注冊到Eureka Server上,注冊的意思就是告訴Eureka Server 自己在哪臺服務器,端口號等,Eureka Server 的注冊表會保存這些服務的元數據信息。這個時候如果訂單服務調用庫存服務,Service Consumer通過Eureka Client組件 向Eureka Server 問一下庫存服務的ip是什么,端口是什么,然后調用庫存服務。訂單服務調用其他服務亦是如此。
當時高并發項目差點讓我丟了工作!看我如何配置優化

 

 

  • 千萬級訪問量:eureka各個服務默認每隔30秒拉取注冊表,每隔30s發起一次心跳,看看Eureka是如何實現千萬級別訪問量
  1. 假設現在有一個大型的分布式系統,一共100個服務,每個服務部署在20臺機器上,機器是4核8G的標準配置。也就是說,相當于你一共部署了100 * 20 = 2000個服務實例,有2000臺機器。每臺機器上的服務實例內部都有一個Eureka Client組件,它會每隔30秒請求一次Eureka Server,拉取變化的注冊表。此外,每個服務實例上的Eureka Client都會每隔30秒發送一次心跳請求給Eureka Server。

那么大家算算,Eureka Server作為一個微服務注冊中心,每秒鐘要被請求多少次?一天要被請求多少次?

按標準的算法,每個服務實例每分鐘請求2次拉取注冊表,每分鐘請求2次發送心跳

  • 這樣一個服務實例每分鐘會請求4次,2000個服務實例每分鐘請求8000次
  • 換算到每秒,則是8000 / 60 = 133次左右,我們就大概估算為Eureka Server每秒會被請求150次
  • 那一天的話,就是8000 * 60 * 24 = 1152萬,也就是每天千萬級訪問量

深入原理:

  • Eureka server注冊數據結構:
當時高并發項目差點讓我丟了工作!看我如何配置優化

 

  • 如上圖所示,圖中的這個名字叫做registryCocurrentHashMap,就是注冊表的核心結構。各個服務的注冊、服務下線、服務故障,全部會在內存里維護和更新這個注冊表。
  • 各個服務每隔30秒拉取注冊表,每隔30s發起一次心跳,都在這Map數據結構中操作

一句話概括:維護注冊表、拉取注冊表、更新心跳時間,全部發生在內存里!

  • 這個ConcurrentHashMap的key就是服務名稱,比如“訂單服務的名字是:order-service,這里就是order-service”, value則代表了一個服務的多個服務實例。Lease的類,它的泛型是一個叫做InstanceInfo,代表服務實例的具體信息,比如機器的ip地址、hostname以及端口號。而這個Lease,里面則會維護每個服務最近一次發送心跳的時間
  • Eureka Server為了避免同時讀寫內存數據結構造成的并發沖突問題,采用了多級緩存機制ReadOnlyCacheMapReadWriteCacheMap)提升服務請求的響應速度。

在拉取注冊表的時候:

  1. 首先從ReadOnlyCacheMap里查緩存的注冊表。
  2. 若沒有,就找ReadWriteCacheMap里緩存的注冊表。
  3. 如果還沒有,就從內存中獲取實際的注冊表數據。

在注冊表發生變更的時候:

  1. 會在內存中更新變更的注冊表數據,同時過期掉ReadWriteCacheMap
  2. 此過程不會影響ReadOnlyCacheMap提供人家查詢注冊表。
  3. 一段時間內(默認30秒),各服務拉取注冊表會直接讀ReadOnlyCacheMap
  4. 30秒過后,Eureka Server的后臺線程發現ReadWriteCacheMap已經清空了,也會清空ReadOnlyCacheMap中的緩存
  5. 下次有服務拉取注冊表,又會從內存中獲取最新的數據了,同時填充各個緩存。

 

總結一下:

  • Eureka Client:負責將這個服務的信息注冊到Eureka Server中
  • Eureka Server:注冊中心,里面有一個注冊表,保存了各個服務所在的機器和端口號

三、Spring Cloud核心組件:Feign

 

實現優雅的rpc調用:解決完服務在哪里之后,該如何去調用服務呢?難道訂單服務要自己寫一大堆代碼,跟其他服務建立網絡連接,然后構造一個復雜的請求,接著發送請求過去,最后對返回的響應結果再寫一大堆代碼來處理嗎?想到這里是不是直想撓頭,為了保住自己本來就不多的頭發!來看看Feign是如何處理的吧!

當時高并發項目差點讓我丟了工作!看我如何配置優化

 

看完上面的代碼是不是感覺干凈清爽!沒有底層的建立連接、構造請求、解析響應的代碼,直接就是用注解定義一個 FeignClient接口,然后調用那個接口就可以了,Feign都幫你做好了。

Feign實現這些的原理:一個關鍵機制就是使用了動態代理

  • 首先,如果你對某個接口定義了@FeignClient注解,Feign就會針對這個接口創建一個動態代理
  • 接著你要是調用那個接口,本質就是會調用 Feign創建的動態代理,這是核心中的核心
  • Feign的動態代理會根據你在接口上的@RequestMApping等注解,來動態構造出你要請求的服務的地址
  • 最后針對這個地址,發起請求、解析響應
當時高并發項目差點讓我丟了工作!看我如何配置優化

 

四、Spring Cloud核心組件:Ribbon

服務集群部署:如果庫存服務部署了3臺怎么辦,如下所示:

  • 192.168.10.10:7000
  • 192.168.10.11:7000
  • 192.168.10.13:7000

問題來了,Feign怎么知道該請求哪臺機器呢?這時就輪到Ribbon出馬了,其提供了解決微服務負載均衡的問題。Ribbon 是一個基于Http和TCP的客服端負載均衡工具,它是基于Netflix Ribbon實現的。它不像spring cloud服務注冊中心、配置中心、API網關那樣獨立部署,但是它幾乎存在于每個spring cloud 微服務中。包括feign提供的聲明式服務調用也是基于該Ribbon實現的。

  • Ribbon的負載均衡默認使用的最經典的Round Robin輪詢算法。如果訂單服務對庫存服務發起10次請求,那就先讓你請求第1臺機器、然后是第2臺機器、第3臺機器,接著再來—個循環,第1臺機器、第2臺機器。。。以此類推。其他常見的負載均衡策略還包括權重輪詢WeightedResponseTimeRule,隨機策略RandomRule,最少并發數策略BestAvailableRule等等

此外,Ribbon是和Feign以及Eureka緊密協作,完成工作的,具體如下:

  • 首先Ribbon會從 Eureka Client里獲取到對應的服務注冊表,也就知道了所有的服務都部署在了哪些機器上,在監聽哪些端口號。
  • 然后Ribbon就可以使用默認的Round Robin算法,從中選擇一臺機器
  • Feign就會針對這臺機器,構造并發起請求

對上述整個過程,再來一張圖:

當時高并發項目差點讓我丟了工作!看我如何配置優化

 

 

五、Spring Cloud核心組件:Hystrix

斷路器,旨在通過熔斷機制控制服務和其依賴服務之間的延遲和故障。比如:在一個大型的微服務架構里,一個服務可能要依賴很多服務,像本文的業務場景,訂單服務依賴庫存服務、物流服務、積分服務三個服務。假設訂單服務最多只有100個線程可以處理請求,如果庫存服務掛了,一般會拋出一個異常。如果系統處于高并發的場景下,大量請求涌過來的時候,訂單服務的100個線程都會卡在請求庫存服務這塊,這導致訂單服務沒有一個線程可以處理請求,服務器完全不響應任何請求。

 

如上圖,這么多服務互相調用,要是不做任何保護的話,某一個服務掛了,就會引起連鎖反應,導致別的服務也掛。比如服務B掛了,會導致服務A的線程全部卡在請求服務B這里,沒有一個線程可以工作。上面這個,就是微服務架構中恐怖的服務雪崩問題

 

當時高并發項目差點讓我丟了工作!看我如何配置優化

 

  • 解決方式:

使用Hystrix。Hystrix是隔離、熔斷以及降級的一個框架。Hystrix處理方式是提供很多個小小的線程池(其中一種解決方式),比如訂單服務請求庫存服務是一個線程池,請求物流服務是一個線程池,請求積分服務是一個線程池。每個線程池里的線程就僅僅用于請求那個服務。

  • 打個比方:現在很不幸,服務B掛了,會咋樣?

當然會導致服務A的那個用來調用服務B的線程都卡死不能工作了啊!但是由于服務A調用服務C、服務D的這兩個線程池都是正常工作的,所以這兩個服務不會受到任何影響。但是如果服務B都掛了,服務A每次調用都要去卡住幾秒鐘干啥呢?有意義嗎?當然沒有!所以我們直接對服務B熔斷不就得了,比如在5分鐘內請求積分服務直接就返回了,不要去走網絡請求卡住幾秒鐘,這個過程,就是所謂的熔斷!如果服務A知道服務B已經熔斷了,可以做一些特殊的處理,比如返回一些兜底的數據或者友好的提示,這個過程,就是所謂的降級。

為幫助大家更直觀的理解,接下來用一張圖,梳理一下Hystrix隔離、熔斷和降級的全流程:

 

當時高并發項目差點讓我丟了工作!看我如何配置優化

 

 

六、Spring Cloud核心組件:Zuul

前面的文章我們介紹了,Eureka用于服務的注冊于發現,Feign和Ribbon支持服務的調用以及均衡負載,Hystrix處理服務的熔斷防止故障擴散我們還是少考慮了一個問題,外部的應用如何來訪問內部各種各樣的微服務呢?在微服務架構中,后端服務往往不直接開放給調用端,而是通過一個API網關根據請求的url,路由到相應的服務。當添加API網關后,在第三方調用端和服務提供方之間就創建了一面墻,這面墻直接與調用方通信進行權限控制,后將請求均衡分發給后臺服務

為什么需要微服務網關?

在微服務架構模式下后端服務的實例數一般是動態的,動態改變的服務實例的訪問地址信息很難被客戶端發現。因此在基于微服務的項目中為了簡化前端的調用邏輯,引入API Gateway作為輕量級網關,而且有一個網關之后,還有很多好處,比如可以做統一的降級、限流、認證授權、安全,等等。

 

當時高并發項目差點讓我丟了工作!看我如何配置優化

 

七、高并發下配置優化

  • 合理的hystrix線程池大小:

假設你的服務A,每秒鐘會接收30個請求,同時會向服務B發起30個請求,然后每個請求的響應時長經驗值大概在200ms,那么你的hystrix線程池需要多少個線程呢?計算公式是:30(每秒請求數量) * 0.2(每個請求的處理秒數) + 4(給點緩沖buffer) = 10(線程數量)。

為什么10個線程可以輕松抗住每秒30個請求?

一個線程200毫秒可以執行完一個請求,那么一個線程1秒可以執行5個請求,理論上,只要6個線程,每秒就可以執行30個請求。也就是說,線程里的10個線程中,就6個線程足以抗住每秒30個請求了。剩下4個線程都在玩兒,空閑著。那為啥要多搞4個線程呢?很簡單,因為你要留一點buffer空間。萬一在系統高峰期,系統性能略有下降,此時不少請求都耗費了300多毫秒才執行完,那么一個線程每秒只能處理3個請求了,10個線程剛剛好勉強可以hold住每秒30個請求。所以你必須多考慮留幾個線程。

  • 合理的超時時間設置

一個接口,理論的最佳響應速度應該在200ms以內,或者慢點的接口就幾百毫秒。如果一個接口響應時間達到1秒+,建議考慮用緩存、索引、NoSQL等各種你能想到的技術手段,優化一下性能。否則你要是胡亂設置超時時間是幾秒,甚至幾十秒,萬一下游服務偶然出了點問題響應時間長了點呢?那你這個線程池里的線程立馬全部卡死!合理的超時時間設置為多少?答案應該不超過300毫秒(這個需要根據實際壓測數據做些優化)。為啥呢?如果你的超時時間設置成了500毫秒,想想可能會有什么后果?考慮極端情況,如果服務B響應變慢,要500毫秒才響應,你一個線程每秒最多只能處理2個請求了,10個線程只能處理20個請求。大量的線程會全部卡死,來不及處理那么多請求,最后用戶會刷不出來頁面。如果你的線程池大小和超時時間沒有配合著設置好,很可能會導致服務B短暫的性能波動,瞬間導致服務A的線程池卡死,里面的線程要卡頓一段時間才能繼續執行下一個請求。哪怕一段時間后,服務B的接口性能恢復到200毫秒以內了,服務A的線程池里卡死的狀況也要好一會兒才能恢復過來。你的超時時間設置的越不合理,比如設置的越長,設置到了1秒、2秒,那么這種卡死的情況就需要越長的時間來恢復。所以說,此時你的超時時間得設置成300毫秒,保證一個請求300毫秒內執行不完,立馬超時返回。這樣線程池里的線程不會長時間卡死,可以有條不紊的處理多出來的請求,大不了就是300毫秒內處理不完立即超時返回,但是線程始終保持可以運行的狀態。這樣當服務B的接口性能恢復到200毫秒以內后,服務A的線程池里的線程很快就可以恢復。

八、總結:

總結一下,上述幾個Spring Cloud核心組件,在微服務架構中,分別扮演的角色:

  • Eureka:各個服務在啟動時,Eureka Client組件會將本服務注冊到Eureka Server,集群以應用名做區分,并且Eureka Client還可以反過來從Eureka Server拉取注冊表,從而知道其他服務在哪里
  • Ribbon:微服務之間發起請求的時候,基于Ribbon做負載均衡,從服務集群中選擇一臺
  • Feign:基于Feign的動態代理機制,根據注解和選擇的機器,拼接請求URL地址,發起請求
  • Hystrix:發起請求是通過Hystrix的線程池來走的,不同的服務走不同的線程池,實現了不同服務調用的隔離,避免了服務雪崩的問題
  • Zuul:微服務路由

當然spring cloud家族還有Spring Cloud Config、Spring Cloud Bus、Spring Cloud for Cloud Foundry、Spring Cloud Cluster、Spring Cloud Consul、Spring Cloud Security、Spring Cloud Sleuth、Spring Cloud Data Flow、Spring Cloud Stream、Spring Cloud Task、Spring Cloud Zookeeper、Spring Cloud Connectors、Spring Cloud Starters、Spring Cloud CLI等等,具體信息請查看:

中文文檔:https://springcloud.cc/

英文文檔:http://spring.io/projects/spring-cloud

來源:網易工程師-周延旭

分享到:
標簽:并發
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定