SpringCloud---(5)Ribbon(客户端负载均衡器)

负载均衡两种方式:服务端负载均衡,客户端负载均衡。

 

Ribbon简介

 

       Ribbon是Netflix发布的云中间层服务开源项目,其主要功能是提供客户端侧负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单来说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询、随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。

 

下图展示了Eureka使用Ribbon时的大致架构:

 

Ribbon工作是分为两步:

第一步:优先选择Eureka Server,它优先选择在同一个Zone且负载均衡较少的Server。

第二步:再根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略,例如轮询round robin、随机Random、根据响应时间加权等。

 

使用Ribbon来进行负载均衡的时候不需要添加依赖包,因为在添加Eureka依赖的时候就包含了Ribbon的依赖。

1.     在启动类的Rest上添加注解@LoadBalanced,该注解帮我们做负载均衡的工作。

2.     在Controller类将硬编码的IP改替换成注册到EurekaServer上的IP,称为Virtual IP(简称VIP)。

 

通过代码自定义配置Ribbon

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">

   <modelVersion>4.0.0</modelVersion>


   <artifactId>microservice-consumer-movie-ribbon</artifactId>

   <packaging>jar</packaging>


   <parent>

      <groupId>com.kevin.cloud</groupId>

      <artifactId>microservice-spring-cloud</artifactId>

      <version>0.0.1-SNAPSHOT</version>

      <relativePath/>

   </parent>


   <properties>

      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

      <java.version>1.8</java.version>

   </properties>


   <dependencies>

      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-web</artifactId>

      </dependency>


      <dependency>

         <groupId>org.springframework.cloud</groupId>

         <artifactId>spring-cloud-starter-eureka</artifactId>

      </dependency>


      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-actuator</artifactId>

      </dependency>

   </dependencies>


</project>

application.yml

server:

  port: 8010

spring:

  application:

    name: microservice-consumer-movie-ribbon

eureka:

  client:

    healthcheck:

      enabled: true

    service-url:

      defaultZone: http://kevin:123456@localhost:8761/eureka

  instance:

    prefer-ip-address: true

ConsumerMovieRibbonApplication.java

因为是将TestConfiguration.java放在与启动类同一行,所以在启动类需要添加注解

@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExcludeFromComponentScan.class)})

package com.keivn.cloud;

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;


/**

 *

 * @title   服务消费者

 * @description

 * @author caonanqing

 * @createDate 2018/11/7

 * @version 1.0

 */

@SpringBootApplication

@EnableEurekaClient    //注册到Eureka

@RibbonClient(name = "microservice-provider-user", configuration = TestConfiguration.class) //随机使用服务提供者

@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExcludeFromComponentScan.class)})

public class ConsumerMovieRibbonApplication {


   @Bean

   @LoadBalanced //该注解让Restful拥有负载均衡的能力

   public RestTemplate restTemplate(){

      return new RestTemplate();

   }


   public static void main(String[] args) {

      SpringApplication.run(ConsumerMovieRibbonApplication.class, args);

      System.out.println("服务消费者启动...");

   }

}

ExcludeFromComponentScan.java

并在该类添加作为注解

package com.keivn.cloud;

/**

 *

 * @title

 * @description

 * @author caonanqing

 * @createDate 2018/11/8

 * @version 1.0

 */

public @interface ExcludeFromComponentScan {

}

TestConfiguration.java

 

package com.keivn.cloud;


import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.RandomRule;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;


/**

 *

 * @title

 * @description

 * @author caonanqing

 * @createDate 2018/11/8

 * @version 1.0

 */

@Configuration

@ExcludeFromComponentScan

public class TestConfiguration {


    //@Autowired

    //IClientConfig iClientConfig;


    //@Bean

    //public IRule ribbonRule(IClientConfig config){

    //    return new RandomRule();

    //}

    @Bean

    public IRule ribbonRule(){

        return new RandomRule();

    }


}

MovieController.java

 

microservice-provider-user和microservice-provider-user2分别是服务提供者在配置文件配置时的IP名称,在之前的文章就有,这里就不多说了

 

