1.Ribbon简介

(1).Ribbon介绍

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

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

(2).Ribbon作用

Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡(LB)的工具。

LB(负载均衡):集中式LB进程内LB。

  集中式LB:即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;

F5:https://baike.baidu.com/item/F5%E6%96%B9%E6%A1%88/1121377?fr=aladdin

进程内LB:将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。

Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

官方文档:

https://github.com/Netflix/ribbon/wiki

https://github.com/Netflix/ribbon/wiki/Getting-Started

2.Ribbon配置

修改microservicecloud-consumer-dept-80工程

(1).修改pom.xml文件

修改部分:

<!-- Ribbon相关 -->

    <dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

</dependencies>

完整部分:

<?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>microservicecloud</artifactId>

<groupId>com.hosystem</groupId>

<version>1.0-SNAPSHOT</version>

</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-consumer-dept-80</artifactId>

<!--<description>部门微服务消费者</description>-->

    <dependencies>

<dependency><!-- 自己定义的api -->

            <!--注意:groupId我们需要由com.hosystem.springcloud 变成com.hosystem就不会出现'Dependency 'com.hosystem.springcloud:microservicecloud-api:1.0-SNAPSHOT' not found'错误-->

            <groupId>com.hosystem</groupId>

<artifactId>microservicecloud-api</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

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

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

</dependency>

<!-- 修改后立即生效,热部署 -->

        <dependency>

<groupId>org.springframework</groupId>

<artifactId>springloaded</artifactId>

</dependency>

<dependency>

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

<artifactId>spring-boot-devtools</artifactId>

</dependency>

<!-- Ribbon相关 -->

        <dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

</dependencies>

</project>

(2).修改application.yml

追加eureka的服务注册地址。

修改部分:

eureka:

  client:

    register-with-eureka: false

    service-url:

      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

完整部分:

server:

  port: 80

eureka:

  client:

    register-with-eureka: false

    service-url:

      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

(3).修改ConfigBean.java

对ConfigBean进行新注解@LoadBalanced,获得Rest时加入Ribbon的配置;

package com.hosystem.springcloud.cfgbeans;

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;

@Configuration

public class ConfigBean //boot ---> spring applicationContext.xml === @Configuration配置 ConfigBean = applicationContext.xml

{

@Bean

@LoadBalanced   //Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

    public RestTemplate getRestTemplate()

{

return new RestTemplate();

}

}

//applicationContext.xml  ---> @Configuration public class ConfigBean {}

//<bean id=UserService" class="com.hosystem.tmall.UserServiceImple>

(4).修改DeptConsumer80_App.java

主启动类DeptConsumer80_App添加@EnableEurekaClient

package com.hosystem.springcloud;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication

@EnableEurekaClient

public class DeptConsumer80_App

{

public static void main(String[] args)

{

SpringApplication.run(DeptConsumer80_App.class, args);

}

}

(5).修改DeptController_Consumer.java

修改DeptController_Consumer客户端访问类

package com.hosystem.springcloud.controller;

import com.hosystem.springcloud.entities.Dept;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

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;

@RestController //:这里一定不能忘记注解@RestController 否则出现404;

public class DeptController_Consumer {

/**

     *  使用restTemplate访问restful接口非常的简单;

     *  (url, requestMap, ResponseBean.class)三个参数代表REST请求地址、请求参数、HTTP响应转换被转换成的对象类型

     */

//    private static final String REST_URL_PREFIX = "http://localhost:8001";

    //修改为微服务名 实现名字访问微服务

    private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";

@Autowired

private RestTemplate restTemplate;

@RequestMapping(value="/consumer/dept/add")

public boolean add(Dept dept)

{

return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class);

}

@RequestMapping(value="/consumer/dept/get/{id}")

public Dept get(@PathVariable("id") Long id)

{

return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id, Dept.class);

}

//@SuppressWarnings("unchecked"):压制警告,因为我们使用了过期的方法

    @SuppressWarnings("unchecked")

@RequestMapping(value="/consumer/dept/list")

public List<Dept> list()

{

return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class);

}

//测试@EnableDiscoveryClient,消费端可以调用服务发现

    @RequestMapping(value="/consumer/dept/discovery")

public Object discovery()

{

return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery", Object.class);

}

}

/**

 *  JDBC    Spring JDBCTemplate

 *          Spring RestTemplate

 */

(6).启动eureka、provider、consumer

先启动3个eureka7001、eureka7002、eureka7003集群后,再启动microservicecloud-provider-dept-8001并注册进eureka,最后启动microservicecloud-consumer-dept-80。

