天天看點

《SpringCloud篇:002Ribbon服務之間的負載均衡》一、概述

一、概述

Ribbon是為了實作服務與服務之間調用的負載均衡,是用戶端負載均衡,并且預設采用輪詢的政策。(類似于Nginx,但是Ribbon是用于服務端的,Nginx是用戶端的)

找官方文檔

《SpringCloud篇:002Ribbon服務之間的負載均衡》一、概述

根據文檔配置pom依賴

《SpringCloud篇:002Ribbon服務之間的負載均衡》一、概述
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>           

複制

啟動類上加LoadBalance注解

package com.qf.springcloud.consumer;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
@ServletComponentScan(basePackages = "com.qf.springcloud.consumer")
public class ConsumerStarterApp {

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


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


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

複制

修改controller,改成直接通路就可以

package com.qf.springcloud.consumer.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.qf.springcloud.consumer.client.ProviderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@RestController
public class ConsumerController {

    /*@Autowired
    private EurekaClient eurekaClient;*/

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ProviderClient providerClient;

    @GetMapping("/consumer/test")
    public String test() throws InterruptedException {
        /*//1. 通過Eureka擷取PROVIDER服務的ip和port
        InstanceInfo provider = eurekaClient.getNextServerFromEureka("PROVIDER", false);
        String ip = provider.getIPAddr();
        int port = provider.getPort();

        //2. 通過RestTemplate調用provider的/provider/test
        String result = restTemplate.getForObject("http://" + ip + ":" + port + "/provider/test", String.class);*/

        /*
        //1. 通路目标服務
        String result = restTemplate.getForObject("http://PROVIDER/provider/test", String.class);
        */
        Thread.sleep(2000);
        System.out.println("test:" + Thread.currentThread().getName());
        String result = providerClient.test();
        //3. 傳回結果
        return result;
    }


    @GetMapping("/param/test/{type}")
    /*
    @HystrixCommand(fallbackMethod = "paramTestFallback",commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "20"),
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "30000"),
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "10")

    })
    */
    public Map paramTest(@PathVariable Integer type) throws InterruptedException {
        System.out.println("paramTest:" + Thread.currentThread().getName());
        if (type == 1){
            // path
            return providerClient.path(123);
        }else if (type == 2){
            int i = 1 / 0;
            // param
            return providerClient.param("張老三",233);
        }else{
            // body
            Map map = new HashMap();
            map.put("abcdefg","hijklmn");
            return providerClient.body(map);
        }
    }


    public Map paramTestFallback(Integer type){
        System.out.println("paramTestFallback:" + Thread.currentThread().getName());
        Map map = new HashMap();
        map.put("msg","我的Consumer自己出現了問題");
        return map;
    }
}           

複制

為了掩飾負載均衡,是以我們建立多個provider,複制原來的provider,在application.yml中修改它的端口号

spring:
  application:
    # 指定服務名稱
    name: provider



eureka:
  client:
    service-url:
      # 指定注冊到的eureka的位址資訊
      defaultZone: http://admin:admin@localhost:8761/eureka/,http://admin:admin@localhost:8762/eureka/



server:
  port: 8081           

複制

在controller也修改一下它的内容讓它們有所區分

package com.qf.springcloud.provider.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProviderController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/provider/test")
    public String test(){
        return "Hello Eureka!!!" + port;
    }

}           

複制

重新開機consumer,實作負載均衡(預設輪詢)

《SpringCloud篇:002Ribbon服務之間的負載均衡》一、概述
《SpringCloud篇:002Ribbon服務之間的負載均衡》一、概述

使用注解或者yml來修改複雜均衡政策

修改consumer中的啟動類,注解中的(随機效果)

package com.qf.springcloud.consumer;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
@ServletComponentScan(basePackages = "com.qf.springcloud.consumer")
public class ConsumerStarterApp {

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


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


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

複制

使用yml配置響應時間權重的負載均衡

PROVIDER:
 ribbon:
   NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightResponseTimeRule           

複制

重新開機,先以輪訓開始,然後根據響應時間配置設定權重