0
点赞
收藏
分享

微信扫一扫

SpringCloud-Netflix-05-Ribbon 负载均衡

文章目录


五、Netflix Ribbon 负载均衡

5.1 Ribbon 简介

Netflix Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST请求自动转换成客户端负载均衡的服务调用。微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的;

Ribbon的主要作用就是两个:

1)服务之间调用

2)服务调用时的负载均衡

5.2 Ribbon 快速入门

5.2.1 Ribbon 服务负载均衡

Ribbon已经被被集成到Eureka中,我们之前在学习Eureka时就已经用过了Ribbon了;

在RestTemplate上添加@LoadBalanced注解之后,调用接口便自动继承了负载均衡的能力;

  • ItemApplication:
package com.cloud.item;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@SpringBootApplication
@EnableDiscoveryClient      // 开启服务发现功能
@EnableEurekaClient         // 开启Eureka客户端
public class ItemApplication {
    public static void main(String[] args) {
        SpringApplication.run(ItemApplication.class);
    }

    @Bean
    @LoadBalanced           // 负载均衡
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  • ItemController:
package com.cloud.item.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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;

import java.util.Map;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@RestController
@RequestMapping("/item")
public class ItemController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/findOrderById/{orderId}")
    public Map findOrderById(@PathVariable Integer orderId){

        // 使用RestTemplate进行远程调用
        Map resultMap = restTemplate.getForObject("http://order-service/order/" + orderId, Map.class);

        return resultMap;
    }
}
  • OrderController:
/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Value("${spring.cloud.client.ip-address}")
    private String ip;

    @Value("${server.port}")
    private String port;

    @GetMapping("{id}")
    public Map findById(@PathVariable Integer id){

        return new HashMap(){{
            put("flag",true);
            put("message","查询成功"+ip+":"+port);
            put("statusCode","200");
            put("id",id);
        }};
    }
}

启动两个Order服务,访问:http://localhost:9001/item/findOrderById/1

在这里插入图片描述

5.2.2 自定义服务列表

当我们在 RestTemplate上添加 @LoadBalanced 注解后,就可以用服务名称来调用接口了,当有多个服务的时候,还能做负载均衡。这是因为 Eureka 中的服务信息已经被拉取到了客户端本地,关系如下:

在这里插入图片描述

有的时候我们希望Ribbon可以跳过Eureka,直接使用IP+端口的方式调用服务,这样的我们就不需要借助Eureka提供的服务名来远程调用了(测试环境用),我们可以自定义服务列表来实现负载均衡;

关闭Ribbon与Eureka的集成:

ribbon:
  eureka:
    enabled: false                # 关闭与Eureka的集成
ribbon-order-service:             # 自定义服务名称
  ribbon:
    listOfServers: localhost:9001,localhost:9002      # 服务的主机列表
  • ItemController:
@GetMapping("/findOrderById/{orderId}")
public Map findOrderById(@PathVariable Integer orderId){

    // 使用自定义的服务名称
    Map resultMap = restTemplate.getForObject("http://ribbon-order-service/order/" + orderId, Map.class);

    return resultMap;
}
  • OrderController:
package com.cloud.order.controller;

import com.cloud.order.entity.Order;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Value("${spring.cloud.client.ip-address}")
    private String ip;

    @Value("${server.port}")
    private String port;

    @GetMapping("{id}")
    public Map findById(@PathVariable Integer id) {

        return new HashMap() {{
            put("flag", true);
            put("message", "查询成功" + ip + ":" + port);
            put("statusCode", "200");
            put("id", id);
        }};
    }
}

5.3 Ribbon的配置

5.3.1 Ribbon 的属性配置

Ribbon的所有的默认配置可以去com.netflix.client.config.DefaultClientConfigImpl类下找:

关于Ribbon的所有配置在com.netflix.client.config.CommonClientConfigKey中定义:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XHQ8xA2R-1647869038595)(media/171.png)]

5.3.2 Ribbon常用配置

5.3.2.1 连接配置

