負(fù)載均衡-Ribbon

一. Ribbon概述

Spring Cloud Ribbon是基于Netflix Ribbon 實現(xiàn)的一套客戶端的負(fù)載均衡工具咽瓷,Ribbon客戶端組件提 供一系列的完善的配置舰讹,如超時,重試等匈睁。通過Load Balancer獲取到服務(wù)提供的所有機器實例桶错, Ribbon會自動基于某種規(guī)則(輪詢,隨機)去調(diào)用這些服務(wù)院刁。Ribbon也可以實現(xiàn)我們自己的負(fù)載均衡算法退腥。

二. 主流負(fù)載均衡

  • 集中式負(fù)載均衡

在消費者和服務(wù)提供方中間使用獨立的代理方式進行負(fù)載,有硬件的(比如 F5)享潜,也有軟件的(比如 Nginx)嗅蔬。

  • 客戶端負(fù)載均衡

客戶端會有一個服務(wù)器地址列表,在發(fā)送請求前通過負(fù)載均衡算法選擇 一個服務(wù)器艺蝴,然后進行訪問鸟废,這是客戶端負(fù)載均衡。

三. 常見負(fù)載均衡算法

算法就是從服務(wù)列表中按某個規(guī)則選取一個鼠冕。

  • 隨機撇叁,通過隨機選擇服務(wù)進行執(zhí)行,一般這種方式使用較少;

  • 輪訓(xùn)楞捂,負(fù)載均衡默認(rèn)實現(xiàn)方式趋厉,請求來之后排隊處理;

  • 加權(quán)輪訓(xùn)君账,通過對服務(wù)器性能的分型,給高配置椭蹄,低負(fù)載的服務(wù)器分配更高的權(quán)重净赴,均衡各個 服務(wù)器的壓力;

  • 地址Hash玖翅,通過客戶端請求的地址的HASH值取模映射進行服務(wù)器調(diào)度。

  • 最小鏈接數(shù)金度,即使請求均衡了猜极,壓力不一定會均衡,最小連接數(shù)法就是根據(jù)服務(wù)器的情況丢胚,比如請求積壓數(shù)等參數(shù)酬姆,將請求分配到當(dāng)前壓力最小的服務(wù)器上辞色。

服務(wù)每處理一個請求,請求數(shù)+1层亿,處理完-1. 新的請求來時選擇請求數(shù)最少的處理立美。這樣性能最好的服務(wù)器接收最多的請求建蹄。

四. Ribbon 模塊

  • ribbon- loadbalancer

負(fù)載均衡模塊,可獨立使用痛单,也可以和別的模塊一起使用劲腿。 Ribbon 內(nèi)置的負(fù)載均衡算法都實現(xiàn)在其中焦人。

  • ribbon-eureka

基于 Eureka 封裝的模塊,能夠快速忽匈、方便地集成 Eureka个从。

  • ribbon-transport

基于 Netty 實現(xiàn)多協(xié)議的支持,比如 HTTP嫌松、Tcp萎羔、Udp 等碳默。

  • ribbon-httpclient

基于 Apache HttpClient 封裝的 REST 客戶端,集成了負(fù)載均衡模塊髓废,可以直接在項目中使用來調(diào)用接口该抒。

  • ribbon-example

Ribbon 使用代碼示例,通過這些示例能夠讓你的學(xué)習(xí)事半功倍涌攻。

  • ribbon-core

一些比較核心且具有通用性的代碼频伤,客戶端 API 的一些配置和其他 API 的定義憋肖。

五. Ribbon 使用

