Spring Cloud 學(xué)習(xí)(10) --- Ribbon(一) 負(fù)載均衡與 Ribbon

通常所說的負(fù)載均衡愿题,一般來說都是在服務(wù)器端使用 Ngnix 或 F5 做 Server 的負(fù)載均衡策略堪旧,在 Ribbon 中提到的負(fù)載均衡涩禀,一般來說是指的客戶端負(fù)載均衡,即 ServiceA 調(diào)用 ServiceB咆繁,有多個 ServiceB 的情況下讳推,由 ServiceA 選擇調(diào)用哪個 ServiceB。

負(fù)載均衡與 Ribbon

負(fù)載均衡(Load Balance)玩般,是一種利用特定方式银觅,將流量分?jǐn)偟蕉鄠€操作單元上的手段,它對系統(tǒng)吞吐量坏为、系統(tǒng)處理能力有著質(zhì)的提升究驴。最常見的負(fù)載均衡分類方式有:軟負(fù)載、硬負(fù)載匀伏,對應(yīng) Ngnix洒忧、F5;集中式負(fù)載均衡够颠、進(jìn)程內(nèi)負(fù)載均衡熙侍。集中式負(fù)載均衡是指位于網(wǎng)絡(luò)和服務(wù)提供者之間,并負(fù)責(zé)把忘了請求轉(zhuǎn)發(fā)到各個提供單位履磨,代表產(chǎn)品有 Ngnix蛉抓、F5;進(jìn)程負(fù)載均衡是指從一個實(shí)例庫選取一個實(shí)例進(jìn)行流量導(dǎo)入剃诅,在微服務(wù)范疇巷送,實(shí)例庫一般是存儲在 Eureka、Consul矛辕、Zookeeper 等注冊中心笑跛,此時的負(fù)載均衡器類似 Ribbon 的 IPC(進(jìn)程間通信)組件付魔,因此進(jìn)程內(nèi)負(fù)載均衡也叫做客戶端負(fù)載均衡。

Ribbon 是一個客戶端負(fù)載均衡器堡牡,賦予了應(yīng)用一些支配 HTTP 與 TCP 行為的能力抒抬,由此可以得知,這里的客戶端負(fù)載均衡也是進(jìn)程內(nèi)負(fù)載均衡的一周晤柄。 Ribbon 在 SpringCloud 生態(tài)內(nèi)的不可缺少的組件,沒有了 Ribbon妖胀,服務(wù)就不能橫向擴(kuò)展芥颈。Feign、Zuul 已經(jīng)集成了 Ribbon赚抡。


示例

Eureka Server 不再贅述爬坑,可以直接使用 spring-cloud-eureka-server-simple

Consumer

源碼:https://gitee.com/laiyy0728/spring-cloud/tree/master/spring-cloud-ribbon/spring-cloud-ribbon-consumer

yml:

spring:
  application:
    name: spring-cloud-ribbon-consumer

server:
  port: 9999

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${server.port}

配置類:

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

@LoadBalanced:對 RestTemplate 啟動負(fù)載均衡

Consumer Controller

@RestController
public class ConsumerController {

    private final RestTemplate restTemplate;

    @Autowired
    public ConsumerController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping(value = "/check")
    public String checkRibbonProvider(){
        return restTemplate.getForObject("http://spring-cloud-ribbon-provider/check", String.class);
    }

}

provider

源碼:https://gitee.com/laiyy0728/spring-cloud/tree/master/spring-cloud-ribbon/spring-cloud-ribbon-provider

pom 依賴:

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

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
</dependencies>

配置文件:

spring:
  application:
    name: spring-cloud-ribbon-provider

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${server.port}

ProviderContr

@RestController
public class ProviderController {

    @Value("${server.port}")
    private int port;

    @GetMapping(value = "/check")
    public String providerPort(){
        return "Provider Port: " + port;
    }
}

驗(yàn)證

分別啟動 Eureka Server涂臣、Consumer盾计、Provider,其中赁遗,Provider 以 mvn 形式啟動贴唇,綁定不同的端口號:

mvn spring-boot:run -Dserver.port=8080
mvn spring-boot:run -Dserver.port=8081

postman 訪問 Consumer


第一次請求

第二次請求

可以看到舰绘,Provider 兩次返回值不一樣,驗(yàn)證了負(fù)載均衡成功。


負(fù)載均衡策略

Ribbon 中提供了 七種 負(fù)載均衡策略