ribbon:
  ConnectTimeout: 2000           # 请求连接的超时时间
  ReadTimeout: 5000               # 请求处理的超时时间

5.3.2.2 懒加载配置

Ribbon进行客户端负载均衡的Client并不是在服务启动的时候就初始化好的,而是在调用的时候才会去创建相应的Client,所以第一次调用的耗时不仅仅包含发送HTTP请求的时间,还包含了创建RibbonClient的时间,这样一来如果创建时间速度较慢,同时设置的超时时间又比较短的话,很容易出现第一次调用超时,之后就调用正常的现象;

ribbon:
  eager-load:
    enabled: true                               			# 开启立即加载客户端
    clients: ribbon-order-service,ribbon02-order-service 	# 选择指定的服务开启立即加载

5.3.2.3 并发调整

ribbon:
  MaxTotalConnections: 500        # 最大连接数
  MaxConnectionsPerHost: 100      # 每个host最大连接数

5.3.3 Ribbon 配置策略

Ribbon的配置分为全局配置和指定客户端配置,两种配置格式不同;

全局配置针对于所有的服务,客户端配置只针对于具体服务使用;

  • 全局配置:
ribbon:
  ConnectTimeout: 20000           # 请求连接的超时时间
  ReadTimeout: 5000               # 请求处理的超时时间
  • 客户端配置:
ribbon-order-service:             					  # 自定义服务名称
  ribbon:
    listOfServers: localhost:9001,localhost:9002      # 服务的主机列表
    ConnectTimeout: 20000
    ReadTimeout: 5000

5.4 Ribbon的负载均衡策略

5.4.1 Ribbon负载均衡策略

不难发现,我们之前使用Ribbon的负载均衡策略都是轮询;在Ribbon中,除了轮询策略外,还提供有其他几种策略,内部负责负载均衡的顶级接口为com.netflix.loadbalancer.IRule

  • com.netflix.loadbalancer.RoundRobinRule

    • **轮询策略;**以轮询的方式进行负载均衡。
  • com.netflix.loadbalancer.WeightedResponseTimeRule

    • **权重策略;**会计算每个服务的权重,响应速度越快的实例选择权重越大,越高的被调用的可能性越大。
  • com.netflix.loadbalancer.ResponseTimeWeightedRule

    • **权重策略;**作用和WeightedResponseTimeRule一致,后来改名为 WeightedResponseTimeRule
  • com.netflix.loadbalancer.BestAvailableRule

    • **最佳策略;**首先过滤掉故障实例,在没有故障的实例中,选择一个压力最小(并发量)的服务
  • com.netflix.loadbalancer.ZoneAvoidanceRule

    • **回避策略;**使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 Server,前一个判断判定一个 Zone 的运行性能是否可用,剔除不可用的 的所有 Server,AvailabilityPredicate 用于过滤掉连接数过多的 Server。
  • com.netflix.loadbalancer.AvailabilityFilteringRule

    • **过滤策略;**过滤掉故障和请求数超过阈值的服务实例,再从剩下的实例中轮询调用。
  • com.netflix.loadbalancer.RandomRule

    • **随机策略;**在服务列表中随机选择一个服务调用;
  • com.netflix.loadbalancer.RetryRule

    • **重试策略;**在RoundRobinRule的基础上添加重试机制,即在指定的重试时间内服务未响应,则继续使用轮询方式访问其他服务;

5.4.1 修改Ribbon负载均衡策略

  • 配置文件方式修改负载均衡策略:基于自定义服务名调用
ribbon:
  eureka:
    enabled: false                # 关闭与Eureka的集成
ribbon-order-service:     		# 只修改ribbon-order-service这个服务的负载均衡策略
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule			# 随机策略
    listOfServers: localhost:9001,localhost:9002,localhost:9003      # 服务的主机列表
  • 基于Eureka服务名调用:
ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
  • 配置类方式修改负载均衡策略:
/**
 * 随机策略
 * @return
 */
@Bean
public RandomRule randomRule(){
    return new RandomRule();
}
举报

相关推荐

0 条评论