spring boot --- Ribbon 客户端负载均衡 + RestTemplate ---心得【无熔断器】

1.前言

  了解了 eureka 服务注册与发现 的3大角色 ,会使用RestTemplate 在消费者 调用提供者 的服务了,

那么如果引入了 集群 ,让提供者集群化 ,那么消费者如何调用 服务呢?

  答案是使用 Ribbon 客户端负载均衡  ,与Nginx不同 ,Nginx是服务端的负载均衡 ,Ribbon则是运行在客户端的,原理是客户端从eureka 获取服务列表信息 ,然后根据在客户端

  配置文件定义的 Ribbon 负载均衡策略来寻找要访问具体是那台服务器【即服务提供者,因为是集群 ,因此是不同的服务器 运行一样的代码,做一样的事情,因此注册在eureka上的应用名是一样的 ,但是ip或端口不同】

2.操作

(1)在消费者 的 pom.xml引入 Ribbon依赖包  

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

完成的pom.文件

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.atguigu.springcloud</groupId>
        <!--    父级maven模块的工程名字-->
        <artifactId>microservicecloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo-my-cen-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo-my-cen-test</name>
    <description>Demo project for Spring Boot</description>

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

    <dependencies>

<!--        引入同级的maven-->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>demo-my-cen-2-2</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

<!--        <dependency>-->
<!--            <groupId>org.yaml</groupId>-->
<!--            <artifactId>snakeyaml</artifactId>-->
<!--&lt;!&ndash;            <version>${version}</version>&ndash;&gt;-->
<!--        </dependency>-->



        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</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>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>




        <dependency><!-- 自己定义的api -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>microservicecloud-api</artifactId>
            <version>${project.version}</version>
        </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>-->

        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
View Code

 

(2)

工程结构

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 

(3)配置 RestTemplate,注册bean, ,配合注解 @LoadBalanced  ,开启负载均衡

完成的配置文件

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
package com.example.demomycentest.cfgBean;


import com.netflix.loadbalancer.BestAvailableRule;
import com.netflix.loadbalancer.IRule;
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 MyConfigBean {

    @Bean
    ////添加注解@LoadBalanced,开启负载均衡。。。就这么简单
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    //设置负载均衡策略
    @Bean
    public IRule myRule() {
        //其他看看 https://www.cnblogs.com/htyj/p/10705472.html
        //
        //该策略通过遍历负载均衡器中维护的所有实例,会过滤调故障的实例,并找出并发请求数最小的一个,所以该策略的特征是选择出最空闲的实例
        //return new BestAvailableRule();

        //轮询策略,其实里面就是一个计数器
        return new RoundRobinRule();

    }
}
View Code

更过负载均衡策略可以查看这篇博文  : https://www.cnblogs.com/htyj/p/10705472.html

基本常用的默认策略 有 :

  • RandomRule:

  实现了从服务实例清单中随机选择一个服务实例的功能

  • RoundRobinRule:

  实现了按照线性轮询的方式一次选择每个服务实例的功能

  • RetryTule:

  实现了一个具备重试机制的实例选择功能

  • WeightedRespinseTimeRule:

  该策略是对RoundRobinRule的扩展,增加了根据实例的运行情况来计算权重,并根据权重来挑选实例,已达到更优的分配效果。

  • ClientConfigEnabledRoundRobinRule

  该策略较为特殊,我们一般不直接使用它。因为它本身并没有实现什么特殊的处理逻辑,真如代码中所示,在他的内部定义了一个RoundRobinRule策略,而choose函数的实现也正是使用了RoundRobinRule的线性轮询机制,所以它实现的功能实际上RoundeRobinRule相同。

  虽然不能直接使用该策略,但是可以通过继承该策略,默认的choose就实现了线性轮询机制,但是可以在子类中实现更高级的策略

  • BestAvailableRule

   该策略通过遍历负载均衡器中维护的所有实例,会过滤调故障的实例,并找出并发请求数最小的一个,所以该策略的特征是选择出最空闲的实例

(4)application.yml文件配置

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
server:
  port: 565

spring:
  application:
    name: demo-my-cen-test
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驱动包
    url: jdbc:mysql://localhost:3306/clinic?characterEncoding=utf-8        # 数据库名称
    username: root
    password: mysql
    dbcp2:
      min-idle: 5                                           # 数据库连接池的最小维持连接数
      initial-size: 5                                       # 初始化连接数
      max-total: 5                                          # 最大连接数
      max-wait-millis: 200                                  # 等待连接获取的最大超时时间



eureka:
  client:
    register-with-eureka: false  # 当前微服务不注册到eureka中(消费端)
    service-url:
      defaultZone: http://localhost:7001/eureka/
#      如果有注册中心不在线,但是写上了地址,会报错
#      ,http://localhost:7002/eureka/,http://localhost:7003/eureka/
View Code

(5)controller层

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
package com.example.demomycentest.controller;




//import com.example.demomycen22.pojo.Food;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@Controller
public class GGController {

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

    /**
     * 使用 使用restTemplate访问restful接口非常的简单粗暴无脑。 (url, requestMap,
     * ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
     */
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/bb")
    @ResponseBody
    public String bb(){

//        Food d = new Food();
//        d.setApple("苹果");
//        d.setEgg("鸡蛋");
//        System.out.println(d);

        System.out.println("调用服务,开启负载均衡Ribbon");
        //使用restTemplate 直接调用 ,postForObject 是post请求方式 ,getForObject是get请求方式,根据服务提供者的接口选择,这个是需要提前知道服务提供者的接口格式的
        return restTemplate.getForObject(REST_URL_PREFIX + "/ask", String.class);

    }
}
View Code

(6)启动类需要使用注解@EnableEurekaClient  ,注册为eureka客户端

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 

 3.测试

(1)提前准备好了2个 服务提供者作为集群,端口分别是8001,8003 ,一个服务注册中心,端口7001  ,本服务消费者端口565

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 

 (2)查看eureka控制面板

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 

 

ok,运行正常

8001端口业务截图

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 

 8003端口业务截图

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 

 消费者565端口的业务 在 第二节(5)controller层  有源码,这里就不展示了

(3)去浏览器调用消费者接口 ,输入 http://localhost:565/bb 

访问第一次

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 

 

访问第2次

spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 访问第三次

 spring boot --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】

 

 完美 !!!

因为是使用了轮询负载均衡策略 ,【就是轮流访问集群的每个服务器】,Ribbon会根据策略选择访问具体是哪个服务 

 

上一篇:springCloud(九) hystrix 和 restTemplate 整合


下一篇:RestTemplate