5.1 直接使用

 // 服務(wù)列表
        List<Server> serverList = Lists.newArrayList(
                new Server("localhost", 8020),
                new Server("localhost", 8021));
        // 構(gòu)建負(fù)載實例
        ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder()
                .buildFixedServerListLoadBalancer(serverList);
        // 調(diào)用 5 次來測試效果
        for (int i = 0; i < 5; i++) {
            String result = LoadBalancerCommand.<String>builder()
                    .withLoadBalancer(loadBalancer).build()
                    .submit(new ServerOperation<String>() {
                        @Override
                        public Observable<String> call(Server server) {
                            String addr = "http://" + server.getHost() + ":" +
                                    server.getPort() + "/order/findOrderByUserId/1";
                                System.out.println(" 調(diào)用地址:" + addr);
                            URL url = null;
                            try {
                                url = new URL(addr);
                                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                conn.setRequestMethod("GET");
                                conn.connect();
                                InputStream in = conn.getInputStream();
                                byte[] data = new byte[in.available()];
                                in.read(data);
                                return Observable.just(new String(data));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            return null;
                        }
                    }).toBlocking().first();

            System.out.println(" 調(diào)用結(jié)果:" + result);
        }
    }

5.2 Spring Cloud快速整合Ribbon

<!‐‐添加ribbon的依賴‐‐> 
 <dependency> 
        <groupId>org.springframework.cloud</groupId> 
        <artifactId>spring‐cloud‐starter‐netflix‐ribbon</artifactId> 
 </dependency>

@Configuration 
public class RestConfig { 
     @Bean 
     @LoadBalanced
     public RestTemplate restTemplate() { 
           return new RestTemplate(); 
     } 
}
@Autowired 
private RestTemplate  restTemplate;  

@RequestMapping(value = "/findOrderByUserId/{id}") 
public R findOrderByUserId(@PathVariable("id") Integer id) { 
      
    String url = "http://mall‐order/order/findOrderByUserId/"+id;
    R result = restTemplate.getForObject(url,R.class);  
    return result; 
}

六. Ribbon原理

Ribbon 本質(zhì)上是基于RestTemplate 的擴展點婚肆,攔截原本請求后坐慰,利用負(fù)載均衡算法在服務(wù)列表中選出一個服務(wù)结胀,替換服務(wù)名實現(xiàn)負(fù)載均衡調(diào)用的。

Ribbon實現(xiàn)原理

@LoadBalanced 原理

1.LoadBalancerAutoConfiguration 自動注入

2.@LoadBalanced利用@Qualifier作為restTemplates注入的篩選條件攀操,篩選出具有負(fù)載均衡標(biāo)識的 RestTemplate速和。

  1. 被@LoadBalanced注解的restTemplate會被定制剥汤,添加LoadBalancerInterceptor攔截器。


    image.png

七. Ribbon 相關(guān)接口

源碼入口RibbonClientConfiguration

  • IRule:Ribbon的負(fù)載均衡策略,默認(rèn)采用ZoneAvoidanceRule實現(xiàn)鹿驼,該策略能夠在多區(qū)域環(huán)境下選出 最佳區(qū)域的實例進行訪問畜晰。
  • IPing:Ribbon的實例檢查策略,默認(rèn)采用DummyPing實現(xiàn)腊瑟,該檢查策略是一個特殊的實現(xiàn),實際上 它并不會檢查實例是否可用,而是始終返回true河胎,默認(rèn)認(rèn)為所有服務(wù)實例都是可用的虎敦。
  • ServerList:服務(wù)實例清單的維護機制,默認(rèn)采用ConfigurationBasedServerList實現(xiàn)胚迫。
  • ServerListFilter:服務(wù)實例清單過濾機制唾那,默認(rèn)采ZonePreferenceServerListFilter闹获,該策略能夠優(yōu)先 過濾出與請求方處于同區(qū)域的服務(wù)實例。
  • ILoadBalancer:負(fù)載均衡器龟虎,默認(rèn)采用ZoneAwareLoadBalancer實現(xiàn)鲤妥,它具備了區(qū)域感知的能力拱雏。

八. Ribbon負(fù)載均衡策略

即IRule的實現(xiàn)


