spring cloud --- Ribbon 客户端负载均衡 + RestTemplate ---心得【无熔断器】 1.前言 2.操作  3.测试

spring boot      1.5.9.RELEASE

spring cloud    Dalston.SR1

  了解了 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.文件

<?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 cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

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

完成的配置文件

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文件配置

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层

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 cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

 3.测试

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

spring cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

 (2)查看eureka控制面板

spring cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

ok,运行正常

8001端口业务截图

spring cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

 8003端口业务截图

spring cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

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

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

访问第一次

spring cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

访问第2次

spring cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

 访问第三次

 spring cloud --- Ribbon 客户端负载均衡 + RestTemplate   ---心得【无熔断器】
1.前言
2.操作
 3.测试

 完美 !!!

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