Spring Cloud:分布式系统的“粘合剂”(四)
专栏Spring Cloud个人主页手握风云目录一、负载均衡1.1. 问题1.2. 定义1.3. 分类二、Spring Cloud LoadBalancer2.1. 快速上手2.2. 负载均衡策略2.3. 底层原理三、多机部署3.1. 前置准备3.2. Maven 项目打包3.3. 服务器 Jar 包上传与后台启动一、负载均衡1.1. 问题在前面的远程调用基础代码中程序会通过 DiscoveryClient 根据服务名称拉取完整的服务实例列表但代码逻辑固定选取列表下标为 0 的第一个实例发起请求。这种写法在服务仅部署单实例时不会出现问题可一旦同一服务启动多份实例流量会全部集中到首个实例多节点扩容的价值完全无法发挥。右键服务启动配置选择 Copy Configuration 复制配置再通过 Modify options 菜单栏添加 VM 启动参数 -Dserver.port端口号以此修改不同实例的占用端口。本次演示共启动 3 个 product-service 服务端口分别为 9090、9091、9092全部注册至 Eureka 注册中心。package com.yang.order.service; import com.yang.order.mapper.OrderMapper; import com.yang.order.model.OrderInfo; import com.yang.order.model.ProductInfo; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; Slf4j Service public class OrderService { Autowired private OrderMapper orderMapper; Autowired private RestTemplate restTemplate; Autowired private DiscoveryClient discoveryClient; private AtomicInteger count new AtomicInteger(1); private ListServiceInstance instances; PostConstruct public void init() { //从Eureka中获取服务列表 instances discoveryClient.getInstances(product-service); } public OrderInfo selectOrderById(Integer orderId) { OrderInfo orderInfo orderMapper.selectOrderById(orderId); // 通过计数器 % 实例 下标索引 int index count.getAndIncrement() % instances.size(); String uri instances.get(index).getUri().toString(); String url uri /product/ orderInfo.getProductId(); log.info(远程调用url:{}, url); ProductInfo productInfo restTemplate.getForObject(url, ProductInfo.class); orderInfo.setProductInfo(productInfo); return orderInfo; } }借助 AtomicInteger 实现原子自增计数通过计数值对实例列表长度取模循环选中不同服务实例改造代码后重新测试请求会均匀分配至三台实例直观展现出负载均衡的基础效果。1.2. 定义负载均衡英文缩写为 LB是构建高并发、高可用分布式系统不可或缺的核心组件。随着业务流量持续上涨开发者通常会通过新增服务节点完成水平扩容而负载均衡的核心作用就是按照预设规则将客户端流量合理分摊到多台服务机器避免单节点压力过载整体提升集群的处理效率。团队初期仅一名员工工作量提升后新增多名员工负载均衡就相当于分配工作的规则均衡分摊任务充分发挥团队整体处理能力和多服务实例分流流量的设计思路完全一致。1.3. 分类真实业务场景下负载均衡的分配规则十分丰富除基础轮询外还可根据服务器硬件性能分配流量硬件配置更高的节点承载更多请求。为统一标准化实现行业内衍生出两类成熟的负载均衡架构分别是服务端负载均衡与客户端负载均衡二者最核心的区分标准是服务实例清单的存储位置。第一类是服务端负载均衡典型代表工具为 Nginx。整体流程为用户请求先统一发送到独立的负载均衡中间设备由均衡器存储全部后端服务清单通过内置算法挑选节点后转发请求所有流量都需要经过这一台集中式设备中转。第二类是客户端负载均衡功能以 SDK 类库的形式集成在调用方服务内部无需独立中间设备。Spring Cloud 早期采用 Ribbon 组件实现该能力但该组件已停止维护2020.0.1 及以上新版本统一使用官方自研的 Spring Cloud LoadBalancer。执行流程为客户端先向 Eureka 注册中心拉取全部可用服务实例列表在本地运行负载均衡算法筛选目标节点之后直接与选中的服务实例建立连接发起调用。二、Spring Cloud LoadBalancer2.1. 快速上手Spring Cloud 在 2020.0.1 版本之后正式移除了原有的 Ribbon 组件改用 Spring Cloud LoadBalancer 作为官方默认的客户端负载均衡实现方案也是当前新项目统一采用的标准组件。想要快速启用该组件实现负载均衡仅需完成两步核心配置。第一步是改造 RestTemplate 的 Bean 配置在创建 RestTemplate 的方法上添加 LoadBalanced 注解该注解会开启负载均衡拦截能力为后续服务名转发提供基础支撑。第二步需要修改远程调用的请求地址摒弃硬编码的 IP 与端口直接使用注册中心内注册的服务名称拼接 URL例如把 http://127.0.0.1:9090/product/{id} 替换为 http://product-service/product/{id}。package com.yang.order.config; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer; import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer; import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.core.env.Environment; public class CustomLoadBalancerConfiguration { Bean ReactorLoadBalancerServiceInstance randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) { String name environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new RandomLoadBalancer(loadBalancerClientFactory .getLazyProvider(name, ServiceInstanceListSupplier.class), name); } }package com.yang.order.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; LoadBalancerClient(name product-service, configuration CustomLoadBalancerConfiguration.class) Configuration public class BeanConfig { Bean LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }Spring Cloud LoadBalancerpackage com.yang.order.service; import com.yang.order.mapper.OrderMapper; import com.yang.order.model.OrderInfo; import com.yang.order.model.ProductInfo; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * author gao * date 2026/7/22 11:34 */ Slf4j Service public class OrderService { Autowired private OrderMapper orderMapper; Autowired private RestTemplate restTemplate; Autowired private DiscoveryClient discoveryClient; private AtomicInteger count new AtomicInteger(1); private ListServiceInstance instances; PostConstruct public void init() { //从Eureka中获取服务列表 instances discoveryClient.getInstances(product-service); } 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; } }持续重复调用订单接口 http://127.0.0.1:8080/order/1 进行功能验证查看三个 product-service 实例的运行日志能够清晰发现请求会自动分发到三台不同实例负载均衡能力正式生效。2.2. 负载均衡策略负载均衡策略是一套通用的流量分配逻辑不管是服务端均衡器还是客户端均衡组件底层设计思路都高度相似。Spring Cloud LoadBalancer 内置仅提供两种原生负载均衡策略分别是轮询策略与随机策略。轮询策略 RoundRobin 是组件默认使用的分配方案逻辑为请求按照顺序轮流分配给集群内每一台可用实例实现简单、适用绝大多数常规业务场景。随机选择 Random 策略则是每次发起请求时从全部可用实例中随机挑选一台处理请求分配逻辑无固定顺序。如果业务场景需要切换为随机策略支持自定义负载均衡算法实现。首先需要新建负载均衡配置类 LoadBalancerConfig在类中注入 RandomLoadBalancer 类型的 Bean同时有两个硬性要求配置类不能标注 Configuration 注解且该类需要处于 Spring 组件扫描范围内。完成策略 Bean 编写后还需要借助 LoadBalancerClient 注解绑定策略与目标服务。该注解添加在 RestTemplate 配置类上方其中 name 属性指定需要生效负载均衡策略的服务名称configuration 属性指向自定义的策略配置类。项目中仅存在 product-service 一个服务提供者因此直接使用单服务绑定注解LoadBalancerClient即可完成配置。2.3. 底层原理Spring Cloud LoadBalancer 的核心拦截载体是 LoadBalancerInterceptor该拦截器会拦截所有通过 RestTemplate 发起的 HTTP 远程调用自动完成服务名解析、实例筛选、地址替换全流程操作。public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor { private LoadBalancerClient loadBalancer; private LoadBalancerRequestFactory requestFactory; public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) { this.loadBalancer loadBalancer; this.requestFactory requestFactory; } public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) { this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer)); } public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException { URI originalUri request.getURI(); String serviceName originalUri.getHost(); Assert.state(serviceName ! null, Request URI does not contain a valid hostname: originalUri); return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution)); } }当请求进入 intercept 拦截方法后第一步会读取请求原始 URI提取 URI 中的 Host 作为服务 ID也就是我们拼接 URL 时填写的服务名称 product-service第二步调用 LoadBalancerClient 的 execute 执行方法传入解析得到的服务 ID进入实例选择逻辑。在 BlockingLoadBalancerClient 的 execute 方法内部会先调用 choose 方法执行负载均衡筛选。程序会根据服务 ID 获取对应的负载均衡器再调用均衡器内置的 choose 方法基于预设的轮询或随机策略从 Eureka 拉取的服务实例列表中选出一台可用 ServiceInstance。如果筛选后没有找到任何可用实例程序会直接抛出无服务实例异常若成功获取有效实例则将请求 URL 中的服务名替换为实例真实 IP 与端口最终发起远程调用完成一整套客户端负载均衡流程。三、多机部署3.1. 前置准备服务器安装 MySQL导入业务初始化 SQL修改项目配置文件替换数据库连接账号、密码适配服务器 MySQL。3.2. Maven 项目打包分别对 3 个微服务打包eureka-server、order-service、product-service标准 SpringBoot Maven 打包流程。3.3. 服务器 Jar 包上传与后台启动Eureka、Order 单实例启动Product 多实例通过 --server.port端口 区分端口分别输出独立日志文件

相关新闻

Unity责任链模式实战:游戏事件处理与代码解耦

Unity责任链模式实战:游戏事件处理与代码解耦

1. 项目概述:为什么Unity开发者需要掌握责任链模式?如果你在Unity里写过稍微复杂一点的逻辑,比如处理一个UI按钮点击后要经过登录验证、资源检查、冷却判断、最终执行一连串操作,或者处理一个游戏事件需要被多个系统(音…

2026/7/27 5:56:44 阅读更多 →
Claude Opus在ARC-AGI-3基准测试创SOTA:AGI评估标准变革与开发实践

Claude Opus在ARC-AGI-3基准测试创SOTA:AGI评估标准变革与开发实践

最近在 AI 圈子里,一个消息引起了不小的震动:Claude Opus 在 ARC-AGI-3 基准测试中创下了新的 SOTA(State-of-the-Art)成绩。但如果你以为这只是又一个“模型刷榜”的新闻,那就错过了真正重要的信息。这个成绩背后真正…

2026/7/27 5:56:44 阅读更多 →
NopCommerce插件开发实战指南:从入门到部署

NopCommerce插件开发实战指南:从入门到部署

1. NopCommerce插件开发概述NopCommerce作为目前最流行的开源电商系统之一,其插件机制为开发者提供了强大的扩展能力。在4.9.3版本中,插件架构经过多次优化,开发体验更加友好。我最近刚完成一个支付网关插件的开发,过程中积累了不…

2026/7/27 5:56:44 阅读更多 →

最新新闻

MySQL 入门:库、表、行、主键是什么

MySQL 入门:库、表、行、主键是什么

🥰个人主页:会编程的土豆(欢迎来访) 💎作者简介:后端学习者 ❄️个人专栏:数据结构与算法,数据库,leetcode ✨那些你一个人走过的夜路,终将化作照亮未来的光 …

2026/7/27 6:10:55 阅读更多 →
WGAN-GP在光伏发电突变预测中的应用与实践

WGAN-GP在光伏发电突变预测中的应用与实践

1. 项目背景与核心价值光伏发电领域一直面临一个关键挑战:如何准确预测"魔法时刻"——那些光照条件突然变化导致发电量陡增或骤降的特殊时段。传统基于历史数据的统计方法往往难以捕捉这些非线性突变,而生成对抗网络(GAN)为我们提供了新的可能…

2026/7/27 6:10:55 阅读更多 →
概率思维与贝叶斯方法在AI中的应用

概率思维与贝叶斯方法在AI中的应用

1. 概率思维:AI应对不确定世界的底层逻辑在现实世界中,我们每天都要面对各种不确定性——天气预报说"70%概率下雨"该不该带伞?医生根据检查结果告诉你"90%可能是良性肿瘤"要不要手术?这些判断背后&#xff0c…

2026/7/27 6:10:55 阅读更多 →
Adobe国际认证培训课程  备考  题型

Adobe国际认证培训课程 备考 题型

✅近期很多备考Adobe认证的家人们会问培训课程有多长时间,自己好安排时间学习,今天就给大家总结了一下 🥇PS专家认证:课程总时长约20h ❶1—81节:基础入门课 ❷87—88节:考前须知 ❸89—92节:理…

2026/7/27 6:10:55 阅读更多 →
Jetson AGX Orin环境下ROS2 Foxy编译lightning_lm

Jetson AGX Orin环境下ROS2 Foxy编译lightning_lm

step1:下载lightning_lm (base) zfjdzfjd-robot:~/zhankun$ git clone https://gitee.com/zhankun3280/lightning-lm Cloning into lightning-lm... remote: Enumerating objects: 605, done. remote: Counting objects: 100% (605/605), done. remote: Compressing objects: 1…

2026/7/27 6:10:55 阅读更多 →
CTF逆向工程入门:从零构建知识体系与实战路径

CTF逆向工程入门:从零构建知识体系与实战路径

1. 从零到一:逆向工程在CTF中的角色与价值 如果你对网络安全竞赛(CTF)感兴趣,尤其是看到那些“逆向工程”(Reverse Engineering)题目时,既觉得酷炫又感到无从下手,那么这篇文章就是为…

2026/7/27 6:09:55 阅读更多 →

日新闻

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:54 阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