当前位置: 首页 > news >正文

【微服务】(4) 负载均衡

一、问题

        当远程调用的服务有多个实例时,instances.get(0) 每次获取的都是服务列表中的第一个实例,可能会导致每次都是对同一个实例发起请求,让该实例压力过大,而其它的实例却没有得到利用。

        在服务流量增大时,为了分担压力,会增加机器进行扩容。负载均衡组件的作用:按照策略合理分配流量到每个实例,应用于高并发、高可用的系统中。

二、实现轮询策略的负载均衡

        product-server 创建多个实例

        再创建 2 个实例,9091、9092:

        启动:

        order-server 轮询向不同实例发起请求,实现简单的负载均衡

    // 原子计数器,保证线程安全private AtomicInteger count = new AtomicInteger(0);private List<ServiceInstance> instances;private int size;@PostConstructpublic void init() {//从Eureka中获取服务列表,指定要查询的服务名// 在应用启动、类加载时,初始化服务列表,避免在请求时再次获取导致每次拿到的服务列表顺序不同instances = discoveryClient.getInstances("product-service");size = instances.size();}@Overridepublic OrderInfo getOrder(String orderId) {// 打印当前线程名称log.info("当前处理线程:{}", Thread.currentThread().getName());OrderInfo orderInfo = orderMapper.selectOrderById(orderId);// 多个商品服务,请求计数器 % size 获得当前请求的服务实例在列表中的 index,实现轮询策略的负载均衡String uri = instances.get(count.getAndIncrement() % size).getUri().toString();// 构造访问商品服务的 urlString url = uri+"/product/"+orderInfo.getProductId();log.info("访问商品服务的 url: " + url);// 使用 restTemplate 访问商品服务ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);// 把商品详情设置到 orderInfo 中orderInfo.setProductInfo(productInfo);return orderInfo;}
  • 为什么使用原则类计数器:spring boot 集成的 tomcat 中使用了线程池来处理并发的 http 请求,为了避免线程不安全问题(不是原子的加法操作,会导致最终计数结果不符合预期),使用原子类定义计数器。
  • 为什么在类加载时就初始化服务里表:每次获取的服务列表是不一样的,我们希望在整个启动的应用中,服务列表不变。
  • 该案例存在 bug:服务列表无法实时更新,感知实例的上线、下线。

        执行结果:

三、负载均衡的实现

  • 服务端负载均衡:通过部署的负载均衡器(如 Nginx),来选择服务器。

 

  • 客户端负载均衡:在客户端从注册中心获取服务列表,通过公共类库提供的负载均衡策略的实现,来选择服务器。

  • 常见的客户端负载均衡库:Ribbon 因 Netflix 不再维护,Spring Cloud 官方弃用。现在使用 Spring Cloud 官方维护的 Spring Cloud LoadBalancer。

四、Spring Cloud LoadBalance

1、快速上手

        1、给 RestTemplate Bean 添加:@LoadBalanced

@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}
}

        2、改 IP:端口号 为服务名:

    @Overridepublic OrderInfo getOrder(String orderId) {OrderInfo orderInfo = orderMapper.selectOrderById(orderId);// 构造访问商品服务的 urlString url = "http://product-service/product/"+orderInfo.getProductId();// 使用 restTemplate 访问商品服务ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);// 把商品详情设置到 orderInfo 中orderInfo.setProductInfo(productInfo);return orderInfo;}

        3、启动 注册中心、订单服务、多个商品服务实例,测试:实现了负载均衡,每个实例收到的请求差不错。

2、负载均衡策略

        Spring Cloud LoadBalancer 实现了两种负载均衡策略:

  • 轮询(Round Robin,默认):循环依次选择实例。
  • 随机(Random):随机选择一个实例。
  • 也可以自定义策略:

        自定义一个随即策略 bean,参考官方文档:Spring Cloud LoadBalancer :: Spring Cloud Commons

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

注意:使用 @LoadBalancerClient 或者 @LoadBalancerClients 给指定服务配置自定义负载均衡类,要么自定义类不加 @Configuration 注解,要么在 Spring 扫描之外(目的:期望实现对局部服务生效,而不是全局服务,不按提示做就会产生冲突)。

        在远程调用模板上,加上 @LoadBalancerClient 注解,指定对 product-server 服务生效,应用自定义负载均衡策略:

@LoadBalancerClient(name = "product-service", configuration = CustomLoadBalancerConfiguration.class)
@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}
}

        重新启动 order-service,测试:每个实例收到的请求数量是随机的。

3、LoadBalancer 原理

        LoadBalancerInterceptor 类会对 RestTemplate 远程调用的请求进行拦截:

        跟踪 execute:

        跟踪 choose:

        跟踪 choose:

        跟踪随机:

        跟踪轮询:

http://www.dtcms.com/a/576870.html

相关文章:

  • 【Qt】Qt实践记录3——UDP通信
  • 考研408--计算机网络--day3--
  • 从云原生部署到智能时序分析:基于 Kubernetes 的 Apache IoTDB 集群实战与 TimechoDB 国产化增强特性深度解析
  • LLaVA-NeXT 学习笔记
  • 投资融资理财网站模板网站搭建福州公司
  • OpenStack创建实例一直处于创建且未分配IP问题解决
  • C++的诗行:一文掌握内存管理中 new/delete 接口正确调用与常见场景适配
  • 谷歌网站 百度做网站对服务器什么要求高
  • Smartproxy 企业级解决方案
  • 图像分类深度学习
  • 自监督骨干(DINOv2)用于内镜分割与跟踪的全面实现分析
  • 6.基础--SQL--DDL表操作-创建查询
  • 《算法闯关指南:优选算法--位运算》--34.判断字符是否唯一,35.丢失的数字
  • 四川建设网网站首页网站开发 周期
  • linux怎么检查磁盘是否有坏道
  • 微信小程序开发——第三章:WXML 与 WXSS —— 小程序页面结构与样式设计
  • Pytorch 内存布局优化:Contiguous Memory
  • pytorch-张量
  • MYSQL CDC 同步到 PAIMON
  • MATLAB实现高光谱分类算法
  • Linux:WSL常用指令总结
  • Git 最近提交中不小心包含了多余的文件怎么办
  • T100打破远程孤岛-轻松实现异地组网-P2P打洞+UDP NAT 穿透
  • 建设网站人员名单企业网站建设报价单
  • 联通研究院:基于‘多模态SCA+全周期协同’的中间件开源风险治理实践
  • 五子棋项目Alpha-Beta剪枝与MCTS+神经网络实现人机对弈算法对比报告
  • 测试题-5
  • 商洛免费做网站公司网站设计策划案
  • Java 项目 HTTP+WebSocket 统一权限控制实战
  • Tomcat日志配置与优化指南