(7).测试

http://localhost/consumer/dept/get/1

http://localhost/consumer/dept/list

http://localhost/consumer/dept/add?dname=大数据部

(8).总结

Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号

3.Ribbon负载均衡

(1).Ribbon架构介绍

Ribbon在工作时分成两步:第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

(2).创建provider8002、provider8003

[1].创建工程provider8002

[2].创建工程provider8003

(3).配置pom文件

[1].配置provider8002 pom文件

<?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>microservicecloud</artifactId>

<groupId>com.hosystem</groupId>

<version>1.0-SNAPSHOT</version>

</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-provider-dept-8002</artifactId>

<dependencies>

<dependency><!-- 引入自己定义的api通用包,可以使用Dept部门Entity -->

            <groupId>com.hosystem</groupId>

<artifactId>microservicecloud-api</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

</dependency>

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-core</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

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

</dependency>

<dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<!-- 修改后立即生效,热部署 -->

        <dependency>

<groupId>org.springframework</groupId>

<artifactId>springloaded</artifactId>

</dependency>

<dependency>

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

<artifactId>spring-boot-devtools</artifactId>

</dependency>

<!-- 将微服务provider侧注册进eureka -->

        <dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<!-- actuator监控信息完善 -->

        <dependency>

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

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

</dependency>

</dependencies>

</project>

[2].配置provider8003 pom文件

<?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>microservicecloud</artifactId>

<groupId>com.hosystem</groupId>

<version>1.0-SNAPSHOT</version>

</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-provider-dept-8003</artifactId>

<dependencies>

<dependency><!-- 引入自己定义的api通用包,可以使用Dept部门Entity -->

            <groupId>com.hosystem</groupId>

<artifactId>microservicecloud-api</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

</dependency>

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-core</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

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

</dependency>

<dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<!-- 修改后立即生效,热部署 -->

        <dependency>

<groupId>org.springframework</groupId>

<artifactId>springloaded</artifactId>

</dependency>

<dependency>

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

<artifactId>spring-boot-devtools</artifactId>

</dependency>

<!-- 将微服务provider侧注册进eureka -->

        <dependency>

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

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

</dependency>

<dependency>

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

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

</dependency>

<!-- actuator监控信息完善 -->

        <dependency>

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

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

</dependency>

</dependencies>

</project>

(4).配置yml文件

修改的地方有端口、数据库链接、实例id(instance-id);对外暴露的统一服务实例名一定不能修改(name: microservicecloud-dept)

[1].配置provider8002 yml文件

server:

  port: 8002

mybatis:

  config-location: classpath:mybatis/mybatis.cfg.xml        # mybatis配置文件所在路径

  type-aliases-package: com.hosytem.springcloud.entities    # 所有Entity别名类所在包

  mapper-locations:

  - classpath:mybatis/mapper/**/*.xml                       # mapper映射文件

#name spring.application.name=microservicecloud-dept  很重要很重要很重要

spring:

   application:

    name: microservicecloud-dept

datasource:

    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型

    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驱动包

    url: jdbc:mysql://192.168.188.188:3306/cloudDB02              # 数据库名称

    username: root

password: 123456

dbcp2:

      min-idle: 5                                           # 数据库连接池的最小维持连接数

      initial-size: 5                                       # 初始化连接数

      max-total: 5                                          # 最大连接数

      max-wait-millis: 200                                  # 等待连接获取的最大超时时间

eureka:

  client: #客户端注册进eureka服务列表内

    service-url:

#      defaultZone: http://localhost:7001/eureka

      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

instance:

    instance-id: microservicecloud-dept8002

prefer-ip-address: true     #访问路径可以显示IP地址

info:

  app.name: hosystem-microservicecloud

company.name: www.hosystem.com

build.artifactId: $project.artifactId$

build.version: $project.version$

[2].配置provider8003 yml文件

server:

  port: 8003

mybatis:

  config-location: classpath:mybatis/mybatis.cfg.xml        # mybatis配置文件所在路径

  type-aliases-package: com.hosytem.springcloud.entities    # 所有Entity别名类所在包

  mapper-locations:

  - classpath:mybatis/mapper/**/*.xml                       # mapper映射文件

#name spring.application.name=microservicecloud-dept  很重要很重要很重要

spring:

   application:

    name: microservicecloud-dept

datasource:

    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型

    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驱动包

    url: jdbc:mysql://192.168.188.188:3306/cloudDB03              # 数据库名称

    username: root

password: 123456