package com.keivn.cloud.controller;


import com.keivn.cloud.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.RestController;

import org.springframework.web.client.RestTemplate;


/**

 *

 * @title

 * @description

 * @author caonanqing

 * @createDate 2018/11/7

 * @version 1.0

 */

@RestController

public class MovieController {

    @Autowired

    private RestTemplate restTemplate;

    @Autowired

    private LoadBalancerClient loadBalancerClient;


    @GetMapping(value = "/movie/{id}")

    public User finById(@PathVariable long id ){

        //http://localhost:7900/simple/

        //VIP virtual IP

        return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);

    }


    @GetMapping("/test")

    public String test(){

        // 指定需要调用的服务

        ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");

        System.out.println("111: " + serviceInstance.getServiceId() + ": " +serviceInstance.getHost() + ": " + serviceInstance.getPort());


        ServiceInstance serviceInstance2 = this.loadBalancerClient.choose("microservice-provider-user2");

        System.out.println("222: "+ serviceInstance2.getServiceId() + ": " +serviceInstance2.getHost() + ": " + serviceInstance2.getPort());



        return "1";

    }


}

User.java

该实体类在本文章是通用的,所以下面就不再讲述

package com.keivn.cloud.entity;



import java.io.Serializable;

import java.math.BigDecimal;



/**

 *

 * @title

 * @description

 * @author caonanqing

 * @createDate 2018/11/7

 * @version 1.0

 */

public class User implements Serializable {



    private Long id;



    private String username;



    private String name;



    private Short age;



    private BigDecimal balance;



    public User() {

    }



    public User(Long id, String username, String name, Short age, BigDecimal balance) {

        this.id = id;

        this.username = username;

        this.name = name;

        this.balance = balance;

    }



    public Long getId() {

        return id;

    }



    public void setId(Long id) {

        this.id = id;

    }



    public String getUsername() {

        return username;

    }



    public void setUsername(String username) {

        this.username = username;

    }



    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public Short getAge() {

        return age;

    }



    public void setAge(Short age) {

        this.age = age;

    }



    public BigDecimal getBalance() {

        return balance;

    }



    public void setBalance(BigDecimal balance) {

        this.balance = balance;

    }

}

通过配置文件自定义配置Ribbon

application.yml

server:

  port: 8010

spring:

  application:

    name: microservice-consumer-movie-ribbon

eureka:

  client:

    healthcheck:

      enabled: true

    service-url:

      defaultZone: http://kevin:123456@localhost:8761/eureka

  instance:

    prefer-ip-address: true

microservice-provider-user:

  ribbon: #配置负载均衡的规则

    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

    #配置负载均衡的规则:响应时间加权的规则

    #NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

ConsumerMovieRibbonApplication.java

package com.keivn.cloud;


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;


/**

 *

 * @title   服务消费者

 * @description

 * @author caonanqing

 * @createDate 2018/11/7

 * @version 1.0

 */

@SpringBootApplication

@EnableEurekaClient    //注册到Eureka

public class ConsumerMovieRibbonApplication {

   @Bean

   @LoadBalanced //该注解让Restful拥有负载均衡的能力

   public RestTemplate restTemplate(){

      return new RestTemplate();

   }

   public static void main(String[] args) {

      SpringApplication.run(ConsumerMovieRibbonApplication.class, args);

      System.out.println("服务消费者启动...");

   }

}

MovieController.java

package com.keivn.cloud.controller;

import com.keivn.cloud.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.RestController;

import org.springframework.web.client.RestTemplate;


/**

 *

 * @title

 * @description

 * @author caonanqing

 * @createDate 2018/11/7

 * @version 1.0

 */

@RestController

public class MovieController {


    @Autowired

    private RestTemplate restTemplate;



    @Autowired

    private LoadBalancerClient loadBalancerClient;


    @GetMapping(value = "/movie/{id}")

