19 KiB
19 KiB
MeshRay Service 层架构详解
文档版本: v1.0
更新时间: 2026-03-24
适用范围: internal/service/ 模块
📊 Service 层在整体架构中的位置
┌─────────────────────────────────────────────┐
│ Web UI(Vue 3 + Element Plus) │
└────────────────┬────────────────────────────┘
│ REST API / WebSocket
┌────────────────▼────────────────────────────┐
│ API Handler(Gin 接入层) │
│ - network_handler.go │
│ - device_handler.go │
│ - user_handler.go │
│ - service_handler.go │
└────────────────┬────────────────────────────┘
│ 函数调用
┌────────────────▼────────────────────────────┐
│ Service Layer(业务逻辑层)⭐核心 │
│ - NetworkService ← 组网管理 │
│ - DeviceService ← 设备管理 │
│ - PolicyService ← 策略管理 │
│ - ExternalService ← 外部服务管理 │
│ - UserService ← 用户认证 │
│ - MonitorService ← 监控告警 │
│ - DDNSService ← DDNS 同步 │
│ - AuditService ← 审计日志 │
└──────┬──────────────────────────────────────┘
│
├──────────────────────────────────────┐
│ │
┌──────▼──────┐ ┌────────▼────────┐
│ Store Layer │ │ Ctr Layer │
│ (数据持久化) │ │ (实时控制) │
│ │ │ │
│ - networks │ │ - wgctrl │
│ - devices │ │ - core gRPC │
│ - policies │ │ - 实时调度 │
│ - users │ │ │
│ - services │ │ │
└─────────────┘ └─────────────────┘
关键点:
- ✅ Service 层是业务逻辑的核心
- ✅ Ctr 层只是 Service 层调用的一个执行器
- ✅ 很多 Service 功能完全不依赖 Ctr(如用户登录、策略校验)
🎯 Service 层模块划分
完整的服务模块清单
internal/service/
├── service.go # Service 层总入口和依赖注入
│ type ServiceProvider struct {
│ network *NetworkService
│ device *DeviceService
│ policy *PolicyService
│ external *ExternalService
│ user *UserService
│ monitor *MonitorService
│ ddns *DDNSService
│ audit *AuditService
│ }
│
├── network.go # 组网管理服务
│ ├── ListNetworks() []Network # 获取网络列表
│ ├── CreateNetwork() (*Network, error) # 创建网络
│ ├── DeleteNetwork() error # 删除网络
│ ├── UpdateNetwork() error # 更新网络配置
│ ├── GenerateMeshSeed() (*MeshSeed, error) # 生成 MeshSeed
│ ├── ParseMeshSeed() (*MeshSeed, error) # 解析 MeshSeed
│ └── JoinNetwork() error # 加入网络
│
├── device.go # 设备管理服务
│ ├── ListDevices() []Device # 设备列表
│ ├── AddDevice() (*Device, error) # 添加设备
│ ├── RemoveDevice() error # 删除设备
│ ├── RegenerateKey() error # 重新生成密钥
│ ├── GetDeviceConfig() (*WGConfig, error) # 获取 WG 配置
│ └── ImportDevice() error # 导入现有设备
│
├── policy.go # 策略管理服务
│ ├── ListPolicies() []Policy # 策略列表
│ ├── SetPolicy() error # 设置传输策略
│ ├── GetPolicy() (*Policy, error) # 获取策略
│ ├── ValidatePolicy() error # 验证策略合法性
│ ├── GetEffectivePolicy() (*Policy, error) # 获取生效策略
│ └── ResetPolicy() error # 重置策略
│
├── external_service.go # 外部服务管理服务
│ ├── ListServices() []ExternalService # 服务列表
│ ├── AddService() error # 添加服务
│ ├── UpdateService() error # 更新服务
│ ├── DeleteService() error # 删除服务
│ ├── TestConnectivity() error # 测试连通性
│ ├── GetServiceSchema() (string, error) # 获取 JSON Schema
│ └── ListByCategory() []ExternalService # 按分类筛选
│
├── user.go # 用户认证服务
│ ├── Login() (string, error) # 登录 → JWT Token
│ ├── Register() error # 注册
│ ├── ChangePassword() error # 修改密码
│ ├── VerifyToken() (*Claims, error) # 验证 JWT
│ ├── RefreshToken() (string, error) # 刷新 Token
│ └── GetUserByID() (*User, error) # 根据 ID 获取用户
│
├── monitor.go # 监控告警服务
│ ├── GetSystemStats() (*SystemStats, error) # 系统统计
│ ├── GetNetworkStatus() (*NetworkStatus, error) # 网络状态
│ ├── CheckAlertRules() ([]Alert, error) # 检查告警规则
│ ├── SendAlert() error # 发送告警
│ ├── ListAlertRules() []AlertRule # 告警规则列表
│ └── AddAlertRule() error # 添加告警规则
│
├── ddns.go # DDNS 服务
│ ├── SyncDDNS() error # 同步 DDNS 记录
│ ├── GetDDNSStatus() (*DDNSStatus, error) # 获取状态
│ ├── RefreshDDNS() error # 刷新记录
│ ├── TestDNSProvider() error # 测试 DNS 服务商
│ └── GetDDNSHistory() []DDNSRecord # 历史记录
│
└── audit.go # 审计日志服务
├── LogAction() error # 记录操作日志
├── ListAuditLogs() []AuditLog # 查询日志
├── ExportAuditLogs() ([]byte, error) # 导出日志
├── GetAuditStats() (*AuditStats, error) # 统计数据
└── CleanOldLogs() error # 清理旧日志
📋 每个 Service 的职责详解
1. NetworkService - 组网管理
职责:
- ✅ 组网的创建、删除、更新
- ✅ MeshSeed 的生成和解析
- ✅ 网络配置的持久化
- ✅ 调用 Ctr 执行实际操作
核心方法示例:
// CreateNetwork 创建网络
func (s *NetworkService) CreateNetwork(req CreateNetworkRequest) (*Network, error) {
// ① 业务规则校验
if req.Name == "" {
return nil, errors.New("组网名称不能为空")
}
// 检查名称是否重复
var existing Network
err := s.store.DB().Where("name = ?", req.Name).First(&existing).Error
if err == nil {
return nil, errors.New("组网名称已存在")
}
// ② 数据生成
networkID := snowflake.Generate()
secret := generateSecureSecret() // 32 字节随机
// ③ 保存到数据库
network := &model.Network{
ID: networkID,
Name: req.Name,
Secret: secret,
Subnet: req.Subnet,
STUNServers: []string{"stun.l.google.com:19302"},
CreatedAt: time.Now(),
}
err = s.store.DB().Create(network).Error
if err != nil {
return nil, err
}
// ④ 调用 ctr 执行(事务外,失败需回滚)
err = s.ctrClient.CreateNetwork(networkID, network.ToConfig())
if err != nil {
// 回滚:删除刚创建的 network
s.store.DB().Delete(network)
return nil, fmt.Errorf("调用 ctr 失败:%w", err)
}
return network, nil
}
// GenerateMeshSeed 生成组网凭证
func (s *NetworkService) GenerateMeshSeed(networkID uint64) (*MeshSeed, error) {
// ① 查询网络信息
var network model.Network
err := s.store.DB().First(&network, networkID).Error
if err != nil {
return nil, errors.New("网络不存在")
}
// ② 生成 SeedID(16 字节随机 Base64)
seedID := generateRandomBase64(16)
// ③ Ed25519 签名
signature := ed25519.Sign(privateKey, []byte(network.Secret))
// ④ AES-GCM 加密配置
ciphertext := aesGCM.Encrypt(network.ToJSON())
// ⑤ 构建 MeshSeed
meshSeed := &MeshSeed{
SeedID: seedID,
NetworkID: networkID,
Signature: signature,
Ciphertext: ciphertext,
IssuedAt: time.Now(),
ExpiresAt: time.Now().Add(365 * 24 * time.Hour),
}
// ⑥ 保存到数据库
s.store.DB().Create(&model.MeshSeed{
NetworkID: networkID,
Data: meshSeed.ToJSON(),
})
return meshSeed, nil
// ✅ 完全不需要调用 ctr!
}
2. DeviceService - 设备管理
职责:
- ✅ WireGuard 密钥对生成
- ✅ 设备信息管理
- ✅ WG 配置文件生成
- ✅ 调用 Ctr 添加 Peer
核心方法示例:
// AddDevice 添加设备
func (s *DeviceService) AddDevice(networkID uint64, name string) (*Device, error) {
// ① 查询网络
var network model.Network
err := s.store.DB().First(&network, networkID).Error
if err != nil {
return nil, errors.New("网络不存在")
}
// ② 生成 WG 密钥对
privateKey, publicKey, err := wgtypes.GenerateKey()
if err != nil {
return nil, err
}
// ③ 分配 IP(从子网中自动分配)
ip := allocateIP(network.Subnet)
// ④ 生成设备 ID
deviceID := snowflake.Generate()
// ⑤ 保存到数据库
device := &model.Device{
ID: deviceID,
NetworkID: networkID,
Name: name,
PublicKey: publicKey.String(),
PrivateKey: encryptPrivateKey(privateKey), // 加密存储
IP: ip,
AllowedIPs: []string{ip + "/32"},
}
err = s.store.DB().Create(device).Error
if err != nil {
return nil, err
}
// ⑥ 调用 ctr 添加 Peer(可选,如果立即上线)
if req.ImmediateConnect {
err = s.ctrClient.AddPeer(networkID, device.PublicKey, device.AllowedIPs)
if err != nil {
s.store.DB().Delete(device)
return nil, fmt.Errorf("调用 ctr 失败:%w", err)
}
}
return device, nil
}
// GetDeviceConfig 获取设备配置(生成 WG 配置文件)
func (s *DeviceService) GetDeviceConfig(deviceID uint64) (string, error) {
// ① 查询设备信息
var device model.Device
err := s.store.DB().Preload("Network").First(&device, deviceID).Error
if err != nil {
return "", errors.New("设备不存在")
}
// ② 解密私钥
privateKey := decryptPrivateKey(device.PrivateKey)
// ③ 生成 WG 配置
config := fmt.Sprintf(`[Interface]
PrivateKey = %s
Address = %s
ListenPort = 51820
[Peer]
PublicKey = %s
AllowedIPs = %s
Endpoint = %s:51820
`, privateKey, device.IP, device.Network.PublicKey, device.AllowedIPs, device.Network.Endpoint)
return config, nil
// ✅ 纯业务逻辑,不需要调用 ctr!
}
3. UserService - 用户认证(完全不依赖 Ctr)
职责:
- ✅ 用户注册、登录
- ✅ JWT Token 生成和验证
- ✅ 密码加密存储
- ✅ 审计日志记录
核心方法示例:
// Login 用户登录
func (s *UserService) Login(username, password string) (string, error) {
// ① 查询用户
var user model.User
err := s.store.DB().Where("username = ?", username).First(&user).Error
if err != nil {
return "", errors.New("用户名或密码错误")
}
// ② 验证密码(bcrypt)
err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password))
if err != nil {
return "", errors.New("用户名或密码错误")
}
// ③ 生成 JWT Token
claims := jwt.Claims{
UserID: user.ID,
Username: user.Username,
Role: user.Role,
}
token := jwt.GenerateToken(claims, jwtSecret, 24*time.Hour)
// ④ 记录登录日志
s.auditService.LogAction(user.ID, "login", "用户登录成功")
return token, nil
// ✅ 完全不需要调用 ctr!
}
// Register 用户注册
func (s *UserService) Register(username, password, email string) error {
// ① 检查用户名是否已存在
var existing model.User
err := s.store.DB().Where("username = ?", username).First(&existing).Error
if err == nil {
return errors.New("用户名已存在")
}
// ② 密码加密(bcrypt)
hash, err := bcrypt.GenerateFromPassword([]byte(password), 12)
if err != nil {
return err
}
// ③ 创建用户
user := &model.User{
Username: username,
Email: email,
PasswordHash: string(hash),
Role: "user",
}
err = s.store.DB().Create(user).Error
if err != nil {
return err
}
// ④ 记录注册日志
s.auditService.LogAction(user.ID, "register", "用户注册成功")
return nil
// ✅ 完全不需要调用 ctr!
}
4. PolicyService - 策略管理(部分依赖 Ctr)
职责:
- ✅ 9 层传输策略配置
- ✅ 策略合法性校验
- ✅ 策略持久化
- ✅ 调用 Ctr 应用策略
核心方法示例:
// SetPolicy 设置传输策略
func (s *PolicyService) SetPolicy(networkID uint64, policy PolicyConfig) error {
// ① 业务规则校验
if err := s.validatePolicy(policy); err != nil {
return fmt.Errorf("策略配置不合法:%w", err)
}
// ② 保存到数据库
policyModel := &model.Policy{
NetworkID: networkID,
Config: policy.ToJSON(),
UpdatedAt: time.Now(),
}
err := s.store.DB().Save(policyModel).Error
if err != nil {
return err
}
// ③ 调用 ctr 应用策略(可选,如果网络正在运行)
if network.IsActive {
err = s.ctrClient.UpdatePolicy(networkID, policy)
if err != nil {
return fmt.Errorf("应用策略失败:%w", err)
}
}
return nil
}
// validatePolicy 验证策略合法性(纯业务逻辑)
func (s *PolicyService) validatePolicy(policy PolicyConfig) error {
// 检查至少启用了一层
if !policy.AnyLayerEnabled() {
return errors.New("至少需要启用一层传输")
}
// 检查优先级顺序
if !policy.IsValidOrder() {
return errors.New("传输层优先级顺序不合法")
}
// 检查 STUN/TURN 服务器配置
if policy.EnableDirectUDP && len(policy.STUNServers) == 0 {
return errors.New("启用 Direct-UDP 需要配置 STUN 服务器")
}
if policy.EnableTURN && len(policy.TURNServers) == 0 {
return errors.New("启用 TURN 需要配置 TURN 服务器")
}
return nil
// ✅ 纯业务逻辑校验,不需要调用 ctr!
}
🔄 Service 层的通用模式
标准操作流程
func (s *XXXService) DoSomething(params Params) (Result, error) {
// ① 业务规则校验
if err := s.validate(params); err != nil {
return nil, err
}
// ② 数据生成/转换
data := generateData(params)
// ③ 保存到数据库
err := s.store.DB().Create(&data).Error
if err != nil {
return nil, err
}
// ④ 调用 ctr 执行(可选,放在事务外)
err = s.ctrClient.DoSomething(data.ID, data.Config)
if err != nil {
// 回滚:删除刚创建的数据
s.store.DB().Delete(&data)
return nil, fmt.Errorf("调用 ctr 失败:%w", err)
}
return data, nil
}
不调用 Ctr 的场景
以下场景完全不需要调用 Ctr:
- ✅ 用户认证:Login/Register/VerifyToken
- ✅ 数据查询:ListXXX/GetXXX
- ✅ 配置生成:GenerateMeshSeed/GetDeviceConfig
- ✅ 策略校验:ValidatePolicy
- ✅ 日志审计:LogAction/ListAuditLogs
- ✅ 统计分析:GetAuditStats/GetSystemStats
📊 Service 与 Ctr 的职责对比
| 维度 | Service 层 | Ctr 层 |
|---|---|---|
| 定位 | 业务逻辑核心 | 实时控制执行器 |
| 职责 | 业务规则、数据生成、持久化 | 执行 WG/Core 操作 |
| 依赖数据库 | ✅ 是(直接操作) | ❌ 否(通过参数接收) |
| 依赖 Ctr | ⚠️ 部分依赖 | ❌ 不依赖 Service |
| 主动性 | ✅ 主动发起调用 | ❌ 被动执行 |
| 可测试性 | ✅ 可 Mock Ctr | ✅ 可独立测试 |
| 示例方法 | CreateNetwork Login GenerateMeshSeed |
CreateDevice AddPeer CreateEngine |
✅ 总结
Service 层的核心价值
-
✅ 业务逻辑的承载者
- 处理所有业务规则
- 生成和转换数据
- 持久化到数据库
-
✅ Ctr 层的调用者
- 决定何时调用 Ctr
- 传递必要的参数
- 处理 Ctr 的返回结果
-
✅ 前后端的桥梁
- 接收 API Handler 的请求
- 返回处理结果给 Handler
- 对外暴露完整的业务能力
设计原则
- ✅ Service 层是核心:所有业务逻辑都在这里
- ✅ Ctr 层是工具:只在需要实时控制时调用
- ✅ 保持解耦:Service 层可以独立于 Ctr 测试
- ✅ 事务一致性:Ctr 失败时需要回滚数据库
文档版本:v1.0
最后更新:2026-03-24
维护者:MeshRay Team