dbcp2:

      min-idle: 5                                           # 数据库连接池的最小维持连接数

      initial-size: 5                                       # 初始化连接数

      max-total: 5                                          # 最大连接数

      max-wait-millis: 200                                  # 等待连接获取的最大超时时间

eureka:

  client: #客户端注册进eureka服务列表内

    service-url:

#      defaultZone: http://localhost:7001/eureka

      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

instance:

    instance-id: microservicecloud-dept8003

prefer-ip-address: true     #访问路径可以显示IP地址

info:

  app.name: hosystem-microservicecloud

company.name: www.hosystem.com

build.artifactId: $project.artifactId$

build.version: $project.version$

(5).配置主启动类

[1].DeptProvider8002_App

[2].DeptProvider8002_App

(6).创建数据库database8002、database8003

新建8002/8003数据库,各自微服务分别连各自的数据库。

[1].创建database8002

DROP DATABASE IF EXISTS cloudDB02;

CREATE DATABASE cloudDB02 CHARACTER SET UTF8;

USE cloudDB02;

CREATE TABLE dept

(

deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,

dname VARCHAR(60),

db_source   VARCHAR(60)

);

INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE());

SELECT * FROM dept;

[2].创建database8003

DROP DATABASE IF EXISTS cloudDB03;

CREATE DATABASE cloudDB03 CHARACTER SET UTF8;

USE cloudDB03;

CREATE TABLE dept

(

deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,

dname VARCHAR(60),

db_source   VARCHAR(60)

);

INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE());

INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE());

SELECT * FROM dept;

(7).启动eureka、provider、consumer

启动3个eureka集群配置区,在启动provider后,我们需要随便打开一个eureka看provider是否都注册上了。

启动3个provider微服务并各自测试通过

http://localhost:8001/dept/list

http://localhost:8002/dept/list

http://localhost:8003/dept/list

启动microservicecloud-consumer-dept-80

(8).访问Dept微服务

客户端通过Ribbo完成负载均衡并访问上一步的Dept微服务

http://localhost/consumer/dept/list

注意观察看到返回的数据库名字,各不相同,负载均衡实现 

(9).总结

Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

4.Ribbon核心组件

(1).查看IRle接口

(2).查看IRleILoadBalancer接口

(3).查看AbstractLoadBalancer接口

(4).使用RandomRule算法

修改consumer-dept-80的ConfigBean.java.

package com.hosystem.springcloud.cfgbeans;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.RandomRule;

import com.netflix.loadbalancer.RetryRule;

import com.netflix.loadbalancer.RoundRobinRule;

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;

@Configuration

public class ConfigBean //boot ---> spring applicationContext.xml === @Configuration配置 ConfigBean = applicationContext.xml

{

@Bean

@LoadBalanced   //Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

    public RestTemplate getRestTemplate()

{

return new RestTemplate();

}

//选择我们使用的算法

    // RoundRobinRule:轮询

    // RandomRule:随机

    // AvailabilityFilteringRule:先过滤多次访问故障处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问

    // WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule

    // RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务

    // BestAvailableRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

    // ZoneAvoidanceRule:默认规则,复合判断server所在区域的性能和server的可用性选择服务器

    @Bean

public IRule myRule(){

//        return new RoundRobinRule(); //轮询算法

//        return new RandomRule();    //随机算法

        return new RetryRule();     //先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务

    }

}

//applicationContext.xml  ---> @Configuration public class ConfigBean {}

//<bean id=UserService" class="com.hosystem.tmall.UserServiceImple>

5.Ribbon自定义

修改microservicecloud-consumer-dept-80

(1).修改主启动类

修改consumer-dept-80的主启动类

package com.hosystem.springcloud;

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="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class) //在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效

public class DeptConsumer80_App

{

public static void main(String[] args)

{

SpringApplication.run(DeptConsumer80_App.class, args);

}

}

(2).配置事项

官方文档明确给出了警告:这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是说我们达不到特殊化定制的目的了。

简单说,就是我们不能够在主启动类(DeptConsumer80_App)所在的包及其子包下创建我们自定义规则类。

如,我们新创建了myrule包,不能够创建在springcloud包下,因为主启动类在springcloud包下了。

(3).自定义步骤

[1].新建package

根据配置事项,我们得知需要重新创建一个包不能和主启动类在一个包下。我们创建com.hosystem.myrule包。

[2].自定义Robbin规则类

package com.hosystem.myrule;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.RandomRule;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class MySelfRule

{

@Bean

public IRule myRule()

{

return new RandomRule();//Ribbon默认是轮询,我自定义为随机

    }

}

