eureka 服務注冊發(fā)現
1.spring Cloud 不能算是一門技術缀磕,他是一套解決微服務架構設計的方案,他包含了各種組件梆奈,比如注冊中心野崇,斷路器,配置中心亩钟,集成路由等乓梨。
2.spring Cloud現在主流的三種生態(tài)主要是由,奈飛清酥,阿里和spring官網分別針對不同的是同場景自研的一套工具扶镀。
3.spring Cloud是基于springBoot來使用的,在使用spring Cloud的時候不同的springBoot版本需要搭配不同的spring Cloud版本來使用焰轻,亂用版本的話可能會存在問題臭觉,一般是有一個對照表的,按照對照表來使用基本不會出現問題辱志。
4.注冊中心的設計滿足cap原則
- c:可靠性:集群中主節(jié)點節(jié)掛掉了蝠筑,整個集群都停止對外提供服務,一直到從新選出一個新的主節(jié)點揩懒,并且所有節(jié)點數據都同步完成才開始對外提供服務菱肖。
- a:可用性:集群中的主節(jié)點掛掉了不影響其它節(jié)點,其它節(jié)點還是正常運行旭从,可能會存在節(jié)點數據不一致問題稳强,但是這是可以接受的。
- p:區(qū)域安全隔離性:注冊中心集群部署一主多從和悦,寫入數據直接寫入主節(jié)點退疫,讀取的時候從節(jié)點讀。主節(jié)點被寫入數據后要需要同步給集群中的從節(jié)點鸽素,同步過程中會存在一定的延遲
一般注冊中心的設計過程中至少要滿足其中的兩個褒繁,一般p是固定的一定會滿足,剩下的就是c和a選其一馍忽,zookeeper他是滿足cp的棒坏,eureka滿足的是ap。
注冊中心的作用:
集群中的服務注冊與發(fā)現遭笋,服務提供者把服務注冊等到注冊中心坝冕,服務消費者到注冊中心查找自己想要調用的服務,找到后拿到ip+port然后去調用自己需要調用的服務瓦呼。
做一個注冊中心的設計需要滿足哪些條件喂窟?
- 注冊中心要有一個容器(list)主要用來裝注冊的服務。
- 調用者服務需要把注冊中心容器中保存的已經注冊到注冊中心的服務拉取到本地做緩存,這樣就可以不用每次調用接口都到注冊中心找地址磨澡。
- 注冊中心不能無限期的保存所有的提供者的服務碗啄,需要定期的判斷服務是否掛掉了,所以需要定期去檢查服務的心跳稳摄,檢查服務的健康情況稚字。
- 注冊中心定期檢查已注冊服務的心跳,如果長時間沒有回應需要把服務從注冊中心刪除厦酬。
- 注冊到注冊中心的服務尉共,需要定期的向注冊中心發(fā)送心跳,防止注冊中心把自己的服務給刪除了
- 服務發(fā)送心跳的頻率要高于注冊中心的檢查的頻率弃锐,不然服務就會被注冊中心刪除
- 如果注冊中心在一次檢查服務心跳的時候發(fā)現大部分服務心跳都失效了袄友,注冊中心不會刪除任何一個注冊到注冊中心的服務,因為eureka滿足的是ap的原則霹菊,即可以容忍數據的不準確性剧蚣,以可用性為主。
配置文件詳解
- eviction-interval-timer-in-ms: 10000 #注冊中心定期剔除服務列表中失效的服務地址
- enable-self-preservation: true # server自我保護機制旋廷,避免因為網絡原因造成誤刪除
- renewal-percent-threshold: 0.85 # 如果在同一個機房中低于85%的服務沒有正常運行(正常續(xù)約的服務小于85%)注冊中心不會刪除任何服務鸠按,保障其可用性
- renewal-percent-threshold應該是同一時間正常續(xù)約的服務低于85%,就啟動自我保護機制,防止因為網絡原因導致客戶端續(xù)約失敗饶碘,影響客戶端之間相互的調用目尖,因為為了保障其可用性,客戶端會從注冊中心定期拉取注冊信息到客戶端本地緩存扎运∩客戶端有緩存地址的情況下只要注冊中心不刪除注冊信息,等網絡恢復后還可以繼續(xù)用豪治。這個也跟eureka的設計原則相關洞拨,因為eureka滿足的是AP高可用性,寧愿提供錯誤的服務也要保障服務的可用性负拟。
服務發(fā)現
spring cloud 是頂級社區(qū)烦衣,他提供了頂級接口,其它廠商都要按照他提供的接口標準去實現掩浙,這樣的好處就是無論哪家廠商提供的框架和組件都可以構建相同的微服務架構花吟,就算不同廠家混著用都可以。
服務發(fā)現的意思就是a服務從注冊中心獲取b服務的注冊信息厨姚,并且緩存在本地隨時可以找到b服務并且調用b服務的接口衅澈。
ribbon 客戶端負載均衡
ribbon理解
- ribbon負責的是消費者端的負載均衡
- 消費者從注冊中心獲取provider的地址,并且緩存在本地
- consumer調用provider的請求會被ribbon攔截并且會做負載均衡遣蚀。
- 負載均衡默認是輪詢矾麻,也可以選擇隨機或者自定義負載均衡的規(guī)則
ribbon負載均衡和 nginx負載均衡的區(qū)別
如上圖nginx負載均衡和ribbon的負載均衡的區(qū)別是,nginx是對外的芭梯,而ribbon相當于是spring cloud集群內部消費者客戶端調用提供者的負載均衡险耀,兩個使用場景是不一樣的。
hystrix
作用
hystrix斷路器(熔斷器)玖喘,可以防止微服務集群雪崩甩牺,斷路器打開訪問服務提供者會直接快速返回不會真的訪問,使用openfeign時請求會被hystrix代理累奈,hystrix的本質就是代理對服務提供者的調用贬派,因為只有代理請求才可以去做熔斷。
手寫斷路器
思路
三種狀態(tài) 開澎媒,關搞乏,半開
- 開:統(tǒng)計失敗次數,失敗次數到達閾值不在調用服務提供者
- 關:關閉狀態(tài)不在調用直接返回
- 半開:時間窗口戒努,處于關閉狀態(tài)時開始即時到達窗口期请敦,設置狀態(tài)為半開,半開狀態(tài)储玫,設置20%的請求可以訪問到提供者侍筛,如果訪問成功修改狀態(tài)為開。
hystrix 配置
配置解釋
hystrix: #hystrix的全局控制
command:
default: #default是全局控制撒穷,也可以換成單個方法控制匣椰,把default換成方法名即可
circuitBreaker:
enabled: true #開啟斷路器
requestVolumeThreshold: 3 #失敗次數(閥值) 20s內調用失敗次數超過3次開啟熔斷器
sleepWindowInMilliseconds: 20000 #窗口時間 20s
errorThresholdPercentage: 60 #失敗率 20s內調用失敗率超過60%開啟熔斷器
execution:
isolation:
Strategy: thread #隔離方式 thread線程隔離集合和semaphore信號量隔離級別
thread:
timeoutInMilliseconds: 3000 #調用超時時長
fallback:
isolation:
semaphore:
maxConcurrentRequests: 1000 #信號量隔離級別最大并發(fā)數
隔離方式
- 隔離方式 兩種隔離方式 thread線程池 按照group(10個線程)劃分服務提供者,用戶請求的線程和做遠程的線程不一樣
- 好處 當B服務調用失敗了 或者請求B服務的量太大了 不會對C服務造成影響 用戶訪問比較大的情況下使用比較好 異步的方式
- 缺點 線程間切換開銷大端礼,對機器性能影響
- 應用場景 調用第三方服務 并發(fā)量大的情況下
- SEMAPHORE信號量隔離 每次請進來 有一個原子計數器 做請求次數的++ 當請求完成以后 --
- 好處 對cpu開銷小
- 缺點 并發(fā)請求不易太多 當請求過多 就會拒絕請求 做一個保護機制
- 場景 使用內部調用 禽笑,并發(fā)小的情況下
- 源碼入門 HystrixCommand AbstractCommand HystrixThreadPool
Sleuth與Zipkin 分布式鏈路追蹤
理論
- sleuth 收集微服務中接口調用的信息并且把信息上傳到zipKin供zipKin分析接口的調用鏈路。
- zipKin 獨立部署蛤奥,提供可視化界面蒲每,可以在可視化界面中查看請求的調用鏈路信息,請求從客戶端發(fā)起喻括,經過了哪些服務邀杏,每個服務花費的時間等都可在可視化界面查看。收集過來的信息默認保存在內存中唬血,也可通過配置把他保存在mysql望蜡,mongoDB等持久化存儲數據庫中。
- Sleuth與Zipkin主要作用是收集請求調用的鏈路(一個請求經過了幾個微服務)信息拷恨,然后再把信息上傳到zipKin,zipKin對這些數據進行保存脖律,分析和展示暖庄。開發(fā)者可以根據zipKin上面保存的鏈路調用數據黄刚,分析請求在鏈路調用過程中的哪個環(huán)節(jié)花費的時間比較長,從而對其進行優(yōu)化肢预。
配置和集成
官方提供一鍵腳本
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar
如果用 Docker 的話,直接
docker run -d -p 9411:9411 openzipkin/zipkin
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
probability: 1 #配置采樣率 默認的采樣比例為: 0.1微姊,即 10%酸茴,所設置的值介于 0 到 1 之間,1 則表示全部采集
rate: 10 #為了使用速率限制采樣器,選擇每秒間隔接受的trace量兢交,最小數字為0薪捍,最大值為2,147,483,647(最大int) 默認為10。
springboot admin
- admin服務端可以從eureka上面拉取客戶端的ip+port,從而建立和client端的心跳配喳,保持對client服務的監(jiān)聽
- spring-boot-admin+spring-boot-actuator一塊使用可以監(jiān)聽微服務集群中的每臺服務的運行情況
gateway
網關作用
- 轉發(fā)酪穿,前端請求都請求到網關,通過網關把接口轉發(fā)到不同的服務晴裹。
- 保護安全被济,請求直接到網關可以不暴漏微服務集群中的服務的ip+port
- 負載均衡
- 網關就是一連串的過濾器來實現的,過濾器分為全局過濾器和局部過濾器
nginx和gateway使用場景
- 網關和nginx兩個都是做請求轉發(fā)的涧团,nginx是服務器級別的請求轉發(fā)溉潭,網關是程序級別的請求轉發(fā),網關的級別要比nginx級別低
- nginx是使用c語言寫的網關底層是webflux做轉發(fā)效率都很高少欺,但是nginx的性能效率是強于網關的
- nginx可以給網關做負載均衡
- gateway高度集成eureka喳瓣,和ribbon結合實現了負載均衡
- nginx做負載均衡每次都需要修改配置文件,gateway繼承了eureka可以直接從注冊中心拉取服務地址做負載均衡赞别。
- nginx 級別最高可以給網關做負載均衡前端請求到了ng之后由ng來決定請求哪個網關畏陕。
- 網關級別第二可以給集群中的消費者類型的服務提供負載均衡,請求到了網關之后由網關決定調用哪個消費者服務仿滔。
- ribbon級別最低是給集群中的提供者提供負載均衡惠毁,請求到了消費者服務,由ribbon決定訪問哪個提供者
gateway+eureka負載均衡實現原理
網關路由轉發(fā)和負載均衡實現
- 直接再配置文件配置單服務的路由轉發(fā)
spring:
application:
name: gate-server
cloud:
gateway:
enabled: true # =只要加了依賴 默認開啟
routes: # 如果一個服務里面有100個路徑 如果我想做負載均衡 ?? 動態(tài)路由
#方式一崎页,配置單個的服務地址做路由轉發(fā)
#請求方式 http://localhost/login
- id: login-service-route # 這個是路由的id 保持唯一即可
uri: http://localhost:8081 # uri統(tǒng)一資源定位符 url 統(tǒng)一資源標識符
predicates: # 斷言是給某一個路由來設定的一種匹配規(guī)則 默認不能作用在動態(tài)路由上
- Path=/login # 匹配規(guī)則 只要你Path匹配上了/doLogin 就往 uri 轉發(fā) 并且將路徑帶上
- 在配置文件配置相同名稱的多臺服務的轉發(fā)和負載均衡鞠绰,要集成eureka從注冊中心獲取服務地址才可以做負載均衡
spring:
application:
name: gate-server
cloud:
gateway:
enabled: true # =只要加了依賴 默認開啟
routes: # 如果一個服務里面有100個路徑 如果我想做負載均衡 ?? 動態(tài)路由
# 方式二,通過配置lb協(xié)議和應用名稱做路由轉發(fā)和負載均衡
# 請求方式 http://localhost/testRibbonBalance
- id: provider-route # 這個是路由的id 保持唯一即可
uri: lb://provider # lb負載均衡協(xié)議飒焦,provider服務名稱蜈膨,通過網關訪問provider服務的path會通過這個配置做負載均衡
predicates: # 斷言是給某一個路由來設定的一種匹配規(guī)則 默認不能作用在動態(tài)路由上
- Path=/** # 匹配規(guī)則 只要你Path匹配上了/doLogin 就往 uri 轉發(fā) 并且將路徑帶上
- 開啟動態(tài)代理訪問的時候path一級路徑加上服務名稱就可實現eureka集群中所有服務的轉發(fā)和負載均衡
spring:
application:
name: gate-server
cloud:
gateway:
enabled: true # =只要加了依賴 默認開啟
# 方式三, 通過打開動態(tài)路由的配置來做路由轉發(fā)和負載均衡
# 請求方式 http://localhost/provider/testRibbonBalance
discovery:
locator:
enabled: true # 開啟動態(tài)路由 開啟通用應用名稱 找到服務的功能
lower-case-service-id: true # 開啟服務名稱小寫
- 在代碼中實現轉發(fā)功能
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("guochuang-id",r->r.path("/guochuang").uri("https://www.bilibili.com/guochuang"))
.route("dance-id",r->r.path("/v/dance").uri("https://www.bilibili.com"))
.route("kichiku-id",r->r.path("/v/kichiku").uri("https://www.bilibili.com"))
.build();
}