SpringCloud——初級(二)Ribbon

Ribbon負載均衡服務調用

一、Ribbon概述

1、是什麼

Spring Cloud Ribbon 是基於Netflix Ribbon實現的一套客戶端負載均衡工具。主要功能是提供客戶端的軟件負載均衡算法和服務調用。
在這裏插入圖片描述
官網
Ribbon現在已經進入維護模式
未來替換方案:
Spring Cloud Starter Loadbalancer

2、能幹嘛

主要做負載均衡
Ribbon和Nginx的區別
在這裏插入圖片描述

1)集中式LB

即在服務的消費方和提供方之間使用獨立的LB設施(可以是硬件,如F5,也可以是軟件,如Nginx),由該設施負責把訪問請求通過某種策略轉發至服務的提供方;

2)進程內LB

將LB邏輯集成到消費方,消費方從服務註冊中心獲知有哪些地址可用,然後自己再從這些地址中選擇一個合適的服務器
Ribbon 就屬於進程內LB,它只是一個類庫,集成於消費方進程,消費方通過它來獲取到服務提供方的地址。

3)總結

前面講過了80通過輪詢負載訪問8001/8002
一句話——負載均衡+RestTemplate調用

二、Ribbon負載均衡演示

1、架構說明

總結:Ribbon其實就是一個軟負載均衡的客戶端組件,它可以和其他所需請求的客戶端結合使用,和eureka結合只是其中的一個實例
在這裏插入圖片描述
Ribbon在工作時分成兩步
第一步選擇EurekaServer ,它優先選擇在同一個區域內負載較少的server。
第二步再根據用戶指定策略,在從server取到的服務註冊列表中選擇一個地址。
其中Ribbon提供了多種策略:比如輪詢、隨機和根據響應時間加權。

2、pom

spring-cloud-starter-netflix-eureka-client
默認已經和Ribbon整合
在這裏插入圖片描述
查看源碼:
在這裏插入圖片描述
不需要再次引入Ribbon的依賴

3、二說RestTemplate

1)官網

RestTemplate官網

2)getForObject方法/getForEntity方法

區別:
getForObejct() 返回對象爲響應體重數據轉化成的對象,基本上可以理解爲Json
在這裏插入圖片描述
getForEntity() 返回對象爲ResponseEntity對象,包含了響應中的一些重要信息,比如響應頭、響應狀態碼、響應體等。
在這裏插入圖片描述

3)postForObject/postForEntity

4)GET請求方法

5)POST請求方法

三、Ribbon核心組件IRule

1、IRule:根據特定算法中從服務列表中選取一個要訪問的服務

在這裏插入圖片描述
1)com.netflix.loadbalancer.RoudRrobinRule——輪詢
2)com.netflix.loadbalancer.RandomRule——隨機
3)com.netflix.loadbalancer.RetryRule——先按照RoundRobinRul的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重試,獲取可用服務
4)WeightedesponseTimeRule——對RoundRobinRule的擴展,響應速度越快的實例選擇權重越大,越容易被選擇
5)BestAvailableRule——會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然後選擇一個併發量最下的服務
6)AvailabilityFilteringRule——先過濾掉故障實例,在選擇併發量較小的實例
7)ZoneAvoidanceRule——默認規則,複合判斷server所在區域的性能和server的可用性選擇服務器

2、如何替換

1)修改cloud-consumer-order80

2)注意配置細節

官方文檔明確給出了警告:
這個自定義配置類不能放在@ComponentScan所掃描的當前包下以及子包下,否則我們自定義的這個配置類就會被所有的Ribbon客戶端所共享,達不到特殊化定製的目的了。
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200404105047740.png?在這裏插入圖片描述

3)新建package(com.atguigu.myrule)

在這裏插入圖片描述

4)上面包下新建MySelfRule規則類

package com.atguigu.myrule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule(){
        return new RandomRule();//定義爲隨機
    }
}

5)主啓動類添加@RibbonClient

package com.atguigu.springcloud;

import com.atguigu.myrule.MySelfRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;


@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name="CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

6)測試

http://localhost/consumer/payment/get/35

四、Ribbon負載均衡算法

1、原理

負載均衡算法:rest接口第幾次請求數%服務器集羣總數量=實際調用服務器位置下標,每次服務重啓動後rest接口技術從1開始
在這裏插入圖片描述

2、源碼

在這裏插入圖片描述
PS:
在這裏插入圖片描述
CAS(compare and swap)自旋鎖,就是操作後會判斷內存值是否跟預期值一致,是則替換。

3、手寫

自己寫一個本地負載均衡器試試

1)7001/7002集羣啓動

2)8001/8002微服務改造——Controller

    @GetMapping("/payment/lb")
    public String getPaymentLB(){
        return serverPort;
    }

3)80訂單微服務改造

1、註釋掉@LoadBalanced註解
2、LoadBalancer接口

package com.atguigu.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;

import java.util.List;

public interface LoadBalancer {
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}

3、MyLB

package com.atguigu.springcloud.lb;


import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class MyLB implements LoadBalancer {
    private AtomicInteger atomicInteger=new AtomicInteger(0);
    public final int getAndIncrement(){
        int current;
        int next;
        do{
            current=this.atomicInteger.get();
            next=current>=2147483647?0:current+1;
        }while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("*******第幾次訪問次數next:"+next);
        return next;
    }
    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

4、OrderController

  @Resource
    private LoadBalancer loadBalancer;

    @Resource
    private DiscoveryClient discoveryClient;
    
   @GetMapping("/consumer/payment/lb")
    public String getPaymentLB(){
      List<ServiceInstance> instances=discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
      if(instances==null||instances.size()<=0){
          return null;
      }
      ServiceInstance serviceInstance=loadBalancer.instances(instances);
      URI uri = serviceInstance.getUri();
      return restTemplate.getForObject(uri+"/payment/lb",String.class);
    }

5、測試
http://localhost/consumer/payment/lb

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章