策略類 命名 描述
RandomRule 隨機(jī)策略 隨機(jī)選擇 Server
RoundRobinRule 輪詢策略 按照順序循環(huán)選擇 Server
RetryRule 重試策略 在一個配置時間段內(nèi)贸毕,當(dāng)選擇的 Server 不成功,則一直嘗試選擇一個可用的 Server
BestAvailableRule 最低并發(fā)策略 逐個考察 Server晶伦,如果 Server 的斷路器被打開而芥,則忽略,在不被忽略的 Server 中選擇并發(fā)連接最低的 Server
AvailabilityFilteringRule 可用過濾測試 過濾掉一直連接失敗耕姊,并被標(biāo)記未 circuit tripped(即不可用) 的 Server桶唐,過濾掉高并發(fā)的 Server
ResponseTimeWeightedRule 響應(yīng)時間加權(quán)策略 根據(jù) Server 的響應(yīng)時間分配權(quán)重,響應(yīng)時間越長茉兰,權(quán)重越低尤泽,被選擇到的幾率就越低
ZoneAvoidanceRule 區(qū)域權(quán)衡策略 綜合判斷 Server 所在區(qū)域的性能和 Server 的可用性輪詢選擇 Server,并判定一個 AWS Zone 的運(yùn)行性能是否可用邦邦,剔除不可用的 Zone 中的所有 Server

Ribbon 默認(rèn)的負(fù)載均衡策略是 輪詢策略安吁。

設(shè)置負(fù)載均衡策略

設(shè)置全局負(fù)載均衡

創(chuàng)建一個聲明式配置,即可實(shí)現(xiàn)全局負(fù)載均衡配置:

@Configuration
public class RibbonConfig {
    /**
     * 全局負(fù)載均衡配置:隨機(jī)策略
     */
    @Bean
    public IRule ribbonRule(){
        return new RandomRule();
    }

}

重啟 Consumer燃辖,訪問測試

基于注解的配置

空注解

聲明一個空注解鬼店,用于使用注解配置 Ribbon 負(fù)載均衡

public @interface RibbonAnnotation {
}

負(fù)載均衡配置類

@Configuration
@RibbonAnnotation
public class RibbonAnnoConfig {

    private final IClientConfig clientConfig;

    @Autowired(required = false)
    public RibbonAnnoConfig(IClientConfig clientConfig) {
        this.clientConfig = clientConfig;
    }

    @Bean
    public IRule ribbonRule(IClientConfig clientConfig){
        return new RandomRule();
    }
}

啟動類

@SpringBootApplication
@EnableDiscoveryClient

@RibbonClient(name = "spring-cloud-ribbon-provider", configuration = RibbonAnnoConfig.class)
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = RibbonAnnotation.class)})
public class SpringCloudRibbonConsumerApplication {

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

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

}

@RibbonClient:針對 spring-cloud-ribbon-provider 服務(wù),使用負(fù)載均衡黔龟,配置類是 configuration 標(biāo)注的類妇智。
@ComponentScan:讓 Spring 不去掃描被 @RibbonAnnotation 類標(biāo)記的配置類滥玷,因?yàn)槲覀兊呐渲脤蝹€服務(wù)生效,不能應(yīng)用于全局巍棱,如果不排除惑畴,啟動就會報錯

如果需要對多個服務(wù)進(jìn)行配置,可以使用 @RibbonClients 注解

@RibbonClients(value = {
        @RibbonClient(name = "spring-cloud-ribbon-provider", configuration = RibbonAnnoConfig.class)        
})

重啟 Consumer航徙,驗(yàn)證基于注解的負(fù)載均衡是否成功

基于配置文件的負(fù)載均衡策略

語法:

{instance-id}: # instance-id 即被調(diào)用服務(wù)名稱
    ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

Ribbon 配置

源碼:https://gitee.com/laiyy0728/spring-cloud/tree/master/spring-cloud-ribbon/spring-cloud-ribbon-config

超時與重試

HTTP 請求難免會出現(xiàn)請求超時如贷,此時對調(diào)用進(jìn)行時限的控制以及在時限之后的重試尤為重要。對于超時重試的配置如下:

{instance-id}: # instance-id 指的是被調(diào)用者的服務(wù)名稱
  ribbon:
    ConnectTimeout: 30000 # 鏈接超時時間
    ReadTimeout: 30000 # 讀超時時間
    MaxAutoRetries: 1 # 對第一次請求的服務(wù)的重試次數(shù)
    MaxAutoRetriesNextServer: 1 # 要重試的下一個服務(wù)的最大數(shù)量(不包括第一個服務(wù))
    OkToRetryOnAllOperations: true # 是否對 連接超時到踏、讀超時杠袱、寫超時 都進(jìn)行重試

