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

思考:客户端负载均衡和服务器负载均衡有什么区别?

一、为啥微服务离不开负载均衡?

咱们先从一个常见场景说起:假设你做了个电商项目,“订单服务” 要调用 “商品服务” 查库存。一开始商品服务就 1 个实例,没问题;但用户多了,1 个实例扛不住,你扩容到 3 个 —— 这时候问题来了:订单服务该给哪个商品服务实例发请求?

并且不可以随便发,万一某个实例已经快满了,再发请求就会超时;也不能只发一个,其他实例闲得慌。这时候 “负载均衡” 就派上用场了:它就像个 “智能调度员”,把请求合理分配给各个实例,既避免单点过载,又能充分利用资源。

在 Spring Cloud 生态里,这个 “调度员” 有两种存在形式:一种在调用方(客户端),一种在统一入口(服务端)

二、客户端负载均衡

客户端负载均衡,典型代表是 Spring Cloud 里的 Ribbon 和 Spring Cloud LoadBalancer。它的核心逻辑是:调用服务的一方(客户端),自己决定该发请求给哪个服务实例

1. 原理:

举个具体例子:订单服务(客户端)调用商品服务(服务端),流程是这样的:

订单服务 → 注册中心(Nacos/Eureka)→ 获取商品服务实例列表 → 客户端负载均衡组件选实例 → 直接调用

  1. 拉取实例列表:订单服务启动时,会从注册中心(比如 Nacos)拉取商品服务的所有实例地址(比如 192.168.1.100:8081192.168.1.101:8081),存在本地缓存。
  2. 选择实例:当订单服务要调用商品服务时,本地的负载均衡组件(比如 Ribbon)会根据预设策略(比如轮询、加权随机),从缓存的实例列表里挑一个。
  3. 直接调用:订单服务直接向选中的商品服务实例发请求,中间没有额外的 “中间商”。

2. Spring Cloud 实战

其实在 Spring Cloud 里用客户端负载均衡特别简单,尤其是结合 OpenFeign(声明式调用)的时候,几乎零配置:

第一步:加依赖(以 Spring Cloud LoadBalancer 为例)
<!-- OpenFeign 依赖(自带 LoadBalancer 集成) -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Spring Cloud LoadBalancer 依赖 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
第二步:写 OpenFeign 接口
// 商品服务的 Feign 接口
@FeignClient(value = "product-service") // 服务名(注册中心里的名字)
public interface ProductFeignClient {// 调用商品服务的查库存接口@GetMapping("/product/stock/{productId}")Integer getStock(@PathVariable("productId") Long productId);
}
第三步:直接使用
@Service
public class OrderService {@Autowiredprivate ProductFeignClient productFeignClient;// 创建订单时查库存public void createOrder(Long productId) {// 这里调用 Feign 接口时,LoadBalancer 会自动做负载均衡Integer stock = productFeignClient.getStock(productId);if (stock <= 0) {throw new RuntimeException("商品库存不足!");}// ... 其他创建订单逻辑}
}

就这么简单!Spring Cloud LoadBalancer 会自动帮你做实例选择,默认是轮询策略,想改策略也容易,比如改加权随机,只需加个配置类就行。

3. 客户端负载均衡的优缺点

优点:

  • 无额外网络开销:客户端直接调用服务实例,不用经过中间转发,延迟低。
  • 去中心化:没有集中的 “调度中心”,就算某个客户端出问题,不影响其他服务,系统更抗造。
  • 灵活:不同客户端可以用不同策略,比如订单服务调用商品服务用轮询,用户服务调用商品服务用最少连接。

缺点

  • 客户端变复杂:每个服务作为 “客户端” 时,都要集成负载均衡组件,增加了一点点开发和维护成本(不过 Spring Cloud 已经帮我们封装得很好了,这点影响不大)。
  • 策略难统一:如果想给所有客户端改策略,得一个个改配置(比如从轮询改最少连接),不如服务端集中管理方便。

三、服务端负载均衡

服务端负载均衡,典型代表是 Nginx、HAProxy,还有硬件级的 F5。它的核心逻辑是:所有请求先到一个统一的 “入口”(负载均衡器),再由这个入口把请求转发给具体的服务实例

1. 原理:

还是拿电商举例,这次是用户通过 App 访问 “订单服务”,流程是这样的:

用户 App → Nginx(负载均衡器)→ 订单服务实例 1/2/3

  1. 请求集中入口:用户 App 发请求时,不是直接找订单服务,而是发给 Nginx(比如 api.youreshop.com 指向 Nginx 的地址)。
  2. Nginx 选实例:Nginx 配置里存了订单服务的所有实例地址,它会根据策略(比如轮询、IP 哈希)选一个实例。
  3. 转发请求:Nginx 把请求转发给选中的订单服务实例,实例处理完后,再通过 Nginx 把响应返回给 App(也可以直接返回,看配置)。

2. 服务端负载均衡的优缺点

优点:

  • 对客户端透明:客户端(比如 App)不用关心后端有多少实例,只需记住 Nginx 的地址就行,开发简单。
  • 集中管理:策略改起来方便,比如想给订单服务加权重,只需改 Nginx 配置,不用动任何服务。
  • 功能丰富:Nginx 不仅能做负载均衡,还能做静态资源缓存、限流、WAF 防护(防黑客攻击),一个组件顶多个用。

缺点

  • 单点风险:如果 Nginx 挂了,所有请求都进不来,整个系统就瘫了(不过可以搞 Nginx 集群,主从备份,解决单点问题)。
  • 额外网络开销:请求要经过 “App → Nginx → 服务实例” 两次网络跳转,比客户端负载均衡多一点延迟(但 Nginx 性能极强,一般情况下影响不大)。
  • 性能瓶颈:如果请求量特别大(比如每秒几十万次),Nginx 可能会成为瓶颈(这时候可以用 HAProxy 或者硬件 F5,性能更强)。

四、核心对比

对比维度客户端负载均衡(Ribbon/LoadBalancer)服务端负载均衡(Nginx/HAProxy)
调度位置调用方(客户端服务内部)统一入口(负载均衡器)
网络开销一次跳转(客户端→服务实例)两次跳转(客户端→负载均衡器→服务实例)
单点风险无(去中心化)有(需做集群备份)
策略管理分散配置(每个客户端独立)集中配置(改负载均衡器就行)
客户端依赖需集成负载均衡组件无(客户端只认负载均衡器地址)
适用场景微服务内部服务间调用外部请求(App/Web)接入微服务
典型组件Ribbon、Spring Cloud LoadBalancerNginx、HAProxy、F5

五、总结

负载均衡没有 “绝对最好” 的方案,只有 “最合适” 的场景。

  • 如果是微服务内部服务间调用,优先用客户端负载均衡(Spring Cloud LoadBalancer),快、灵活、无单点。
  • 如果是外部请求接入微服务,优先用服务端负载均衡(Nginx),好管理、能防护、对客户端友好。
  • 复杂项目就两者结合,外部 Nginx 扛入口,内部 LoadBalancer 提效率,这样的架构既稳定又高效。
http://www.dtcms.com/a/392256.html

相关文章:

  • 网络编程day04/05原始套接字
  • Yarn命令与npm命令的区别与联系(npm:Node.js的官方包管理工具;Yarn:Facebook开发的JavaScript包管理工具)
  • 【大语言模型 67】梯度压缩与稀疏通信
  • LeetCode第365题_水壶问题
  • OpenCV:DNN 模块实现图像风格迁移
  • 锤子助手插件功能六十四:禁用视频前置摄像头镜像
  • OpenHarmony NFC Tag驱动深度剖析:从HDF框架到NDEF读写全流程实战
  • 黑马头条_SpringCloud项目阶段四:多媒体短文章提交功能实现详解
  • TraceID串联数据孤岛:勤源全链路可观测性平台破解微服务“黑箱困境”
  • 随机梯度下降(SGD)算法及其在机器学习中的应用
  • 趣谈bug - the Norway problem
  • $attrs 和 $listeners 的使用场景和用法是什么?
  • [Linux]学习笔记系列 -- lib/radix-tree.c 基数树(Radix Tree) 整数键到指针的高效映射
  • Scikit-learn Python机器学习 - 回归分析算法 - 线性回归 (LinearRegression SGDRegressor)
  • ts的内置工具类型
  • 扫地车:守护多元场景的清洁 “多面手”
  • 力扣 136.只出现一次的数字
  • 【序列晋升】38 Spring Data MongoDB 的统一数据访问范式与实践
  • 如何将枯燥的大数据呈现为可视化的图和动画?
  • 前后端分离架构下,如何安全存储和使用 API 密钥?
  • Nano 编辑器快捷键
  • 《智能体教程》——如何构建多智能体系统:开发者实用指南
  • 小杰机器学习高级(three)——逻辑回归、二分类算法
  • Spring注解驱动开发:从XML到注解的完美蜕变
  • 【Spring AI】第三弹:深入解析 RAG 核心特性、关键流程、基于 Spring AI + 知识库实现 RAG 检索增强器
  • 【剪映】官方下载方式?【图文详解】电脑版下载?正版安全下载?最新版下载?
  • 《UE5_C++多人TPS完整教程》学习笔记56 ——《P57 未装备武器的蹲伏(Crouch Unequipped)》
  • AI人工智能训练师五级(初级)考试题库(1)1~100题
  • 【Python精讲 02】编程第一课:彻底掌握Python变量、数字、字符串与布尔值
  • Unity2D-Sprite