IRule實現(xiàn)
  1. RandomRule: 隨機選擇一個Server古涧。
  2. RetryRule: 對選定的負(fù)載均衡策略機上重試機制,在一個配置時間段內(nèi)當(dāng)選擇Server不成功菇爪,則一直嘗試使用subRule的方式選擇一個可用的server柒昏。
  3. RoundRobinRule: 輪詢選擇职祷, 輪詢index届囚,選擇index對應(yīng)位置的Server是尖。
  4. AvailabilityFilteringRule: 過濾掉一直連接失敗的被標(biāo)記為circuit tripped的后端Server饺汹,并 過濾掉那些高并發(fā)的后端Server或者使用一個AvailabilityPredicate來包含過濾server的邏輯,其 實就是檢查status里記錄的各個Server的運行狀態(tài)迎瞧。
  5. BestAvailableRule: 選擇一個最小的并發(fā)請求的Server凶硅,逐個考察Server扫皱,如果Server被 tripped了,則跳過编检。
  6. WeightedResponseTimeRule: 根據(jù)響應(yīng)時間加權(quán)允懂,響應(yīng)時間越長衩匣,權(quán)重越小,被選中的可 能性越低生百。
  7. ZoneAvoidanceRule: 默認(rèn)的負(fù)載均衡策略蚀浆,即復(fù)合判斷Server所在區(qū)域的性能和 Server的可用性選擇Server搜吧,在沒有區(qū)域的環(huán)境下滤奈,類似于輪詢(RandomRule)
  8. NacosRule: 同集群優(yōu)先調(diào)用

九.自定義負(fù)載均衡策略

自定義

public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
      @Override 
      public Server choose(Object key) {
            .... .... ....
            return Server
      }
}

全局生效

@Configuration 
public class RibbonConfig { 
       /** 
         * 全局配置 
         * 指定負(fù)載均衡策略 
         * @return 
         */ 
  @Bean 
  public IRule() { 
       // 
       return new  NacosRandomWithWeightRule(); 
  } 
}

局部生效

//修改application.yml
# 被調(diào)用的微服務(wù)名 
   mall‐order: 
           ribbon: 
                 # 指定使用負(fù)載均衡策略 
                     NFLoadBalancerRuleClassName: xxxx.NacosRandomWithWeightRule

十. 饑餓加載

開啟饑餓加載蜒程,解決第一次調(diào)用慢的問題

 ribbon:
         eager‐load: 
                 # 開啟ribbon饑餓加載 
                 enabled: true 
                 # 配置mall‐user使用ribbon饑餓加載伺帘,多個使用逗號分隔 
                 clients: mall‐order
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伪嫁,一起剝皮案震驚了整個濱河市礼殊,隨后出現(xiàn)的幾起案子针史,更是在濱河造成了極大的恐慌啄枕,老刑警劉巖族沃,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脆淹,死亡現(xiàn)場離奇詭異,居然都是意外死亡漓糙,警方通過查閱死者的電腦和手機烘嘱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門蝇庭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哮内,“玉大人,你說我怎么就攤上這事纹因×詹Γ” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵从绘,是天一觀的道長寄疏。 經(jīng)常有香客問我是牢,道長,這世上最難降的妖魔是什么陕截? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任驳棱,我火速辦了婚禮,結(jié)果婚禮上农曲,老公的妹妹穿的比我還像新娘社搅。我一直安慰自己,他們只是感情好乳规,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著暮的,像睡著了一般笙以。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冻辩,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天猖腕,我揣著相機與錄音,去河邊找鬼恨闪。 笑死倘感,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咙咽。 我是一名探鬼主播老玛,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼钧敞!你這毒婦竟也來了逻炊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤犁享,失蹤者是張志新(化名)和其女友劉穎余素,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炊昆,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡桨吊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凤巨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片视乐。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖敢茁,靈堂內(nèi)的尸體忽然破棺而出佑淀,到底是詐尸還是另有隱情,我是刑警寧澤彰檬,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布伸刃,位于F島的核電站谎砾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捧颅。R本人自食惡果不足惜景图,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碉哑。 院中可真熱鬧挚币,春花似錦、人聲如沸扣典。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贮尖。三九已至笛粘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間远舅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工痕钢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留图柏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓任连,卻偏偏與公主長得像蚤吹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子随抠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容