1. 程式人生 > 其它 >spring cloud 之 ribbon介紹

spring cloud 之 ribbon介紹

ribbon是負責負載均衡的,屬於程序內負載均衡。請求傳送到ribbon然後由ribbon傳送到各個服務.

服務端負載均衡:Nginx與F5集中式負載均衡指位於因特網與服務提供者之間,並負責把網路請求轉發到各個提供單位.

 

 程序內負載均衡是指從一個例項庫選取一個例項進行流量匯入,在微服務的範疇內,例項庫一般是儲存在Eureka、Consul、Zookeeper、etcd這樣的註冊中心,而此時的負載均衡器就是類似Ribbon的IPC(Inter-Process Communication,程序間通訊)元件,因此,程序內負載均衡也叫作客戶端負載均衡

 

 

Ribbon負載均衡策略

 

 

 

 

 可以在java配置檔案中配置自己需要的負載均衡策略如:

 

 

也可以在yml檔案中配置負載均衡的實現類:(注意:yml的配置高於java配置檔案,若同時配置了Java和yml則會選擇yml的配置)

 

 

bootstrap.yml中配置ribbon的其他配置:

 

 

 ribbon預設是懶載入,所以第一次請求會慢很多(它需要從註冊中心拿取服務例項列表,在進行自身策略的調整),為了避免這個問題使懶載入變為餓載入讓其在專案啟動時就載入,我們採用如下配置:

 

 

 ribbon1.2.0之後的版本支援了yml配置ribbon的行為,也就是說通過配置檔案能決定讓ribbon使用哪些實現類來完成負載均衡:

ribbon各個功能的介面:這些介面在用到的時候可查有哪些實現類,若有興趣也可自己實現具體實現類來配置。

 

 

 自定義配置實現類的列表:

 配置具體功能的實現類如:

 

 

 由於ribbon因為是以eureka client的身份去連線eureka server,從而拿到各個服務例項的列表去做負載均衡,所以當eureka server是一個社群型的公共註冊中心時,可能下面的例項有的是你不需要的。這時候就沒必要從eureka server來拿服務例項了,可自行配置需要的服務例項如下配置:

1.先關掉從eureka那服務例項列表的開關:

 

 

 2.在配置需要做負載均衡的例項:

 

 

 程式碼:

啟動類:負載均衡依靠@LoadBalanced註解修飾過的RestTemplate來實現。具體原理可通過原始碼@loadBalanced註解內部註釋或網上介紹檢視。

package cn.springcloud.book;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.client.RestTemplate;

import cn.springcloud.book.config.AvoidScan;
import cn.springcloud.book.config.TestConfiguration;

@SpringBootApplication
@EnableDiscoveryClient
@RibbonClient(name = "client-a", configuration = TestConfiguration.class)
//@RibbonClients(value = {
//        @RibbonClient(name = "client-a", configuration = TestConfiguration.class),
//        @RibbonClient(name = "client-b", configuration = TestConfiguration.class)
//})
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {AvoidScan.class})})
public class RibbonLoadbalancerApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonLoadbalancerApplication.class, args);
    }
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

自定義註解:該註解是個空註解,主要是為了讓啟動類中的掃描註解過濾掉改擁有該註解的類。

package cn.springcloud.book.config;

public @interface AvoidScan {

}

配置類:

package cn.springcloud.book.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;

@Configuration
@AvoidScan
public class TestConfiguration {
    
    @Autowired
    IClientConfig config;

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

controller類:該類是接收外部請求,拿到請求後先確定是哪個服務,之後在負載均衡到該服務下的某個服務例項上。

package cn.springcloud.book.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class TestController {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private LoadBalancerClient lbClient;

    @GetMapping("/add")
    public String adda(Integer a, Integer b) {
        String result = restTemplate
                .getForObject("http://CLIENT-A/add?a=" + a + "&b=" + b, String.class);
        System.out.println(result);
        return result;
    }
    
    @GetMapping("/add1")
    public void add1(Integer a, Integer b) {
        ServiceInstance instance = this.lbClient.choose("client-a");
        System.out.println(instance.getHost()+":"+instance.getPort());
    }
    
    @GetMapping("/add2")
    public void add2(Integer a, Integer b) {
        ServiceInstance instance = this.lbClient.choose("client-b");
        System.out.println(instance.getHost()+":"+instance.getPort());
    }
}

 

 

 

 bootstrap.yml

spring:
  application:
    name: ribbon-loadbalancer
server:
  port: 7777
eureka:
  client:
    serviceUrl:
      defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8888}/eureka/
  instance:
    prefer-ip-address: true
#client-a:
#  ribbon:
#    ConnectTimeout: 3000
#    ReadTimeout: 60000
#    MaxAutoRetries: 1 #對第一次請求的服務的重試次數
#    MaxAutoRetriesNextServer: 1 #要重試的下一個服務的最大數量(不包括第一個服務)
#    OkToRetryOnAllOperations: true
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule#
#ribbon:
#  eager-load:
#    enabled: true
#    clients: client-a, client-b, client-c

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.springcloud.book</groupId> 父類為spring boot 2.0.0
        <artifactId>ch5-2</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>ch5-2-ribbon-loadbalancer</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>