• Spring Cloud LoadBalancer基础知识


    概念

    LoadBalancer(负载均衡器)是一种网络设备或软件机制, 用于分发传入的网络流量负载(请求)到多个后端目标服务器上, 从而实现系统资源的均衡利用和提高系统的可用性和性能
    负载均衡分为服务器端负载均衡和客户端负载均衡

    1. 服务器端负载均衡是指放在服务器端的负载均衡器(反向代理), 如: Nginx, HAProxy, F5等
    2. 客户端负载均衡器是指嵌套在客户端的负载均衡器(正向代理), 如: Ribbon, Spring Cloud LoadBalancer等

    服务器端负载均衡器所有请求都会发送到服务器端, 就会造成服务器端压力大的情况

    常见的负载均衡策略

    1. 轮询(默认): 按照顺序将请求发送到服务器
    2. 随机选择: 随机选择一个服务器处理请求
    3. 最少连接: 选择连接数最少的一个服务器
    4. IP 哈希: 使用客户端IP地址计算哈希值然后发送到与之对应的服务器
    5. 加权轮询: 按照权重值的比例发送请求
    6. 加权随机选择: 按照权重值随机选择后端服务器
    7. 最短响应时间: 将请求发送到响应时间最短的服务器

    Spring Cloud LoadBalancer 默认只支持轮询和随机选择, 但是可以自定义负载均衡策略

    使用随机选择的负载均衡策略

    创建随机选择负载均衡器

    public class MyRandomLoadBalancer {
        @Bean
        public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                                       LoadBalancerClientFactory loadBalancerClientFactory) {
            String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
            return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    配置

    image.png
    注意: 配置局部负载均衡器有可能不起作用, 可以配置全局负载均衡器
    image.png

    Nacos 权重负载均衡器

    Nacos 中支持两种负载均衡器, 一种是权重负载均衡器, 另一种是第三方的CMDB(地域就近访问)标签负载均衡器, 我们可以将Spring Cloud LoadBalancer 直接配置为 Nacos 的负载均衡器

    创建 Nacos 负载均衡器

    @LoadBalancerClients(defaultConfiguration = MyNacosLoadBalancer.class)
    public class MyNacosLoadBalancer {
        @Resource
        private NacosDiscoveryProperties nacosDiscoveryProperties;
        @Bean
        public ReactorLoadBalancer<ServiceInstance> nacosLoadBalancer(Environment environment,
                                                                       LoadBalancerClientFactory loadBalancerClientFactory) {
            String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
            return new NacosLoadBalancer(
                    loadBalancerClientFactory.getLazyProvider
                            (name, ServiceInstanceListSupplier.class),
                    name, nacosDiscoveryProperties);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    配置

    image.png

    自定义负载均衡器(根据IP哈希策略选择)

    创建自定义负载均衡器

    public class CustomLoadBalancer implements ReactorServiceInstanceLoadBalancer {
        private static final Log log = LogFactory.getLog(RandomLoadBalancer.class);
        private final String serviceId;
        private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
    
        public CustomLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
            this.serviceId = serviceId;
            this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        }
    
        public Mono<Response<ServiceInstance>> choose(Request request) {
            ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier)this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
            return supplier.get(request).next().map((serviceInstances) -> {
                return this.processInstanceResponse(supplier, serviceInstances);
            });
        }
    
        private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier, List<ServiceInstance> serviceInstances) {
            Response<ServiceInstance> serviceInstanceResponse = this.getInstanceResponse(serviceInstances);
            if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
                ((SelectedInstanceCallback)supplier).selectedServiceInstance((ServiceInstance)serviceInstanceResponse.getServer());
            }
    
            return serviceInstanceResponse;
        }
    
        private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
            if (instances.isEmpty()) {
                if (log.isWarnEnabled()) {
                    log.warn("No servers available for service: " + this.serviceId);
                }
    
                return new EmptyResponse();
            } else {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                String ipAddress = request.getRemoteAddr();
                System.out.println("ip地址:" + ipAddress);
                int hash = instances.hashCode();
                int index = hash % instances.size();
                ServiceInstance instance = (ServiceInstance) instances.get(index);
                return new DefaultResponse(instance);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    由于自定义负载均衡器和内置的负载均衡器只是在服务器选择的时候有所不同, 所以我们可以直接复制 RandomLoadBalancer 然后 在 getInstanceResponse()方法中进行改动即可

    封装自定义负载均衡器

    image.png

    配置

    image.png

    缓存

    Spring Cloud LoadBalancer 在获取实例时有两种选择:

    1. 及时获取: 每次都从注册中心获取到最新的实例, 效果好但是开销大
    2. 缓存服务列表: 每次得到服务列表后, 缓存一段时间,

    spring Cloud LoadBalancer 默认缓存过期时间为 35s, 保存个数为 256个
    我们也可以通过配置来改变这两个值

    spring:
      cloud:
        loadbalancer:
          cache:
            ttl: 10
            capacity: 1000
    #       enabled: false 关闭缓存
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    生产环境下不要关闭缓存否则会降低性能

  • 相关阅读:
    Python 如何实现适配器设计模式?什么是适配器(Adapter)设计模式?
    能涨薪3k的jmeter接口测试 接口自动化测试全套教程
    电子统计台账:快速设置产品的排除与保留
    pixhawk接深度计
    讯飞离线语音合成新版(Aikit)-android sdk合成 demo(Java版本)
    游戏陪玩小程序怎么开发-游戏陪玩小程序功能
    vite + react + typescript + uni-app + node 开发一个生态系统
    内存泄漏?
    Nginx 核心配置文 nginx.conf介绍
    【面经】特斯拉大数据开发面经
  • 原文地址:https://blog.csdn.net/m0_71645055/article/details/134321187