Ribbon 饑餓加載

Ribbon 在進(jìn)行負(fù)載均衡時,并不是啟動時就加載上線文窝稿,而是在實(shí)際的請求發(fā)送時楣富,才去請求上下文信息,獲取被調(diào)用者的 ip伴榔、端口纹蝴,這種方式在網(wǎng)絡(luò)環(huán)境較差時,往往會使得第一次引起超時踪少,導(dǎo)致調(diào)用失敗塘安。此時需要指定 Ribbon 客戶端,進(jìn)行饑餓加載秉馏,即:在啟動時就加載好上下文耙旦。

ribbon:
  eager-load:
    enabled: true
    clients: spring-cloid-ribbon-provider

此時啟動 consumer,會看到控制打印信息如下:

Client: spring-cloid-ribbon-provider instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=spring-cloid-ribbon-provider,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
Using serverListUpdater PollingServerListUpdater
DynamicServerListLoadBalancer for client spring-cloid-ribbon-provider initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=spring-cloid-ribbon-provider,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@79e7188e

可以看到啟動時就加載了 spring-cloid-ribbon-provider萝究,并綁定了LoadBalancer

Ribbon 常用配置

配置項(xiàng) 說明
{instance-id}:ribbon.NFLoadBalancerClassName 指負(fù)載均衡器類路徑
{instance-id}:ribbon:NFLoadBalancerRuleClassName 指定負(fù)載均衡算法類路徑
{instance-id}:ribbom:NFLoadBalancerPingClassName 指定檢測服務(wù)存活的類路徑
{instance-id}:ribbon:NIWSServerListClassName 指定獲取服務(wù)列表的實(shí)現(xiàn)類路徑
{instance-id}:ribbon:NIWSServerListFilterClassName 指定服務(wù)的 Filter 實(shí)現(xiàn)類路徑

Ribbon 脫離 Eureka

默認(rèn)情況下免都,Ribbon 客戶端會從 Eureka Server 讀取服務(wù)注冊信息列表,達(dá)到動態(tài)負(fù)載均衡的功能帆竹。如果 Eureka 是一個提供多人使用的公共注冊中心(如 SpringCloud 中文社區(qū)公益 Eureka:http://eureka.springcloud.cn)绕娘,此時極易產(chǎn)生服務(wù)侵入問題,此時就不能從 Eureka 中讀取服務(wù)列表栽连,而應(yīng)該在 Ribbon 客戶端自行制定源服務(wù)地址

ribbon:
  eureka:
    enabled: false # Ribbon 脫離 Eureka 使用

{instance-id}:
  ribbon:
    listOfServers: http://localhost:8888 # 制定源服務(wù)地址
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末险领,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子秒紧,更是在濱河造成了極大的恐慌绢陌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熔恢,死亡現(xiàn)場離奇詭異脐湾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)叙淌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門秤掌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愁铺,“玉大人,你說我怎么就攤上這事闻鉴∫鹇遥” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵孟岛,是天一觀的道長瓶竭。 經(jīng)常有香客問我,道長蚀苛,這世上最難降的妖魔是什么在验? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮堵未,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盏触。我一直安慰自己渗蟹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布赞辩。 她就那樣靜靜地躺著雌芽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辨嗽。 梳的紋絲不亂的頭發(fā)上世落,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機(jī)與錄音糟需,去河邊找鬼屉佳。 笑死,一個胖子當(dāng)著我的面吹牛洲押,可吹牛的內(nèi)容都是我干的武花。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼杈帐,長吁一口氣:“原來是場噩夢啊……” “哼体箕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挑童,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤累铅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后站叼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娃兽,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年大年,在試婚紗的時候發(fā)現(xiàn)自己被綠了换薄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玉雾。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖轻要,靈堂內(nèi)的尸體忽然破棺而出复旬,到底是詐尸還是另有隱情,我是刑警寧澤冲泥,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布驹碍,位于F島的核電站,受9級特大地震影響凡恍,放射性物質(zhì)發(fā)生泄漏志秃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一嚼酝、第九天 我趴在偏房一處隱蔽的房頂上張望浮还。 院中可真熱鬧,春花似錦闽巩、人聲如沸钧舌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洼冻。三九已至,卻和暖如春隅很,著一層夾襖步出監(jiān)牢的瞬間撞牢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工叔营, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屋彪,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓审编,卻偏偏與公主長得像撼班,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子垒酬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345