springcloud-04-自定義ribbon的配置方式


在dubbo項目中, zookeeper即注冊中心幫我們實現了調度和負載均衡的能力, 這種方式被稱為服務器端的負載均衡, springcloud中, 使用ribben實現的客戶端負載均衡

什么是ribbon? 

Ribbon是Netflix發布的雲中間層服務開源項目,其主要功能是提供客戶端側負載均衡算法。Ribbon客戶端組件提供一系列完善的配置項如連接超時,重試等。簡單的說,Ribbon是一個客戶端負載均衡器,我們可以在配置文件中列出Load Balancer后面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連接等)去連接這些機器,我們也很容易使用Ribbon實現自定義的負載均衡算法。

eureka使用ribbon的大致架構

 

 

Ribbon工作時分為兩步:第一步先選擇 Eureka Server, 它優先選擇在同一個Zone且負載較少的Server;第二步再根據用戶指定的策略,在從Server取到的服務注冊列表中選擇一個地址。其中Ribbon提供了多種策略,例如輪詢round robin、隨機Random、根據響應時間加權等。

 

通過代碼實現: 

將剛才的cosumer-movie改造成ribbon的項目

添加一個注解類, 需要放置在mainClass掃描不到的包下, 或者在mainClass中通過@COmponentScan進行過濾

這兒使用的是注解過濾, 所以首先需要一個注解: 

package com.wenbronk.cosumer.ribben.annotation;

/**
 * 自定義注解, 排除不想被掃描到的內容
 * Created by wenbronk on 2017/5/18.
 */
public @interface ExcudeAnnotation {
}

然后是一個ribbon的注解聲明類: 

package com.wenbronk.cosumer.ribben.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.wenbronk.cosumer.ribben.annotation.ExcudeAnnotation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 默認規則為輪詢, 這個為隨機規則
 * 該類必須放置在掃描不到的包下, 或者添加排除, 雖然他必須有注解
 * Created by wenbronk on 2017/5/18.
 */
@Configuration
@ExcudeAnnotation
public class MyRibbonConfig {

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

}

在mainClass中進行過濾

package com.wenbronk.cosumer.ribben;

import com.wenbronk.cosumer.ribben.annotation.ExcudeAnnotation;
import com.wenbronk.cosumer.ribben.config.MyRibbonConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.client.RestTemplate;

/**
 * 通過RIbbonClient自定義ribbon客戶端
 * Created by root on 2017/5/18.
 */
@SpringBootApplication
@EnableEurekaClient
// 使用此規則不可放在 可掃描的路徑下, 如果非要放置, 需要加自定義注解
@RibbonClient(name = "microserver-provider-user", configuration = MyRibbonConfig.class)
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {ExcudeAnnotation.class})})
public class MovieRibbenApplication {

    /**
     * 使用LoadBalanced開啟客戶端負載均衡的功能
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

}

驗證: 

通過配置端口, 將user服務啟動4個實例, 並注冊為2個服務, 在movie-ribbon的controller中加入如下代碼

package com.wenbronk.cosumer.ribben.controller;

import com.wenbronk.cosumer.ribben.entity.User;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * Created by root on 2017/5/18.
 */
@RestController
public class MovieRibbenController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @RequestMapping("/movie/{id}")
    public User findById(@PathVariable Long id) {
        return restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);
    }

    @GetMapping("/test")
    public void test() {
        ServiceInstance instance = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER");
        System.out.println("111: " + instance.getServiceId() + ": " + instance.getHost() + ": " + instance.getPort());
//        System.out.println(instance.toString());

        ServiceInstance instance1 = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER-1");
        System.out.println("222: " + instance1.getServiceId() + ": " + instance1.getHost() + ": " + instance1.getPort());
//        System.out.println(instance1);
//        System.out.println(instance == instance1);
    }
}

通過瀏覽器重復的發送請求, 在控制台可看到只有provide-user 使用了我們自定義的規則, user-1 仍然使用的ribbon的默認規則輪詢

 

 通過配置文件的方式, 自定義ribbonclient:

從版本1.2.0開始,Spring Cloud Netflix現在支持使用屬性與Ribbon文檔兼容來自定義Ribbon客戶端

 配置的優先級: 配置文件 >  java代碼 > springcloud default

 

配置文件配置, 只需要在yml'中添加如下內容

users:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
NFLoadBalancerRuleClassName 是規則, 除了此規則 springcloud還有
每個規則可添加的類也有很多 

 

mainClass.java 

package com.wenbronk.cosumer.ribbon.yml;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * Created by wenbronk on 2017/5/20.
 */
@SpringBootApplication
@EnableEurekaClient
public class MoveiRibbonYmlApplicatoin {

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

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

MovieRibbonController

package com.wenbronk.cosumer.ribbon.yml.controller;

import com.wenbronk.cosumer.ribbon.yml.entity.User;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * Created by root on 2017/5/18.
 */
@RestController
public class MovieRibbenController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @RequestMapping("/movie/{id}")
    public User findById(@PathVariable Long id) {
        return restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);
    }

    @GetMapping("/test")
    public void test() {
        ServiceInstance instance = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER");
        System.out.println("111: " + instance.getServiceId() + ": " + instance.getHost() + ": " + instance.getPort());
//        System.out.println(instance.toString());

        ServiceInstance instance1 = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER-1");
        System.out.println("222: " + instance1.getServiceId() + ": " + instance1.getHost() + ": " + instance1.getPort());
//        System.out.println(instance1);
//        System.out.println(instance == instance1);
    }
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM