技术选型 RPC 框架

在"现代分布式系统 / 微服务底层通信"里,有两个常用的 RPC 框架:gRPC + Protocol Buffers 和 OpenFeign。

  • gRPC + Protobuf
    • 真正的"高性能RPC框架"
    • 基于 HTTP/2 + 二进制协议
    • 强类型IDL(.proto)
    • 多语言友好(Go / Java / Python / C++ 等)
  • OpenFeign
    • 本质是"声明式 HTTP 客户端"
    • 通常基于 REST(HTTP/1.1 + JSON)
    • 强依赖 Spring Cloud 生态
    • 更像是"调用远程 REST API 的优雅封装",不算纯RPC

👉 换句话说:

  • gRPC 是"协议级RPC方案"
  • OpenFeign 是"开发体验层封装工具"

现代大厂更偏向:

  • gRPC + Protocol Buffers

典型场景:

  • 微服务内部通信
  • 高QPS系统(交易、推荐、实时计算)
  • 多语言服务互调

原因:

  • 性能高(比 JSON 快很多)
  • 网络开销小(序列化体积小)
  • 支持 streaming(长连接)

传统Java微服务 / Spring Cloud体系

更偏向:

  • OpenFeign

典型场景:

  • B端业务系统(订单、用户、库存)
  • 内部系统之间调用
  • CRUD为主的服务

原因:

  • 上手极其简单(写接口就能调)
  • 和 Spring Boot 无缝集成
  • 调试方便(直接 HTTP)

趋势比较明确:

gRPC 在上升,OpenFeign 在"稳定但不再增长"

原因:

  1. 云原生(K8s)推动 gRPC
  2. 多语言架构越来越普遍
  3. 性能要求越来越高
  4. REST + JSON 在内部调用显得"太重"

但注意:

  • 外部 API(对前端 / 对第三方)仍然是 REST(不会用 gRPC)
  • 所以现实是:
    • 内部:gRPC
    • 外部:REST(内部调用外部服务时可能用 Feign)

用 OpenFeign 调第三方服务,并不需要它注册到注册中心。

只有在这种情况下才需要注册中心(比如 Nacos):调用"自己体系里的微服务"

例如:

text 复制代码
order-service → user-service

这时候你可以写:

java 复制代码
@FeignClient("user-service")

Feign 会:

  • 去注册中心找 user-service
  • 做服务发现 + 负载均衡

调用第三方服务时直接写死 URL(或配置 URL)

java 复制代码
@FeignClient(name = "payment", url = "https://api.xxx.com")
public interface PaymentClient {
    @PostMapping("/pay")
    PayResponse pay(PayRequest req);
}

👉 这里:

  • name 只是一个标识
  • url 才是真正访问地址
  • ❗ 不走注册中心

有时候会这样设计:混合(网关 + 第三方)

text 复制代码
Feign → 网关 → 第三方

👉 "Feign → 网关 → 第三方"本质就是:你不直接调第三方,而是先调你自己的一个'中间服务(或网关)',由它统一转发到第三方。"

这里的"网关"不一定是传统意义上的 API Gateway(比如 Spring Cloud Gateway)

更常见的是两种实现:

✅ 方式1(更主流):专门的"第三方接入服务"

text 复制代码
Feign → payment-adapter-service → 第三方支付

✅ 方式2:网关转发(较少用于复杂业务)

text 复制代码
Feign → API Gateway → 第三方

👉 实际生产中:方式1更多

架构:

text 复制代码
[order-service]
       ↓ Feign
[payment-adapter-service]   ←(自己写的服务)
       ↓ HTTP
[支付宝 / Stripe / PayPal]

涉及:

  • OpenFeign(内部调用)
  • Spring Boot(实现 adapter 服务)

不直接 Feign 调第三方,原因在于:

✅ 1. 统一接入(解耦)

如果直接调第三方:

text 复制代码
order-service → 支付宝
user-service → 支付宝
coupon-service → 支付宝