    public User findById(@PathVariable long id ){

        //http://localhost:7900/simple/

        //VIP virtual IP

        //HAProxy Heartbeat

        ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");

        System.out.println("---: " + serviceInstance.getServiceId() + ": " +serviceInstance.getHost() + ": " + serviceInstance.getPort());



        return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);

    }


    @GetMapping("/test")

    public String test(){

        // 指定需要调用的服务

        ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");

        System.out.println("111: " + serviceInstance.getServiceId() + ": " +serviceInstance.getHost() + ": " + serviceInstance.getPort());



        ServiceInstance serviceInstance2 = this.loadBalancerClient.choose("microservice-provider-user2");

        System.out.println("222: "+ serviceInstance2.getServiceId() + ": " +serviceInstance2.getHost() + ": " + serviceInstance2.getPort());


        return "1";

    }

}

 

User.java(跟上面的一样)

 

Ribbon脱离Eureka的使用

 

Ribbon的依赖包包含在Eureka的依赖包里,所有pom.xml不必变更。

在配置文件中可以配置让Ribbon与Eureka脱离使用

application.yml

ribbon.eureka.enabled: false 使用该配置让Riboon可以跟eureka分离使用

server:

  port: 8010

spring:

  application:

    name: microservice-consumer-movie-ribbon-without-eureka

eureka:

  client:

    healthcheck:

      enabled: true

    service-url:

      defaultZone: http://kevin:123456@localhost:8761/eureka

  instance:

    prefer-ip-address: true

ribbon: #使用该配置让Riboon可以跟eureka分离使用

  eureka:

    enabled: false

microservice-provider-user:

  ribbon: #配置Ribbon能访问的为服务节点,多个节点使用逗号隔开

    listOfServers: localhost:7900, localhost:7902

    #配置负载均衡的规则:响应时间加权的规则

    #NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

ConsumerMovieRibbonApplication.java

package com.keivn.cloud;


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;


/**

 *

 * @title   服务消费者

 * @description

 * @author caonanqing

 * @createDate 2018/11/7

 * @version 1.0

 */

@SpringBootApplication // 使用SpringBoot开发微服务

//@EnableEurekaClient  //注册到Eureka

public class ConsumerMovieRibbonApplication {


   @Bean

   @LoadBalanced //该注解让Restful拥有负载均衡的能力

   public RestTemplate restTemplate(){

      return new RestTemplate();

   }


   public static void main(String[] args) {

      SpringApplication.run(ConsumerMovieRibbonApplication.class, args);

      System.out.println("服务消费者启动...");

   }

}

MovieController.java

package com.keivn.cloud.controller;

import com.keivn.cloud.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.RestController;

import org.springframework.web.client.RestTemplate;


/**

 *

 * @title

 * @description

 * @author caonanqing

 * @createDate 2018/11/7

 * @version 1.0

 */

@RestController

public class MovieController {

    @Autowired

    private RestTemplate restTemplate;

    @Autowired

    private LoadBalancerClient loadBalancerClient;

    @GetMapping(value = "/movie/{id}")

    public User findById(@PathVariable long id ){

        //http://localhost:7900/simple/

        //VIP virtual IP

        //HAProxy Heartbeat

        ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");

        System.out.println("---: " + serviceInstance.getServiceId() + ": " +serviceInstance.getHost() + ": " + serviceInstance.getPort());

        return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);

    }

    @GetMapping("/test")

    public String test(){

        // 指定需要调用的服务

        ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");

        System.out.println("111: " + serviceInstance.getServiceId() + ": " +serviceInstance.getHost() + ": " + serviceInstance.getPort());

        ServiceInstance serviceInstance2 = this.loadBalancerClient.choose("microservice-provider-user2");

        System.out.println("222: " + serviceInstance2.getServiceId() + ": " +serviceInstance2.getHost() + ": " + serviceInstance2.getPort());

        return "1";

    }

}

User.java(跟上面一样)

 

Ribbon负载均衡策略

 

Ribbon一共提供了7中负载均衡策略。

负载均衡的策略是在配置文件application.yml配置的

(比如:)

microservice-provider-user:
  ribbon:
#配置负载均衡的规则
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.负载均衡策略名称

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值