[3].修改主启动类

package com.hosystem.springcloud;

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="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class) //在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效

public class DeptConsumer80_App

{

public static void main(String[] args)

{

SpringApplication.run(DeptConsumer80_App.class, args);

}

}

[4].测试

http://localhost/consumer/dept/list

(4).自定义规则深度解析

依旧轮询策略,但是加上新需求,每个服务器要求被调用5次。也即以前是每台机器一次,现在是每台机器5次。

[1].源码解析

https://github.com/Netflix/ribbon/blob/master/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java

[2].RandomRule_Hosystem.java

参考源码修改为我们需求要求的RandomRule_Hosystem.java

package com.hosystem.myrule;

import com.netflix.client.config.IClientConfig;

import com.netflix.loadbalancer.AbstractLoadBalancerRule;

import com.netflix.loadbalancer.ILoadBalancer;

import com.netflix.loadbalancer.Server;

import java.util.List;

import java.util.concurrent.ThreadLocalRandom;

public class RandomRule_Hosystem extends AbstractLoadBalancerRule{

//total = 0 total==5时 指向才能往下走

    //index = 0 当前对外提供的服务器地址

    //total5置为0时 我们index=1

    private int total = 0;    //总共被调用的次数,目前要求每台被调用5

    private int currentIndex = 0;//当前提供服务的机器号

    /**

     * Randomly choose from all living servers

     */

//    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")

    public Server choose(ILoadBalancer lb, Object key) {

if (lb == null) {

return null;

}

Server server = null;

while (server == null) {

if (Thread.interrupted()) {

return null;

}

List<Server> upList = lb.getReachableServers();

List<Server> allList = lb.getAllServers();

int serverCount = allList.size();

if (serverCount == 0) {

/*

                 * No servers. End regardless of pass, because subsequent passes

                 * only get more restrictive.

                 */

                return null;

}

//            int index = chooseRandomInt(serverCount);

//            server = upList.get(index);

//            private int total = 0;    //总共被调用的次数,目前要求每台被调用5

//            private int currentIndex = 0;//当前提供服务的机器号

            //分析,因为我们需要访问5次 但是微服务只有8001 8002 8003三台 所以我们需要设定currentIndex>=upList.size()时重新从8001开始

            if(total < 5)

{

server = upList.get(currentIndex);

total++;

}else {

total = 0;

currentIndex++;

if(currentIndex >= upList.size())

{

currentIndex = 0;

}

}

if (server == null) {

/*

                 * The only time this should happen is if the server list were

                 * somehow trimmed. This is a transient condition. Retry after

                 * yielding.

                 */

                Thread.yield();

continue;

}

if (server.isAlive()) {

return (server);

}

// Shouldn't actually happen.. but must be transient or a bug.

            server = null;

Thread.yield();

}

return server;

}

protected int chooseRandomInt(int serverCount) {

return ThreadLocalRandom.current().nextInt(serverCount);

}

@Override

public Server choose(Object key) {

return choose(getLoadBalancer(), key);

}

@Override

public void initWithNiwsConfig(IClientConfig iClientConfig) {

}

}

[3].MySelfRule.java

package com.hosystem.myrule;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.RandomRule;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class MySelfRule

{

@Bean

public IRule myRule()

{

//        return new RandomRule();//Ribbon默认是轮询,我自定义为随机

        return  new RandomRule_Hosystem();  //自定义每台机器访问5

    }

}

[4].测试

http://localhost/consumer/dept/list

参考文档:

https://baike.baidu.com/item/F5%E6%96%B9%E6%A1%88/1121377?fr=aladdin

https://github.com/Netflix/ribbon/wiki

https://github.com/Netflix/ribbon/wiki/Getting-Started

https://github.com/Netflix/ribbon/blob/master/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java

