1. 程式人生 > >SpringCloud學習 - Ribbon負載均衡(客戶端)

SpringCloud學習 - Ribbon負載均衡(客戶端)

  1. Ribbon負載均衡(客戶端)

書籤:

(1)@LoadBalanced 負載均衡

(2)Ribbon自帶的負載規則

(3)Ribbon自定義負載規則

  1. @LoadBalanced 負載均衡

複製專案eureka-provider,生成eureka-provider-2,修改eureka-provider-2的埠成8091即可,請求返回的資訊改變一下:

@GetMapping("/t")
public Object t(){
   return "msg from provider-2";// 後面加個2,方便對比
}

 

修改eureka-consumer專案啟動類:主要是加上註解@LoadBalanced;請求服務提供者用服務名

package cn.ywj.eurekaconsumer;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@RestController
public class EurekaConsumerApplication {

   @Bean
   @LoadBalanced
   public RestTemplate getRestTemplate () {// 注入一個RestTemplate
      return new RestTemplate() ;
   }

   @Autowired
   private RestTemplate restTemplate;

   //@Autowired
   //private EurekaClient eurekaClient;

   @RequestMapping("/t")
   public Object t(){

      //InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("EUREKA-PROVIDER", false);// 通過服務名可以拿到地址
      String str = restTemplate.getForObject("http://EUREKA-PROVIDER/t", String.class);// 直接用服務名請求
      return str;
   }

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

 

 

啟動eureka-consumer專案,訪問:http://localhost:8082/t 返回的結果有時是:msg from provider,有時是:msg from provider-2,輪來輪去。

 

  1. Ribbon自帶的負載規則

package cn.ywj.eurekaconsumer;

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

@Configuration
public class RibbonConfiguration {

    @Bean
    public IRule ribbonRule() {
        return new RoundRobinRule();// 輪循演算法

        /*
        相關演算法

        一、RoundRobinRule :系統預設的規則,通過簡單地輪詢服務列表來選擇伺服器

        二、AvailabilityFilteringRule 該規則會忽略以下伺服器

            1、無法連線的伺服器 在預設情況下,如果 次連線失敗,該伺服器將會被置為“路”的狀態,該狀態將持續 30 秒;如果再次連線失敗, “短路”狀態的持續時間
            將會以幾何級數增加。可以通過修改 niws.loadbalancer. <clientName>.connectionFailureCountThreshold
            屬性,來配置連線失敗的次數

            2、併發數過高的伺服器:如果連線到該伺服器的併發數過高,也會被這個規則忽略,可以通過修改< lientName> .ribbon.ActiveConnectionsLirnit 屬性
            來設最高併發數

        三、WeightedResponseTimeRule :為每個伺服器賦予一個權重值 伺服器的響應時間越長,該權重值就越少,這個規則會隨機選擇伺服器,權重值有可能會決定伺服器選擇

        四、ZoneAvoidanceRule :該規則以區域、可用伺服器為基礎進行伺服器選擇。使用 Zone對伺服器進行分類,可以理解為機架或者機房

        五、BestAvailableRule :忽略“短路”的伺服器,並選擇併發數較低的伺服器。

        六、RandomRule :顧名思義,隨機選擇可用的伺服器。

        七、RerRule 含有重試的選擇邏輯,如果使用 RoundRobinRule 選擇的伺服器無法連線,那麼將會重新選擇伺服器。*/
    }
}

 

 

  1. Ribbon自定義負載規則

參考RandomRule.java類,簡單自定義一個規則 -- 只訪問第一個服務

建立DiyRibbon.java

DiyRibbon.java不能被@ComponentScan掃到!

DiyRibbon.java不能被@ComponentScan掃到!

DiyRibbon.java不能被@ComponentScan掃到!

package diy.ribbon;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 此類不能被@ComponentScan掃到
 */
public class DiyRibbon extends AbstractLoadBalancerRule {


    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object o) {
        return choose(getLoadBalancer(), o);
    }

    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        List<Server> upList = lb.getReachableServers();
        System.out.println("--->"+upList.size());
        if(upList != null && upList.size() > 0){
            return upList.get(0);// 拿第一個
        }
        return null;
    }
}

 

建立配置類:RibbonConfiguration.java

package cn.ywj.eurekaconsumer;

import com.netflix.loadbalancer.*;
import diy.ribbon.DiyRibbon;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RibbonConfiguration {

    @Bean
    public IRule ribbonRule() {

        return new DiyRibbon();// 自定義負載規則

        //return new RoundRobinRule();// 輪循演算法

        /*
        相關演算法

        一、RoundRobinRule :系統預設的規則,通過簡單地輪詢服務列表來選擇伺服器

        二、AvailabilityFilteringRule 該規則會忽略以下伺服器

            1、無法連線的伺服器 在預設情況下,如果 次連線失敗,該伺服器將會被置為“路”的狀態,該狀態將持續 30 秒;如果再次連線失敗, “短路”狀態的持續時間
            將會以幾何級數增加。可以通過修改 niws.loadbalancer. <clientName>.connectionFailureCountThreshold
            屬性,來配置連線失敗的次數

            2、併發數過高的伺服器:如果連線到該伺服器的併發數過高,也會被這個規則忽略,可以通過修改< lientName> .ribbon.ActiveConnectionsLirnit 屬性
            來設最高併發數

        三、WeightedResponseTimeRule :為每個伺服器賦予一個權重值 伺服器的響應時間越長,該權重值就越少,這個規則會隨機選擇伺服器,權重值有可能會決定伺服器選擇

        四、ZoneAvoidanceRule :該規則以區域、可用伺服器為基礎進行伺服器選擇。使用 Zone對伺服器進行分類,可以理解為機架或者機房

        五、BestAvailableRule :忽略“短路”的伺服器,並選擇併發數較低的伺服器。

        六、RandomRule :顧名思義,隨機選擇可用的伺服器。

        七、RerRule 含有重試的選擇邏輯,如果使用 RoundRobinRule 選擇的伺服器無法連線,那麼將會重新選擇伺服器。*/
    }
}

 

啟動類加入註解:@RibbonClient

package cn.ywj.eurekaconsumer;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.MalformedURLException;
import java.net.URI;

@SpringBootApplication
@RestController
@RibbonClient(name = "eureka-provider", configuration = RibbonConfiguration.class)// name是服務註冊者
public class EurekaConsumerApplication {

   @Bean
   @LoadBalanced
   public RestTemplate getRestTemplate () {// 注入一個RestTemplate
      return new RestTemplate() ;
   }

   @Autowired
   private RestTemplate restTemplate;

   //@Autowired
   //private EurekaClient eurekaClient;

   @RequestMapping("/t")
   public Object t(){

      //InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("EUREKA-PROVIDER", false);// 通過服務名可以拿到地址
      String str = restTemplate.getForObject("http://EUREKA-PROVIDER/t", String.class);// 直接用服務名請求
      return str;
   }

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

測試結果:怎麼重新整理都只是返回第一個provider返回的資訊。。。OK