淺談SpringCloud (三) Ribbon負載均衡


什么是負載均衡

當一台服務器的單位時間內的訪問量越大時,服務器壓力就越大,大到超過自身承受能力時,服務器就會崩潰。為了避免服務器崩潰,讓用戶有更好的體驗,我們通過負載均衡的方式來分擔服務器壓力。

我們可以建立很多很多服務器,組成一個服務器集群,當用戶訪問網站時,先訪問一個中間服務器,在讓這個中間服務器在服務器集群中選擇一個壓力較小的服務器,然后將該訪問請求引入該服務器。如此以來,用戶的每次訪問,都會保證服務器集群中的每個服務器壓力趨於平衡,分擔了服務器壓力,避免了服務器崩潰的情況。

Ribbon

  Spring Cloud Ribbons是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。

  Spring Cloud Ribbon雖然只是一個工具類框架,它不像服務注冊中心、配置中心、API網關那樣需要獨立部署,但是它幾乎存在於每一個Spring Cloud構建的微服務和基礎設施中。因為微服務間的調用,API網關的請求轉發等內容,實際上都是通過Ribbon來實現的,包括后續我們將要介紹的Feign,它也是基於Ribbon實現的工具。所以,對Spring Cloud Ribbon的理解和使用,對於我們使用Spring Cloud來構建微服務非常重要。

 SpringCloud使用Ribbon

1.修改客戶端的pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>

<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">
    <parent>
        <artifactId>springclouddemo</artifactId>
        <groupId>com.aomeibox</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>customer-order</artifactId>

    <name>customer-order</name>
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>1.4.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- Ribbon 相關-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>1.1.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>

    </dependencies>

</project>

 

2.修改客戶端的MyConfig類

package com.aomeibox.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * Created by jl on 2018/12/27.
 */
@Configuration
public class MyConfig {

    @Bean
    @LoadBalanced  //負載均衡工具
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

 

3.修改客戶端的controller,通過在Eureka中注冊的ApplicaitonName進行訪問

package com.aomeibox.con;

import com.aomeibox.pojo.User;
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.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * Created by leo on 2018/12/24.
 */
@RestController
public class OrderController {

    @Autowired
    private RestTemplate template;//spring提供的一個用於訪問rest接口的模板對象
    private static final String url = "http://PROVIDER-USER";

//    @Autowired
//    private EurekaClient eurekaClient;

    @GetMapping("/order/{id}")
    public User getUser(@PathVariable Integer id){

//        InstanceInfo eureka = eurekaClient.getNextServerFromEureka("PROVIDER-USER", false);

        //訪問提供者獲取數據
//        User user = template.getForObject(eureka.getHomePageUrl()+"/user/"+ id, User.class);//通過訪問rest 獲取到json數據,然后轉換成User對象

        User user = template.getForObject(url+"/user/"+ id, User.class);

        return user;
    }
}

 

4.運行項目

 

Ribbon負載均衡策略

使用負載均衡帶來的好處很明顯:

  • 當集群里的1台或者多台服務器down的時候,剩余的沒有down的服務器可以保證服務的繼續使用
  • 使用了更多的機器保證了機器的良性使用,不會由於某一高峰時刻導致系統cpu急劇上升

負載均衡有好幾種實現策略,常見的有:

  • 隨機 (RandomRuler)
  • 輪詢 (RoundRobinRuler)   (默認)
  • 一致性哈希 (ConsistentHashRuler)
  • 哈希 (HashRuler)
  • 加權(WeightedRuler)

   RoundRobinRule輪詢策略表示每次都取下一個服務器,比如一共有5台服務器,第1次取第1台,第2次取第2台,第3次取第3台,以此類推。

   WeightedResponseTimeRule繼承了RoundRobinRule,開始的時候還沒有權重列表,采用父類的輪詢方式,有一個默認每30秒更新一次權重列表的定時任務,該定時任務會根據實例的響應時間來更新權重列表,choose方法做的事情就是,用一個(0,1)的隨機double數乘以最大的權重得到randomWeight,然后遍歷權重列表,找出第一個比randomWeight大的實例下標,然后返回該實例。

   BestAvailableRule策略用來選取最少並發量請求的服務器。

如果需要改變輪訓的策略,需要修改自己的配置類。

package com.aomeibox.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * Created by leo on 2018/12/27.
 */
@Configuration
public class MyConfig {//@Configuration + 本類  = applicationContext.xml文件

    @Bean
    @LoadBalanced  //負載均衡工具
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    public IRule myRule(){
        return new RandomRule();//隨機策略
    }

}

自定義負載均衡策略

1.主啟動類新增注解。注意,自己編寫的Rule類,不能和主啟動類放在同一個包下

 

package com.aomeibox;

import com.aomei.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 = "PROVIDER-USER",configuration = MySelfRule.class)//MySelfRule.class不能在本類的包或者子包下
public class CustomerOrder
{
    public static void main( String[] args )
    {
        SpringApplication.run(CustomerOrder.class);
    }
}

 

 

 

2.新增MyRule類。

package com.aomei;

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

/**
 * Created by leo on 2018/12/29.
 */
@Configuration
public class MySelfRule {

    @Bean
    public IRule myRule(){
        return new BestAvailableRule();
    }
}

Feign負載均衡

  上述的Ribbon功能很強大,可以自定義算法。

  Feign 是一個聲明web服務客戶端,這便得編寫web服務客戶端更容易,使用Feign 創建一個接口並對它進行注解,它具有可插拔的注解支持包括Feign注解與JAX-RS注解,Feign還支持可插拔的編碼器與解碼器,Spring Cloud 增加了對 Spring MVC的注解,Spring Web 默認使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的負載均衡的HTTP客戶端 Feign。

 

  上述大部分,我們通常是以微服務的ApplicaitonName進行訪問的。但是在開發編程過程中,我們通常是面向接口編程。因此出現了Feign。Feign可以使用接口+注解,調用其他項目的接口。

 

@FeignClient("provider-user")
public interface UserClient {
 
    @RequestMapping(method = RequestMethod.GET, value = "/getuser")
    public User getuserinfo();
     
    @RequestMapping(method = RequestMethod.GET, value = "/getuser")
    public String getuserinfostr();
     
    @RequestMapping(method = RequestMethod.GET, value = "/info")
    public  String  info();
 
}
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class, args);
    }
 
} 
@RestController
public class UserController {
 
    @Autowired
    UserClient userClient;
 
    @RequestMapping(value = "/getuserinfo", method = RequestMethod.GET)
    public User getuserinfo() {
        return userClient.getuserinfo();
    }
     
    @RequestMapping(value = "/getuserinfostr", method = RequestMethod.GET)
    public String getuserinfostr() {
        return userClient.getuserinfostr();
    }
     
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public String info() {
        return userClient.info();
    }
 
 
}

 


免責聲明!

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



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