3.负载均衡-LoadBalance

1.背景引入

1.1问题描述

java 复制代码
List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
 //服务可能有多个, 获取第⼀个
EurekaServiceInstance instance = (EurekaServiceInstance) instances.get(0);

针对某个服务,我们启动多个实例进行观察

访问eureka后,可以看到注册的实例

但是发现一个问题,每次进行数据访问时,都是同一台机器

我们启动多个实例, 是希望可以分担其他机器的负荷

1.2负载均衡

负载均衡(Load Balance) , 是⾼并发, ⾼可⽤系统必不可少的关键组件.当服务流量增⼤时, 通常会采⽤增加机器的⽅式进⾏扩容, 负载均衡就是⽤来在多个机器或者其他资源中, 按照⼀定的规则合理分配负载

1.3服务端负载均衡

在服务端进⾏负载均衡的算法分配.

⽐较有名的服务端负载均衡器是Nginx. 请求先到达Nginx负载均衡器, 然后通过负载均衡算法, 在多个服务器之间选择⼀个进⾏访问.

1.4客户端负载均衡

在客⼾端进⾏负载均衡的算法分配.

把负载均衡的功能以库的⽅式集成到客⼾端, ⽽不再是由⼀台指定的负载均衡设备集中提供.

⽐如Spring Cloud的Ribbon, 请求发送到客⼾端, 客⼾端从注册中⼼(⽐如Eureka)获取服务列表, 在发

送请求前通过负载均衡算法选择⼀个服务器,然后进⾏访问.

2.Spring Cloud LoadBalancer

2.1使⽤Spring Cloud LoadBalancer实现负载均衡

(1)给 RestTemplate 这个Bean添加 @LoadBalanced 注解

java 复制代码
@Configuration
public class BeanConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

(2)修改IP端⼝号为服务名称

java 复制代码
    public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);

        String url="http://product-service/product/"+orderInfo.getProductId();

        log.info("远程调用url{}",url);
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }

2.2负载均衡策略

负载均衡策略是⼀种思想, ⽆论是哪种负载均衡器, 它们的负载均衡策略都是相似的. Spring Cloud LoadBalancer 仅⽀持两种负载均衡策略: 轮询策略 和 随机策略

  • 轮询: 轮询策略是指服务器轮流处理⽤⼾的请求. 这是⼀种实现最简单, 也最常⽤的策略. ⽣活中也有类似的场景, ⽐如学校轮流值⽇, 或者轮流打扫卫⽣.
  • 随机选择: 随机选择策略是指随机选择⼀个后端服务器来处理新的请求.

Spring Cloud LoadBalancer 默认负载均衡策略是轮询策略,如果服务的消费者如果想采⽤随机的负载均衡策略, 也⾮常简单

(1)定义随机算法对象, 通过 @Bean 将其加载到 Spring 容器中

java 复制代码
public class CustomLoadBalancerConfiguration {

    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

(2)使⽤ @LoadBalancerClient 或者 @LoadBalancerClients 注解

在 RestTemplate 配置类上⽅, 使⽤ @LoadBalancerClient 或 @LoadBalancerClients 注解, 可以对不同的服务提供⽅配置不同的客⼾端负载均衡算法策略

java 复制代码
//name指定这个配置针对的服务名称是"product-service",configuration指定自定义的负载均衡配置类
@LoadBalancerClient(name = "product-service",configuration = CustomLoadBalancerConfiguration.class)
@Configuration
public class BeanConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

2.3LoadBalancer原理

LoadBalancer 的实现, 主要是 LoadBalancerInterceptor , 这个类会对 RestTemplate 的请求进⾏拦截, 然后从Eureka根据服务id获取服务列表,随后利⽤负载均衡算法得到真实的服务地址信息,替换服务id

3.服务部署(Linux)

3.1准备数据

  • 安装mysql
  • 数据初始化
  • 修改配置文件,主要包括用户名和密码

3.2服务构建打包

采用Maven打包,对所以服务进行打包

3.3启动服务

java 复制代码
#后台启动eureka-server, 并设置输出⽇志到logs/eureka.log
nohup java -jar eureka-server.jar >logs/eureka.log &
#其他服务同理

#再多启动两台实例
#启动实例, 指定端⼝号为9091
nohup java -jar product-service.jar --server.port=9091 >logs/product-9091.log &
#启动实例, 指定端⼝号为9092
nohup java -jar product-service.jar --server.port=9092 >logs/product-9092.log &

3.4开放端口号

对于不同的服务厂商,开放端口号的方法不同,这里以阿里云为例

相关推荐
Mahir081 小时前
Spring 循环依赖深度解密:从问题本质到三级缓存源码级解析
java·后端·spring·缓存·面试·循环依赖·三级缓存
RyFit2 小时前
SpringAI 常见问题及解决方案大全
java·ai
在角落发呆3 小时前
Linux转发配置:解锁网络互联的核心密码
linux·运维·网络
石山代码3 小时前
C++ 内存分区 堆区
java·开发语言·c++
绝知此事3 小时前
【算法突围 01】线性结构与哈希表:后端开发的收纳术
java·数据结构·算法·面试·jdk·散列表
无风听海3 小时前
C# 隐式转换深度解析
java·开发语言·c#
一只大袋鼠4 小时前
Git 进阶(二):分支管理、暂存栈、远程仓库与多人协作
java·开发语言·git
裴东青4 小时前
10-实战:RuoYi-Cloud的自动化发布
运维·ci/cd·自动化
哎呦,帅小伙哦4 小时前
Linux 时间:从原子钟到 clock_gettime 的每一面
linux·运维·服务器
德思特4 小时前
从 Dify 配置页理解 RAG 的重要参数
java·人工智能·llm·dify·rag