👉 改一个接口,全崩

而用 adapter:

text 复制代码
所有服务 → payment-adapter → 支付宝

👉 改动只在一处

✅ 2. 安全控制(必须)

第三方支付通常需要:

  • 私钥
  • 签名算法
  • token

👉 不能把这些散落在各个服务里

✅ 3. 统一处理复杂逻辑

比如:

  • 重试
  • 限流
  • 幂等
  • 日志
  • 异常转换

✅ 4. 协议转换

内部你可能用:

  • JSON

第三方可能用:

  • form-data
  • XML(很多支付还在用)

👉 adapter 负责"翻译"

👉 Feign ≠ 服务发现工具

👉 它只是一个"声明式 HTTP 客户端"

  • 有注册中心 👉 可以做服务发现
  • 没有注册中心 👉 就是普通 HTTP 调用工具

👉 gRPC + Protocol Buffers 本身也不依赖注册中心,它们只是"通信协议 + 序列化方式"。

✅ gRPC 可以直连调用,也可以配注册中心

gRPC 最基础的调用方式(没有注册中心)最原始、也是最简单的方式就是直连

服务端:

text 复制代码
启动在 10.0.0.1:50051

客户端:

java 复制代码
ManagedChannel channel = ManagedChannelBuilder
    .forAddress("10.0.0.1", 50051)
    .usePlaintext()
    .build();

👉 这就已经能调了

👉 完全不需要 Nacos

生产环境中之所以配置注册中心是因为实际生产环境有这些问题:
服务实例不止一个

text 复制代码
user-service:
  10.0.0.1
  10.0.0.2
  10.0.0.3

👉 不能写死一个 IP

实例会动态变化(扩缩容)

  • Kubernetes 扩容
  • 容器重启
  • 节点漂移

👉 IP 会变

需要负载均衡

gRPC 默认是:

  • 单连接
  • 单目标

👉 需要额外机制做 LB

于是就引入"服务发现"(注册中心)

👉 架构变成:

text 复制代码
client → 注册中心 → service 实例列表 → gRPC 调用

gRPC + 注册中心有两种主流方式:

✅ 方式1:自己从注册中心拉地址(最常见)

text 复制代码
1. 从 Nacos 拿到实例列表
2. 自己做负载均衡
3. 建立 gRPC 连接

👉 这种方式灵活,但需要自己封装

✅ 方式2:用 gRPC 的服务发现机制

gRPC 支持:

  • DNS
  • xDS(Envoy / Service Mesh)

比如在 Kubernetes 里:

text 复制代码
user-service.default.svc.cluster.local

👉 gRPC 直接用服务名解析

gRPC 性能更高的原因

👉 gRPC 比基于 REST(HTTP + JSON)的方案性能更高,核心不是"某一项优化",而是"协议层 + 序列化 + 连接模型"整体更高效。

二进制序列化更高效

gRPC 使用 Protocol Buffers,相比于 JSON:

json 复制代码
{"userId":123,"userName":"Tom"}

vs Protobuf(实际是二进制):

text 复制代码
更短、更紧凑(不可读)
  • 体积更小(通常小 30%~70%)
  • 解析更快(不用字符串解析)
  • 字段是编号而不是字符串 key

👉 直接结果:

  • 网络传输更快
  • CPU 消耗更低

基于 HTTP/2(而不是 HTTP/1.1)

gRPC 默认跑在 HTTP/2 上,而 REST 大多还是 HTTP/1.1,HTTP/2 带来的优势:

1️⃣ 多路复用(Multiplexing)

👉 一个 TCP 连接可以同时跑多个请求

text 复制代码
HTTP/1.1:一个连接基本串行(或少量并发)
HTTP/2:一个连接并发 N 个请求

2️⃣ 头部压缩(HPACK)

  • HTTP header 不再重复传
  • 减少带宽占用

3️⃣ 长连接(减少握手)

  • 不用频繁建连接
  • 避免 TCP + TLS 开销

减少不必要的"文本处理"

REST(JSON)的问题:

  • 字符串解析(慢)
  • 字段名重复(浪费带宽)
  • 类型不严格(需要额外校验)

gRPC:

  • 强类型(.proto 定义)
  • 编译期生成代码
  • 直接映射内存结构

👉 本质是:少做了很多"解释工作"

代码生成(零反射/低反射)

使用 Protocol Buffers 后:

text 复制代码
.proto → 自动生成 Java / Go / Python 代码

调用时:

java 复制代码
stub.getUser(request)
  • 不需要像 JSON 那样反射解析
  • 没有 Map → Object 转换
  • 几乎是"函数调用体验"

支持流式通信(Streaming)

gRPC 原生支持:

  • Server Streaming
  • Client Streaming
  • Bidirectional Streaming
text 复制代码
一个连接上持续传数据

👉 对比 REST:

  • REST 通常是"一问一答"
  • 做流式要靠轮询 / WebSocket(更重)

gRPC 不适用的场景

1️⃣ 对外公开 API(前端 / 第三方)

👉 几乎一定不能用 gRPC

原因:

  • 浏览器原生不支持(需要 gRPC-Web,限制多)
  • 调试困难(不像 JSON 能直接看)
  • 生态不通用(合作方不一定支持)

👉 标准做法:

  • 外部统一用 REST(HTTP + JSON)
  • 内部才用 gRPC

2️⃣ 要求"强可调试性"的系统

👉 比如:

  • B 端后台系统
  • 运维接口
  • 调试频繁的业务 API

问题:

  • gRPC 是二进制(不可读)
  • 无法直接用 curl / Postman 调

👉 对比:

  • REST:一眼看懂请求和响应
  • gRPC:需要工具 + .proto

3️⃣ 多团队 / 异构系统且"协议无法统一"

👉 如果对接方:

  • 不愿意维护 .proto
  • 技术栈混乱(老系统、PHP等)
  • 无法引入 gRPC SDK

👉 强行用 gRPC 会带来:

  • 接入成本极高
  • 推不动

4️⃣ 简单 CRUD / 低并发系统

👉 比如:

  • 后台管理系统
  • 内部工具平台

问题:

  • 性能不是瓶颈
  • 引入 gRPC 增加复杂度

👉 现实情况:

  • REST + OpenFeign 更简单

5️⃣ 对接第三方(支付 / 短信 / OAuth 等)

👉 现实是:

  • 第三方几乎全部是 REST

比如:

  • 支付接口
  • 登录授权
  • 短信服务

👉 只能用 HTTP

Feign 底层原理

👉 OpenFeign 的本质就是"用动态代理把接口方法调用,转成一次 HTTP 请求"。

👉 Feign = 动态代理 + 注解解析 + HTTP 客户端封装

代码结构:

java 复制代码
@FeignClient("user-service")
public interface UserClient {
    @GetMapping("/user/{id}")
    User getUser(@PathVariable("id") Long id);
}

调用:

java 复制代码
userClient.getUser(1L);

启动时:

  • Spring 扫描到 @FeignClient
  • 为这个接口生成一个代理对象(Proxy)

