Spring Cloud之负载均衡与服务调用(Ribbon)-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

Ribbon

简介

负载均衡

简介

负载均衡方式

服务端负载均衡

工作原理

特点

客户端负载均衡

工作原理

特点

对比

实现

负载均衡策略

切换负载均衡策略

定制负载均衡策略

超时与重试

单个服务配置

全局配置

服务调用

示例


Ribbon

简介

        Ribbon 是 Netflix 公司发布的开源组件其主要功能是提供客户端的负载均衡算法和服务调用通过它我们可以将面向服务的 REST 模板请求转换为客户端负载均衡的服务调用。微服务之间的调用API 网关的请求转发等内容实际上都是通过 Ribbon 来实现的。

负载均衡

简介

        在任何一个系统中负载均衡都是一个十分重要且不得不去实施的内容它是系统处理高并发、缓解网络压力和服务端扩容的重要手段之一。

        负载均衡简单点说就是将用户的请求平摊分配到多个服务器上运行以达到扩展服务器带宽、增强数据处理能力、增加吞吐量、提高网络的可用性和灵活性的目的。

负载均衡方式

常见的负载均衡方式有两种服务端负载均衡、客户端负载均衡

服务端负载均衡
工作原理

        服务端负载均衡是在客户端和服务端之间建立一个独立的负载均衡服务器该服务器既可以是硬件设备例如 F5也可以是软件例如 Nginx。这个负载均衡服务器维护了一份可用服务端清单然后通过心跳机制来删除故障的服务端节点以保证清单中的所有服务节点都是可以正常访问的。

        当客户端发送请求时该请求不会直接发送到服务端进行处理而是全部交给负载均衡服务器由负载均衡服务器按照某种算法例如轮询、随机等从其维护的可用服务清单中选择一个服务端然后进行转发。

特点

        1.需要建立一个独立的负载均衡服务器

        2.负载均衡是在客户端发送请求后进行的因此客户端并不知道到底是哪个服务端提供的服务

        3.可用服务端清单存储在负载均衡服务器上

客户端负载均衡

相较于服务端负载均衡客户端服务在均衡则是一个比较小众的概念

工作原理

        客户端负载均衡是将负载均衡逻辑以代码的形式封装到客户端上即负载均衡器位于客户端。客户端通过服务注册中心例如 Eureka Server获取到一份服务端提供的可用服务清单。有了服务清单后负载均衡器会在客户端发送请求前通过负载均衡算法选择一个服务端实例再进行访问以达到负载均衡的目的

        客户端负载均衡也需要心跳机制去维护服务端清单的有效性这个过程需要配合服务注册中心一起完成 

特点

        1.负载均衡器位于客户端不需要单独搭建一个负载均衡服务器

        2.负载均衡是在客户端发送请求前进行的因此客户端清楚地知道是哪个服务端提供的服务

        3.客户端都维护了一份可用服务清单而这份清单都是从服务注册中心获取的

        Ribbon 就是一个基于 HTTP 和 TCP 的客户端负载均衡器当我们将 Ribbon 和 Eureka 一起使用时Ribbon 会从 Eureka Server服务注册中心中获取服务端列表然后通过负载均衡策略将请求分摊给多个服务提供者从而达到负载均衡的目的

对比

实现

        Ribbon 是一个客户端的负载均衡器它可以与 Eureka 配合使用轻松地实现客户端的负载均衡。Ribbon 会先从 Eureka Server服务注册中心去获取服务端列表然后通过负载均衡策略将请求分摊给多个服务端从而达到负载均衡的目的

负载均衡策略
序号实现类负载均衡策略
1RoundRobinRule轮询策略即按照一定的顺序依次选取服务实例
2RandomRule随机选取一个服务实例
3RetryRule按照轮询的策略来获取服务如果获取的服务实例为 null 或已经失效则在指定的时间之内不断地进行重试如果超过指定时间依然没获取到服务实例则返回 null 
4WeightedResponseTimeRule根据平均响应时间来计算所有服务实例的权重响应时间越短的服务实例权重越高被选中的概率越大
5BestAvailableRule先过滤点故障或失效的服务实例然后再选择并发量最小的服务实例
6AvailabilityFilteringRule先过滤掉故障或失效的服务实例然后再选择并发量较小的服务实例
7ZoneAvoidanceRule默认的负载均衡策略综合判断服务所在区域的性能和服务的可用性来选择服务实例
切换负载均衡策略

Ribbon 默认使用轮询策略选取服务实例我们也可以根据自身的需求切换负载均衡策略只需要在服务消费者客户端的配置类中将 IRule 的其他实现类注入到容器中即可

在配置类 ConfigBean 中添加以下代码将负载均衡策略切换为 RandomRule随机

@Bean
public IRule myRule() {
    // RandomRule 为随机策略
    return  new RandomRule();
}
定制负载均衡策略

1.创建一个名为 MyRandomRule 的类

package net.biancheng.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;

