📖 本章预览
本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。
第四章:通信层 — gRPC 长连接架构
上一章我们跟踪了服务注册的全链路,其中 gRPC 通信层是请求从客户端到达服务端的"高速公路"。本章深入拆解这条高速公路的设计与实现。
4.1 为什么从 HTTP 切换到 gRPC
Nacos 1.x 的通信架构有三个致命问题:
| 场景 | 1.x 方案 | 问题 |
|---|---|---|
| 配置监听 | HTTP 长轮询(hold 住 30s) | Tomcat 线程池被大量 hold 住的连接占满 |
| 服务推送 | UDP 推送 | 不可靠,丢包无感知,客户端需要兜底轮询 |
| 每次请求 | HTTP 短连接 | 频繁建连/断连,TCP 三次握手开销大 |
Nacos 2.x 的 gRPC 长连接方案:
- 一条连接复用所有通信:注册、注销、订阅、配置监听、心跳、推送,全部走同一条 gRPC 连接
- 双向流:服务端可以随时通过已建立的连接向客户端推送消息
- HTTP/2 多路复用:一条 TCP 连接上并发多个请求,互不阻塞
4.2 双 gRPC Server 设计
Nacos 启动了两个 gRPC Server,端口不同,职责分离:
┌─────────────────────────────────────────────────┐
│ Nacos Server │
│ │
│ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ GrpcSdkServer │ │ GrpcClusterServer │ │
│ │ 端口: 主端口+1000 │ │ 端口: 主端口+1001 │ │
│ │ │ │ │ │
│ │ 处理客户端请求: │ │ 处理集群内部通信: │ │
│ │ · 服务注册/注销 │ │ · Distro 数据同步 │ │
│ │ · 配置发布/查询 │ │ · Raft 日志复制 │ │
│ │ · 服务订阅 │ │ · 配置变更集群同步 │ │
│ │ · 配置监听 │ │ · 健康状态同步 │ │
│ │ · 心跳保活 │ │ │ │
│ └──────────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────┘
为什么要分两个 Server?
- 安全隔离:SDK 端口对外暴露,Cluster 端口只在内网开放
- 流量隔离:大量客户端请求不会影响集群内部的数据同步
- 权限控制:通过
@InvokeSource注解限制调用来源
// 只允许 SDK 调用的 Handler
@InvokeSource(source = "sdk")
public class InstanceRequestHandler extends RequestHandler<...> { }
// 只允许集群内部调用的 Handler
@InvokeSource(source = "cluster")
public class DistroDataRequestHandler extends RequestHandler<...> { }
4.3 ConnectionManager — 连接池管理器(深度源码分析)
4.3.1 核心数据结构
public class ConnectionManager {
// 所有活跃连接:connectionId → Connection
Map<String, Connection> connections = new ConcurrentHashMap<>();
// 连接事件监听器注册中心
private final ClientConnectionEventListenerRegistry connectionEventListenerRegistry;
}
4.3.2 连接注册 — 建连时发生了什么
public synchronized boolean register(String connectionId, Connection connection) {
// 第一步:连接数限制检查(DDoS 防护)
if (checkLimit(connection)) {
return false;
}
// 第二步:存入连接池
connections.put(connectionId, connection);
// 第三步:通知所有 ClientConnectionEventListener(观察者模式)
connectionEventListenerRegistry.notifyClientConnected(connection);
// naming 模块收到通知 → 创建 Client 对象
// config 模块收到通知 → 初始化配置监听上下文
return true;
}
设计亮点:register 加了 synchronized,保证连接注册的原子性。但 getConnection 等读操作直接读 ConcurrentHashMap,不需要加锁。写安全 + 读高效的平衡。
🔒 解锁完整内容
本章剩余内容需要解锁后查看
以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。
加入知识星球你将获得:
- ✅ 全部 17 章完整内容 + 持续更新
- ✅ 配套源码 + 实战项目
- ✅ 一对一答疑 + 面试辅导
- ✅ 简历优化 + 内推机会
📚 本章完整目录
以下为本章完整目录结构,加入知识星球即可解锁全部内容。