👉 用的是:

  • JDK 动态代理(Proxy.newProxyInstance

2️⃣ 方法调用被"拦截"

当你调用:

java 复制代码
userClient.getUser(1L);

👉 实际进入的是:

text 复制代码
InvocationHandler.invoke()

3️⃣ 解析注解(核心步骤)

Feign 会解析:

  • @GetMapping("/user/{id}")
  • @PathVariable
  • 参数值

👉 生成:

text 复制代码
HTTP Method: GET
URL: http://user-service/user/1

4️⃣ 构建 RequestTemplate

Feign 内部有个核心对象:

text 复制代码
RequestTemplate

里面包含:

  • URL
  • Header
  • Body
  • Query 参数

5️⃣ 负载均衡(如果有注册中心)

如果你写的是:

java 复制代码
@FeignClient("user-service")

👉 会结合:

  • Spring Cloud LoadBalancer(或 Ribbon)
    流程:
text 复制代码
user-service → 注册中心 → 获取实例列表 → 选一个实例

6️⃣ 发起 HTTP 请求

Feign 本身不发请求,它会委托底层客户端:

常见实现:

  • JDK HttpURLConnection(默认)
  • Apache HttpClient
  • OkHttp(最常用)

👉 最终发出真实 HTTP 请求

7️⃣ 解析响应(Decoder)

返回的是 JSON:

json 复制代码
{"id":1,"name":"Tom"}

Feign 会用:

  • Jackson(默认)

👉 转成:

java 复制代码
User 对象

核心组件拆解

Feign 内部关键组件:

1️⃣ Contract(契约解析器)

👉 作用:解析注解

  • Spring MVC 注解 → HTTP 语义

2️⃣ Encoder(编码器)

👉 作用:把 Java 对象 → HTTP 请求体

比如:

java 复制代码
User → JSON

3️⃣ Decoder(解码器)

👉 作用:HTTP 响应 → Java 对象

4️⃣ Client(HTTP执行器)

👉 真正发请求的地方

5️⃣ LoadBalancer(负载均衡)

👉 结合注册中心使用

6️⃣ Retryer(重试机制)

👉 请求失败自动重试

7️⃣ Logger(日志)

👉 打印请求/响应

Feign 是"伪 RPC"

写的是:

java 复制代码
userClient.getUser(1);

看起来像:

text 复制代码
本地方法调用

但实际上:

text 复制代码
→ HTTP 请求
→ JSON 序列化
→ 网络通信

Feign 只是"让 HTTP 看起来像 RPC"

五、vs gRPC

Feign gRPC
调用本质 HTTP + JSON HTTP/2 + Protobuf
是否真RPC ❌ 伪RPC ✅ 真RPC
性能 一般
易用性 较复杂

Feign 这么优雅的本质原因:

👉 "用接口 + 注解 + 动态代理,把模板代码全隐藏了"

如果不用 Feign,你要写:

java 复制代码
RestTemplate.exchange(...)

👉 Feign 帮你自动生成

总结:

👉 "Feign 通过动态代理拦截接口调用,结合注解解析生成 HTTP 请求,并委托底层 HTTP 客户端执行,从而实现声明式远程调用。"

gRPC 实现负载均衡的方式

👉 gRPC 默认是"客户端负载均衡(Client-side LB)",而不是服务端负载。

但在生产里,两种模式都能用,只是侧重点不同。

✅ 客户端负载均衡(gRPC 默认)

text 复制代码
client 拿到所有实例列表 → 自己选一个 → 直连
text 复制代码
client
  ↓
(自己做LB)
  ↓
server1 / server2 / server3

✅ 服务端负载均衡(传统模式)

text 复制代码
client → 负载均衡器 → 转发到某个 server
text 复制代码
client
  ↓
Load Balancer(Nginx / Envoy)
  ↓
server1 / server2 / server3

gRPC 选用"客户端负载的核心原因:性能 + 连接模型

1️⃣ gRPC 是长连接(HTTP/2)

  • 一个连接会复用很多请求
  • 如果走服务端 LB:

👉 所有请求会"粘"在同一个后端实例上

text 复制代码
client → LB → server1(一直是它)

👉 负载就不均匀了 ❗

2️⃣ 客户端可以"更聪明地选节点"

客户端拿到所有实例后可以:

  • round-robin(轮询)
  • pick-first(选一个)
  • weighted(权重)
  • latency-aware(延迟优先)

👉 比单纯转发更灵活

3️⃣ 少一跳网络

text 复制代码
客户端LB: client → server
服务端LB: client → LB → server

👉 少一次转发:

  • 延迟更低
  • 吞吐更高

客户端负载实现主要依靠 gRPC 内部的两个核心组件:

1️⃣ Name Resolver(服务发现)

负责拿到服务实例列表:

来源可以是:

  • DNS
  • Kubernetes Service
  • 注册中心(如 Nacos)

👉 输出:

text 复制代码
server1, server2, server3

2️⃣ Load Balancer(负载策略)

常见策略:

✅ pick_first(默认)

text 复制代码
选一个实例,一直用

👉 优点:简单

👉 缺点:不均衡

✅ round_robin(最常用)

text 复制代码
轮流选 server1 → server2 → server3

👉 需要开启配置

✅ xDS(高级)

结合:

  • Istio
  • Envoy

支持:

  • 动态权重
  • 熔断
  • 灰度发布

虽然 gRPC 偏向客户端 LB,但下面场景会用服务端 LB:

1️⃣ 跨语言 / 多团队统一入口

text 复制代码
client → Envoy → gRPC service

👉 好处:

  • 所有流量统一控制
  • 不需要每个客户端实现 LB

2️⃣ Service Mesh(主流大厂方案)

比如:

  • Istio + Envoy

架构:

text 复制代码
client sidecar → server sidecar → service

👉 LB 在 sidecar 做

👉 本质:

  • "伪客户端LB"(代理帮你做)

3️⃣ 对外暴露 gRPC 服务

text 复制代码
外部 → LB → gRPC service

👉 必须要入口层

两种方式对比

维度 客户端 LB 服务端 LB
延迟 更低 多一跳
负载均衡效果 更好 容易不均
实现复杂度 客户端复杂 服务端复杂
控制能力 分散 集中
扩展性 一般

大厂不会只用一种,而是:

text 复制代码
        外部流量
           ↓
      LB / Gateway
           ↓
   内部服务(gRPC)
           ↓
   客户端负载均衡

或者:

text 复制代码
Service Mesh(Istio)
→ sidecar 做 LB(xDS)

👉 本质是:

  • 外部:服务端 LB
  • 内部:客户端 LB / mesh LB

总结:

👉 "gRPC 默认采用客户端负载均衡,由客户端获取服务实例并选择目标节点,从而避免 HTTP/2 长连接导致的负载不均问题,同时减少一次网络跳转,提高性能。"

Feign 负载均衡

👉 OpenFeign 是"客户端负载均衡"(Client-side LB)

text 复制代码
Feign client
   ↓
拿到服务实例列表(注册中心)
   ↓
在本地选一个实例(负载均衡)
   ↓
直接发 HTTP 请求到该实例

👉 关键点在于:
"选哪个服务实例,是在客户端决定的"

Feign 本身不做负载均衡,它会配合:

  • Spring Cloud LoadBalancer(现在主流)
  • 或早期的 Ribbon

流程:

text 复制代码
@FeignClient("user-service")
        ↓
LoadBalancer 从注册中心拿实例列表
        ↓
选择一个实例(轮询等策略)
        ↓
Feign 发请求

对比"服务端负载均衡",服务端 LB(比如 Nginx)

text 复制代码
client → Nginx → server1/server2/server3
  • 客户端只知道一个入口
  • 不知道后面有多少实例
  • 转发由中间层完成

Feign(客户端 LB)

text 复制代码
client(Feign)
   ↓
server1 / server2 / server3(直接选)
  • 客户端知道所有实例
  • 自己做选择
  • 没有中间转发

Spring Cloud 选择客户端 LB 原因和 gRPC 类似:

✅ 1. 少一跳,性能更好

text 复制代码
客户端LB: client → server
服务端LB: client → LB → server

✅ 2. 更灵活

可以做:

  • 权重
  • 灰度发布
  • 按标签路由

✅ 3. 和注册中心天然结合

配合:

  • Nacos

👉 客户端可以直接拿到服务列表

现实中经常是"混合模式"

text 复制代码
       外部请求
           ↓
     Nginx / Gateway   ←(服务端LB)
           ↓
     微服务(Feign)
           ↓
   内部调用(客户端LB)
层级 负载方式
外部流量 服务端 LB
内部调用 客户端 LB(Feign)

总结:

👉 "Feign 采用客户端负载均衡,通过从注册中心获取服务实例列表并在客户端选择目标节点来完成请求分发。"

Feign 的负载均衡和 gRPC 的客户端负载本质区别

👉 本质区别不在"谁来选节点",而在"连接模型 + 负载粒度 + 实现位置"。

👉 OpenFeign 的负载均衡是"基于请求级别"的;
👉 gRPC 的客户端负载是"基于连接/流(stream)级别"的。

✅ Feign:HTTP 请求级负载

text 复制代码
每发一次 HTTP 请求 → 选一次实例
  • 粒度:请求级
  • 每个请求都重新负载均衡
  • 天然均匀

✅ gRPC:连接 / Stream 级负载

gRPC 基于 HTTP/2:

text 复制代码
一个连接(connection) → 多个请求(stream)
text 复制代码
client
  ├─ connection1 → server1
  │     ├─ stream1
  │     ├─ stream2
  │     └─ stream3
  └─ connection2 → server2
  • 粒度:连接 / 子连接(subchannel)
  • 请求复用连接
  • 不一定每个请求都重新选节点

1️⃣ Feign 更"平均",但成本更高

  • 每个请求重新选节点
  • 不存在连接粘性问题

👉 优点:

  • 简单
  • 均匀

👉 缺点:

  • 每次都有选择开销
  • 不能复用连接(HTTP/1.1为主)

2️⃣ gRPC 更高效,但可能"不均匀"

  • 一旦连接建立,请求会复用连接
  • 容易出现:
text 复制代码
大部分流量集中在某几个连接

👉 这就是经典问题:

❗ "gRPC round_robin 还是不均匀"

原因就在这里

负载均衡"位置"的差异

Feign

text 复制代码
Feign → LoadBalancer → HTTP Client

👉 负载均衡:

  • 调用前
  • 每次请求都会触发

依赖:

  • Spring Cloud LoadBalancer

gRPC

text 复制代码
gRPC Channel
   ↓
Subchannel(连接池)
   ↓
LoadBalancer

👉 负载均衡:

  • 连接管理层
  • 不是每次请求都触发

连接模型差异

Feign gRPC
协议 HTTP/1.1(通常) HTTP/2
连接 短连接 / 连接池 长连接
请求复用 强(多路复用)
负载粒度 请求级 连接 / stream 级

带来的实际影响

1️⃣ Feign 很少出现"不均衡问题"

因为:

  • 每次请求都重新选

2️⃣ gRPC 容易"热点连接"

比如:

  • 某个连接承载大量流量
  • 某些实例空闲

👉 需要:

  • 连接池调优
  • subchannel 数量控制
  • xDS / Istio

3️⃣ gRPC 更适合高并发

因为:

  • 连接复用
  • 少 TCP / TLS 开销

gRPC 不做"请求级负载的原因是:

👉 HTTP/2 的设计目标就是"减少连接",而不是"每次重新选择连接"

如果每次请求都选:

  • 就破坏了多路复用优势

总结:

👉 "Feign 的负载均衡发生在请求层,每个请求独立选择实例;而 gRPC 的负载均衡发生在连接层,通过管理 subchannel 和 stream 分发流量,因此在性能更高的同时,也带来了连接级不均衡的问题。"

解决 gRPC 负载不均衡问题

👉 gRPC 的"不均衡",本质不是负载算法不行,而是"HTTP/2 长连接 + 多路复用"导致流量粘在少数连接/实例上。

所以解决思路也不是只换个算法,而是从"连接层 + 策略层 + 架构层"一起下手

👉 从低成本到重方案:

  1. 调整客户端 LB 策略(round_robin 等)
  2. 增加连接数(subchannel / channel)
  3. 控制连接生命周期(定期重建)
  4. 引入请求级打散(限流/并发控制)
  5. 使用 xDS / Service Mesh(如 Istio)
text 复制代码
一个 gRPC 连接(HTTP/2)
    ↓
承载大量 stream(请求)
    ↓
流量"粘"在这个连接对应的 server 上

👉 即使你用 round_robin:

  • 只在"连接建立时"生效
  • 后续请求不会再重新选节点

✅ 方案1:开启 round_robin(基础但不够)

默认是 pick_first(选一个一直用)

👉 改成:

text 复制代码
round_robin

效果:

text 复制代码
连接分散到多个实例

⚠️ 但问题:

  • 仍然是"连接级均衡"
  • 如果连接数少,还是会不均

👉 结论:必须做,但不够

✅ 方案2:增加连接数(最关键)

👉 核心思想:

既然是"连接级均衡",那就多建几个连接

text 复制代码
1 个 Channel → N 个 Subchannel(连接)

或者:

text 复制代码
多个 Channel(连接池)

效果:

text 复制代码
client
  ├─ conn1 → server1
  ├─ conn2 → server2
  ├─ conn3 → server3

👉 流量自然更均匀

✅ 方案3:限制单连接并发(防止热点)

如果一个连接可以跑无限 stream:

👉 会出现:

text 复制代码
某个连接被打爆

解决:

  • 限制 max concurrent streams
  • 控制客户端并发

👉 让请求"被迫分散到其他连接"

✅ 方案4:连接定期重建

👉 问题:

  • 长连接会"越用越偏"

解决:

text 复制代码
定期关闭连接 → 重新建连接 → 重新负载均衡

👉 常见策略:

  • TTL(比如几分钟)
  • 空闲连接回收

✅ 方案5:客户端"智能负载"(进阶)

自定义策略,比如:

  • latency-aware(选延迟低的)
  • least-request(最少请求)
  • 权重(weighted)

👉 比简单 round_robin 更稳定

✅ 方案6:使用 xDS(大厂方案)

结合:

  • Envoy
  • Istio

👉 架构:

text 复制代码
client → sidecar(Envoy) → service

优点:

  • 动态下发 LB 策略
  • 支持:
    • 权重
    • 熔断
    • 限流
    • 灰度发布

👉 本质:

把负载均衡"从代码里拿出来,交给基础设施"

👉 一般不是单点优化,而是组合:

text 复制代码
✔ round_robin
✔ 多连接(connection pool)
✔ 限制并发
✔ 定期重建连接

如果是大厂:

text 复制代码
✔ + Service Mesh(Istio)

总结

👉 "gRPC 负载不均衡的本质是连接级调度问题,解决方案是增加连接粒度并控制连接生命周期,而不是单纯依赖负载算法。"
👉 "由于 gRPC 基于 HTTP/2 长连接,请求会复用连接,导致负载均衡发生在连接层而非请求层,从而可能出现流量倾斜。解决方法包括使用 round_robin 策略、增加 subchannel 数量、限制单连接并发、定期重建连接,以及在复杂场景下引入 xDS 或 Service Mesh 来实现更精细的流量调度。"

相关推荐
勤劳的进取家4 小时前
应用层基础
运维·网络·学习
计算机安禾4 小时前
【Linux从入门到精通】第37篇:NFS网络文件系统——无状态的数据共享
linux·网络·php
Name_NaN_None4 小时前
Android 手机投屏 iPad :公网+局域网免费方案
网络·计算机外设·电脑·远程工作
2401_873479404 小时前
深度解析IP查询工具与普通IP库的核心区别:选型指南与业务场景对照
网络协议·tcp/ip·php
古城小栈4 小时前
rust 亿级并发模型,实践完成
开发语言·网络·rust
垦利不5 小时前
websocket通信
网络·websocket·网络协议
酣大智5 小时前
POE概念
网络·wifi·无线·poe
byte轻骑兵5 小时前
【HID】规范精讲[7]: 蓝牙HID底层核心——基带与LMP依赖深度解析
网络·人工智能·人机交互·蓝牙·键盘·hid
RunningBComeOn5 小时前
为什么无法抓取到http之间的明文传输
网络·网络协议·http