/**
* 定制 Ribbon 负载均衡策略
*/
public class MyRandomRule extends AbstractLoadBalancerRule {
    private int total = 0;            // 总共被调用的次数目前要求每台被调用5次
    private int currentIndex = 0;    // 当前提供服务的机器号

    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();

            //如果没有任何的服务实例则返回 null
            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }
            //与随机策略相似但每个服务实例只有在调用 3 次之后才会调用其他的服务实例
            if (total < 3) {
                server = upList.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()) {
                    currentIndex = 0;
                }
            }
            if (server == null) {
                Thread.yield();
                continue;
            }
            if (server.isAlive()) {
                return (server);
            }
            server = null;
            Thread.yield();
        }
        return server;
    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
        // TODO Auto-generated method stub
    }
}

2.创建一个名为 MySelfRibbonRuleConfig 的配置类将我们定制的负载均衡策略实现类注入到容器中

/**
* 定制 Ribbon 负载均衡策略的配置类
* 该自定义 Ribbon 负载均衡策略配置类 不能在 net.biancheng.c 包及其子包下
* 否则所有的 Ribbon 客户端都会采用该策略无法达到特殊化定制的目的
*/
@Configuration
public class MySelfRibbonRuleConfig {
    @Bean
    public IRule myRule() {
        //自定义 Ribbon 负载均衡策略
        return new MyRandomRule(); //自定义随机选择某一个微服务执行五次
    }
}

3.修改位于启动类在该类上使用 @RibbonClient 注解让我们定制的负载均衡策略生效

@SpringBootApplication
@EnableEurekaClient
//自定义 Ribbon 负载均衡策略在主启动类上使用 RibbonClient 注解在该微服务启动时就能自动去加载我们自定义的 Ribbon 配置类从而是配置生效
// name 为需要定制负载均衡策略的微服务名称application name
// configuration 为定制的负载均衡策略的配置类
// 且官方文档中明确提出该配置类不能在 ComponentScan 注解SpringBootApplication 注解中包含了该注解下的包或其子包中即自定义负载均衡配置类不能在 net.biancheng.c 包及其子包下
@RibbonClient(name = "MICROSERVICECLOUDPROVIDERDEPT", configuration = MySelfRibbonRuleConfig.class)
public class MicroServiceCloudConsumerDept80Application {
    public static void main(String[] args) {
        SpringApplication.run(MicroServiceCloudConsumerDept80Application.class, args);
    }
}

超时与重试

        使用HTTP发起请求难免会发生问题在F版开始Ribbon的重试机制默认是开启的需要添加对超时时间与重试策略的配置

单个服务配置
RIBBON-SERVICE-B:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    ConnectTimeout: 3000
    ReadTimeout: 60000
    MaxAutoRetries: 3 #对第一次请求的服务的重试次数
    MaxAutoRetriesNextServer: 1 #要重试的下一个服务的最大数量不包括第一个服务
    OkToRetryOnAllOperations: true
全局配置
ribbon:
  ConnectTimeout: 3000
  ReadTimeout: 60000
  MaxAutoRetries: 3 #对第一次请求的服务的重试次数
  MaxAutoRetriesNextServer: 1 #要重试的下一个服务的最大数量不包括第一个服务
  OkToRetryOnAllOperations: true

服务调用

        Ribbon 可以与 RestTemplateRest 模板配合使用以实现微服务之间的调用

        RestTemplate 是 Spring 家族中的一个用于消费第三方 REST 服务的请求框架。RestTemplate 实现了对 HTTP 请求的封装提供了一套模板化的服务调用方法。通过它Spring 应用可以很方便地对各种类型的 HTTP 请求进行访问。

示例

1.引入依赖

        <!--Spring Cloud Ribbon 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

2.创建请求调用服务端提供的服务

@RestController
public class DeptController_Consumer {
    //private static final String REST_URL_PROVIDER_PREFIX = "http://localhost:8001/"; 这种方式是直调用服务方的方法根本没有用到 Spring Cloud

    //面向微服务编程即通过微服务的名称来获取调用地址
    private static final String REST_URL_PROVIDER_PREFIX = "http://MICROSERVICECLOUDPROVIDERDEPT"; // 使用注册到 Spring Cloud Eureka 服务注册中心中的服务即 application.name

    @Autowired
    private RestTemplate restTemplate; //RestTemplate 是一种简单便捷的访问 restful 服务模板类是 Spring 提供的用于访问 Rest 服务的客户端模板工具集提供了多种便捷访问远程 HTTP 服务的方法

    //获取指定部门信息
    @RequestMapping(value = "/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Integer id) {
        return restTemplate.getForObject(REST_URL_PROVIDER_PREFIX + "/dept/get/" + id, Dept.class);
    }
    //获取部门列表
    @RequestMapping(value = "/consumer/dept/list")
    public List<Dept> list() {
        return restTemplate.getForObject(REST_URL_PROVIDER_PREFIX + "/dept/list", List.class);
    }
}

3.访问

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring