Initial commit
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
# ConnPool 删除决策说明
|
||||
|
||||
**删除时间**: 2026-03-24
|
||||
**状态**: ✅ 已完成
|
||||
**决策依据**: YAGNI 原则(You Aren't Gonna Need It)
|
||||
|
||||
---
|
||||
|
||||
## 📋 ConnPool 的设计目的
|
||||
|
||||
### **原始意图**
|
||||
|
||||
```go
|
||||
// ConnPool 连接池 - 复用 net.Conn 以减少资源消耗
|
||||
type ConnPool struct {
|
||||
pools map[string][]net.Conn // key: 对端标识,value: 连接池
|
||||
maxSize int // 最大连接数
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**设计目标**:
|
||||
1. ✅ 复用已建立的连接到同一对端
|
||||
2. ✅ 避免每次都重新拨号(STUN/TURN/WS 等)
|
||||
3. ✅ 减少资源消耗(每个连接有内存和 goroutine 开销)
|
||||
|
||||
---
|
||||
|
||||
## 🤔 是否需要保留?
|
||||
|
||||
### **现状分析**
|
||||
|
||||
#### **实际情况**
|
||||
|
||||
在 MeshRay 的 P2P 通信模型中:
|
||||
|
||||
```
|
||||
Peer A ←→ Peer B
|
||||
↑
|
||||
└── 只需要一个连接
|
||||
```
|
||||
|
||||
**特点**:
|
||||
- ✅ 每个 Peer 对之间只需要**一个活跃连接**
|
||||
- ✅ 连接建立后持续使用,直到断开
|
||||
- ✅ 不需要"池"的概念(不是 Web 服务器的高并发场景)
|
||||
|
||||
---
|
||||
|
||||
#### **ConnPool vs ConnectionManager**
|
||||
|
||||
| 方案 | ConnPool(连接池) | ConnectionManager(连接管理器) |
|
||||
|------|-------------------|-------------------------------|
|
||||
| **复杂度** | 高(102 行代码) | 低(~50 行代码) |
|
||||
| **功能** | 连接池复用、大小限制、健康检查 | 简单映射管理、一对一连接 |
|
||||
| **数据结构** | `map[string][]net.Conn` | `map[string]net.Conn` |
|
||||
| **适用场景** | 高并发、多连接复用 | 一对一 P2P 连接 |
|
||||
| **维护成本** | 高(需要管理池生命周期) | 低(简单的 CRUD) |
|
||||
| **当前需求** | ❌ 不需要 | ✅ 正好满足 |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 删除理由
|
||||
|
||||
### **1. 过度设计**
|
||||
|
||||
**ConnPool 的复杂逻辑**:
|
||||
```go
|
||||
// 需要管理:
|
||||
- 连接池大小限制(maxSize)
|
||||
- 连接的获取(Get)
|
||||
- 连接的归还(Put)
|
||||
- 连接的健康检查
|
||||
- 过期连接的清理(Clear)
|
||||
- 并发控制(mutex)
|
||||
```
|
||||
|
||||
**但实际只需要**:
|
||||
```go
|
||||
// ConnectionManager 就够了:
|
||||
- 保存连接(Set)
|
||||
- 获取连接(Get)
|
||||
- 关闭连接(Close)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **2. 没有实际使用**
|
||||
|
||||
**审查结果**:
|
||||
```bash
|
||||
# 搜索整个项目
|
||||
grep -r "ConnPool" .
|
||||
grep -r "NewConnPool" .
|
||||
grep -r "pool\.Get\|pool\.Put" .
|
||||
```
|
||||
|
||||
**发现**:
|
||||
- ❌ **没有任何地方使用 ConnPool**
|
||||
- ❌ 只在文档中提到过
|
||||
- ❌ 是"为未来可能的需求"提前写的代码
|
||||
|
||||
---
|
||||
|
||||
### **3. 违反 YAGNI 原则**
|
||||
|
||||
**YAGNI** = **You Aren't Gonna Need It**(你不会需要的)
|
||||
|
||||
**ConnPool 的问题**:
|
||||
- ❌ 为不存在的"高并发场景"提前优化
|
||||
- ❌ 增加了 102 行代码的维护成本
|
||||
- ❌ 让架构变得更复杂
|
||||
- ❷ 实际上完全用不到
|
||||
|
||||
---
|
||||
|
||||
### **4. 正确的做法**
|
||||
|
||||
在 `connection_manager.go` 中直接管理:
|
||||
|
||||
```go
|
||||
type ConnectionManager struct {
|
||||
mu sync.RWMutex
|
||||
conns map[string]net.Conn // key: peerID
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (m *ConnectionManager) GetConnection(peerID string) net.Conn {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.conns[peerID]
|
||||
}
|
||||
|
||||
func (m *ConnectionManager) SetConnection(peerID string, conn net.Conn) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
// 关闭旧连接(如果有)
|
||||
if oldConn, exists := m.conns[peerID]; exists {
|
||||
oldConn.Close()
|
||||
}
|
||||
|
||||
m.conns[peerID] = conn
|
||||
}
|
||||
|
||||
func (m *ConnectionManager) CloseConnection(peerID string) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if conn, exists := m.conns[peerID]; exists {
|
||||
conn.Close()
|
||||
delete(m.conns, peerID)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**优点**:
|
||||
- ✅ 简单直接 - 就是普通的 map 管理
|
||||
- ✅ 每个 Peer 一个连接 - 符合实际需求
|
||||
- ✅ 无需连接池 - 不需要复杂的复用逻辑
|
||||
- ✅ 易于理解和维护
|
||||
|
||||
---
|
||||
|
||||
## 📊 如果未来真的需要 ConnPool
|
||||
|
||||
### **什么情况下需要?**
|
||||
|
||||
如果 MeshRay 未来支持:
|
||||
|
||||
1. **多路径传输** (Multipath Transport)
|
||||
```
|
||||
Peer A ←→ [Path 1] ←→ Peer B
|
||||
↘ [Path 2] ↗
|
||||
|
||||
// 需要同时维护多个连接
|
||||
```
|
||||
|
||||
2. **连接预热** (Connection Preheating)
|
||||
```go
|
||||
// 预先建立一批连接,等待分配
|
||||
pool.Preheat(10) // 预建 10 个连接
|
||||
```
|
||||
|
||||
3. **高并发场景** (High Concurrency)
|
||||
```go
|
||||
// 大量请求需要快速分配连接
|
||||
for i := 0; i < 1000; i++ {
|
||||
go func() {
|
||||
conn := pool.Get("peer-x")
|
||||
// ...
|
||||
}()
|
||||
}
|
||||
```
|
||||
|
||||
**那么可以加 ConnPool**,但现在是**完全不需要**的。
|
||||
|
||||
---
|
||||
|
||||
## ✅ 删除决策
|
||||
|
||||
### **删除的文件**
|
||||
|
||||
```
|
||||
core/pool/connpool.go (102 行)
|
||||
```
|
||||
|
||||
### **删除的目录**
|
||||
|
||||
```
|
||||
core/pool/ (空目录已自动清理)
|
||||
```
|
||||
|
||||
### **影响评估**
|
||||
|
||||
- ✅ **无负面影响** - 没有任何地方使用它
|
||||
- ✅ **代码更简洁** - 减少 102 行无用代码
|
||||
- ✅ **架构更清晰** - 移除不必要的抽象层
|
||||
- ✅ **维护更容易** - 少一个需要理解的组件
|
||||
|
||||
---
|
||||
|
||||
## 🎯 技术原则
|
||||
|
||||
### **本次决策遵循的原则**
|
||||
|
||||
1. **YAGNI 原则**
|
||||
- ✅ You Aren't Gonna Need It
|
||||
- ❌ 不要为不存在的需求写代码
|
||||
|
||||
2. **KISS 原则**
|
||||
- ✅ Keep It Simple, Stupid
|
||||
- ❌ 不要过度设计
|
||||
|
||||
3. **实事求是**
|
||||
- ✅ 根据实际需求选择技术方案
|
||||
- ❌ 不要模仿大厂的架构(场景不同)
|
||||
|
||||
4. **保持简洁**
|
||||
- ✅ 简单往往就是最好的
|
||||
- ❌ 复杂不等于好
|
||||
|
||||
---
|
||||
|
||||
## 📈 改进成果
|
||||
|
||||
### **代码减少**
|
||||
|
||||
| 项目 | 删除行数 | 删除文件 |
|
||||
|------|----------|----------|
|
||||
| ConnPool | 102 行 | 1 个文件 |
|
||||
| pool 目录 | - | 1 个空目录 |
|
||||
|
||||
### **架构简化**
|
||||
|
||||
**删除前**:
|
||||
```
|
||||
core/
|
||||
├── pool/
|
||||
│ └── connpool.go # 连接池(未使用)
|
||||
├── connection_manager.go # 连接管理器
|
||||
```
|
||||
|
||||
**删除后**:
|
||||
```
|
||||
core/
|
||||
├── connection_manager.go # 连接管理器(足够用了)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
### **核心改进**
|
||||
- ✅ **删除过度设计** - ConnPool 对于 P2P 场景是多余的
|
||||
- ✅ **回归本质** - 简单的 map 管理就够用了
|
||||
- ✅ **代码简洁** - 减少 102 行无用代码
|
||||
- ✅ **易于维护** - 架构更清晰
|
||||
|
||||
### **经验教训**
|
||||
- ✅ **不要提前优化** - 除非证明需要
|
||||
- ✅ **按需实现** - 根据实际需求写代码
|
||||
- ✅ **保持简单** - 简单往往就是最好的
|
||||
- ✅ **敢于删除** - 没用的代码就删掉
|
||||
|
||||
---
|
||||
|
||||
**删除完成时间**: 2026-03-24
|
||||
**状态**: ✅ **已完成**
|
||||
**评价**: ✅ **正确的决策**
|
||||
|
||||
*ConnPool 删除圆满完成!MeshRay 的架构更加简洁清晰!* 🎉
|
||||
Reference in New Issue
Block a user