5、Spring Cloud Ribbon的更多相关文章

  1. Spring Cloud微服务笔记(四)客户端负载均衡:Spring Cloud Ribbon

    客户端负载均衡:Spring Cloud Ribbon 一.负载均衡概念 负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容.因为负载均衡对系统的高可用性. 网络压力的缓解和处理能力的扩容的 ...

  2. 一:Spring Boot、Spring Cloud

    上次写了一篇文章叫Spring Cloud在国内中小型公司能用起来吗?介绍了Spring Cloud是否能在中小公司使用起来,这篇文章是它的姊妹篇.其实我们在这条路上已经走了一年多,从16年初到现在. ...

  3. 撸一撸Spring Cloud Ribbon的原理-负载均衡器

    在上一篇<撸一撸Spring Cloud Ribbon的原理>中整理发现,RestTemplate内部调用负载均衡拦截器,拦截器内最终是调用了负载均衡器来选择服务实例. 接下来撸一撸负载均 ...

  4. 笔记:Spring Cloud Ribbon 客户端配置详解

    自动化配置 由于 Ribbon 中定义的每一个接口都有多种不同的策略实现,同时这些接口之间又有一定的依赖关系,Spring Cloud Ribbon 中的自动化配置能够很方便的自动化构建接口的具体实现 ...

  5. 笔记:Spring Cloud Ribbon 客户端负载均衡

    Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,基于 Netflix Ribbon 实现,通过Spring Cloud 的封装,可以让我们轻松的将面向服 ...

  6. 基于Spring cloud Ribbon和Eureka实现客户端负载均衡

    前言 本案例将基于Spring cloud Ribbon和Eureka实现客户端负载均衡,其中Ribbon用于实现客户端负载均衡,Eureka主要是用于服务注册及发现: 传统的服务端负载均衡 常见的服 ...

  7. 第四章 客户端负载均衡:Spring Cloud Ribbon

    spring cloud ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于Netflix Ribbon 实现.通过Spring Cloud 的封装,可以轻松的将面向服务的R ...

  8. Spring Cloud Ribbon入门

    一.简介 Spring Cloud Ribbon是一个基于Http和TCP的客户端负载均衡工具,它是基于Netflix Ribbon实现的.它不像服务注册中心.配置中心.API网关那样独立部署,但是它 ...

  9. 【SpringCloud微服务实战学习系列】客户端负载均衡Spring Cloud Ribbon

    Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让我们轻松地将面向服务的RES模板 ...

随机推荐

  1. 微软发布.net 6,net5 RC2

    2020-11-13 更新 .net 6 SDK https://dotnetcli.azureedge.net/dotnet/Sdk/6.0.100-alpha.1.20562.2/dotnet-s ...

  2. BPMN开源工作流编辑器bpmn-js落地实践中文文档

    BPMN是一套标准的业务流程建模符号规范,bpmn-js是基于此规范实现的一套渲染工具包和web建模器,可以实现拖拽生成工作流程图,效果大概如下 最近刚好用到,研究之后写了系列文章,分享给有需要的小伙 ...

  3. 利用Github Action和.Net 5 自动执行米游社原神每日签到福利

    GenshinDailyHelper 原神的签到福利是需要单独下载APP进行才可以领取,并且每天需要打卡,虽然奖励并不是很可观,但有一些摩拉,食材和可观的经验书累计起来还是挺有吸引力的.可能本身不怎么 ...

  4. python像matlab类似的符号函数绘图

    matplotlib 绘图之前需要先定义数据范围,python 有一个 sympy 包,类似 matlab 里面的符号函数,可以用来进行二维和三维的图像绘制, from sympy.plotting ...

  5. redis-server文件启动cmd一闪而过

    工作上需要在本地装redis,所以就帮别人排查了一个问题,就是redis服务双击了之后不能起来,就是一个黑色的cmd框一闪而过,正常的是这样的: 然而,我当时第一次接触windows上的redis服务 ...

  6. linux云服务搭建七日杀服务器

    目录 准备工作 1.设置swap 2.安装screen 3.安装SteamCmd运行所需环境 4.创建一个用户 steamCMD与七日杀服务器端 1.下载并安装SteamCMD 2.登录steam账号 ...

  7. 算法题目:北邮python 3-C 排队前进

    一道python作业的题目,比较有意思,题目如下: 题目描述 有 n 个人排队向一个方向前进,他们前进的速度并不一定相同. 最开始即 t=0 时,每个人的位置并不相同.可以把他们放在数轴上,设他们前进 ...

  8. WinRM服务远程命令执行

    WinRM服务简介 WinRM是WindowsRemoteManagementd(win远程管理)的简称.基于Web服务管理(WS-Management)标准,使用80端口或者443端口.这样一来,我 ...

  9. 聊聊 elasticsearch 之分词器配置 (IK+pinyin)

    系统:windows 10 elasticsearch版本:5.6.9 es分词的选择 使用es是考虑服务的性能调优,通过读写分离的方式降低频繁访问数据库的压力,至于分词的选择考虑主要是根据目前比较流 ...

  10. 接入twitter第三方登陆接口遇到的一个问题

    本地开了 Shadowsocks,然后postman模拟的twitter的接口是请求成功的,然后用php-curl去请求网址,出现以下错误 Failed to connect to api.twitt ...