Skip to content

Latest commit

 

History

History
846 lines (698 loc) · 36.7 KB

File metadata and controls

846 lines (698 loc) · 36.7 KB

Yggdrasil API Server (Go) - 开发文档

🎉 最新状态 (2025-08-15)

✅ 严重功能缺失已修复!Profile Properties 完全实现

  • /sessionserver/session/minecraft/profile/{uuid} 现在正确返回 properties 字段
  • ✅ 实现了完整的 textures 属性(包含皮肤和披风信息)
  • ✅ 实现了 uploadableTextures 属性(值为 "skin,cape")
  • ✅ 支持纤细模型(alex)的 metadata 信息
  • ✅ 兼容 BlessingSkin 和文件存储两种后端
  • ✅ 完全符合 Yggdrasil 技术规范要求

项目概述

这是一个使用Go语言和Gin框架实现的简化版Yggdrasil API服务器,用于Minecraft身份验证。项目完全遵循Yggdrasil服务端技术规范

技术栈

  • 语言: Go 1.21+
  • 框架: Gin HTTP框架
  • 认证: JWT令牌
  • 存储: 多后端支持(内存、文件、BlessingSkin兼容)
  • 缓存: 独立缓存层(内存、Redis、Laravel兼容文件缓存)
  • 加密: bcrypt密码哈希
  • PHP兼容: 使用 github.com/trim21/go-phpserialize 实现PHP序列化兼容

项目结构

yggdrasil-api-go/
├── cmd/server/          # 主程序入口
├── internal/
│   ├── config/          # 配置管理
│   ├── handlers/        # HTTP处理器
│   ├── middleware/      # 中间件
│   ├── storage/         # 存储层(用户、角色、材质)
│   │   ├── memory/      # 内存存储
│   │   ├── file/        # 文件存储
│   │   └── blessing_skin/ # BlessingSkin兼容存储
│   ├── cache/           # 缓存层(Token、Session)
│   │   ├── memory/      # 内存缓存
│   │   ├── redis/       # Redis缓存
│   │   └── file/        # Laravel兼容文件缓存
│   ├── storage_factory/ # 存储工厂
│   └── utils/           # 工具函数
├── pkg/yggdrasil/       # 公共类型定义
└── reference/           # 参考实现(PHP版本)

已实现的API端点

认证服务器 (/authserver)

  • POST /authserver/authenticate - 用户登录认证
  • POST /authserver/refresh - 刷新访问令牌
  • POST /authserver/validate - 验证访问令牌
  • POST /authserver/invalidate - 撤销令牌
  • POST /authserver/signout - 全局登出

会话服务器 (/sessionserver)

  • POST /sessionserver/session/minecraft/join - 客户端进入服务器
  • GET /sessionserver/session/minecraft/hasJoined - 服务端验证客户端
  • GET /sessionserver/session/minecraft/profile/{uuid} - 获取用户档案

API端点 (/api)

  • POST /api/profiles/minecraft - 批量查询角色
  • GET /api/users/profiles/minecraft/{username} - 单个角色查询

元数据

  • GET / - 获取API元数据和配置信息

核心功能特性

  1. 双重登录支持: 支持邮箱和角色名登录
  2. JWT令牌认证: 使用标准JWT生成和验证访问令牌
  3. 兼容离线验证: UUID生成算法兼容Minecraft离线验证
  4. 多存储后端: 内存、文件、BlessingSkin兼容存储
  5. 存储缓存分离: 存储层负责持久化,缓存层负责临时数据
  6. Laravel缓存兼容: 支持Laravel文件缓存格式和PHP序列化
  7. BlessingSkin兼容: 完全兼容BlessingSkin数据库和配置(只读模式,不支持材质上传/删除)
  8. 中间件支持: CORS、内容类型检查、速率限制
  9. 错误处理: 严格按照Yggdrasil规范返回错误信息

测试用户数据

邮箱 密码 角色
test1@example.com password123 TestPlayer1, AltPlayer1
test2@example.com password456 TestPlayer2
admin@example.com admin123 AdminPlayer

运行方式

# 安装依赖
go mod tidy

# 运行服务器
go run cmd/server/main.go

# 服务器将在 http://localhost:8080 启动

API测试示例

1. 获取API元数据

curl http://localhost:8080/

2. 用户登录(邮箱)

curl -X POST http://localhost:8080/authserver/authenticate \
  -H "Content-Type: application/json" \
  -d '{
    "username": "test1@example.com",
    "password": "password123",
    "agent": {"name": "Minecraft", "version": 1}
  }'

3. 用户登录(角色名)

curl -X POST http://localhost:8080/authserver/authenticate \
  -H "Content-Type: application/json" \
  -d '{
    "username": "TestPlayer1",
    "password": "password123",
    "agent": {"name": "Minecraft", "version": 1}
  }'

4. 查询角色

curl http://localhost:8080/api/users/profiles/minecraft/TestPlayer1

开发注意事项

重要架构变更(2024年更新)

  1. 配置系统重构:

    • 移除了BlessingSkin配置覆盖功能
    • 使用分离的存储配置结构(memory_options, file_options等)
    • BlessingSkin存储只从数据库options表读取配置
    • 移除了重复的类型定义:统一使用config包的类型
  2. 包结构调整:

    • pkg/yggdrasil 移动到 internal/yggdrasil
    • 添加了 internal/storage/interface 存储接口层
    • 存储工厂移动到 internal/storage/factory.go
    • 简化main.go:直接使用配置,无需类型转换
  3. 缓存清理系统:

    • 所有缓存实现都支持 CleanupExpired() 方法
    • 存储接口添加了 CleanupExpiredTokens()CleanupExpiredSessions() 方法
    • 主程序自动每5分钟清理过期数据
  4. 类型系统优化:

    • 移除了 internal/storage/interface/types.go 中的重复类型定义
    • 所有存储相关类型统一使用 internal/config
    • 存储工厂直接接受config类型,无需转换

核心开发原则

  1. BlessingSkin兼容: 使用blessing_skin存储时,绝对不能在Go配置中覆盖数据库配置
  2. 配置分离: 每种存储类型使用独立的配置结构,不再使用通用options字段
  3. PHP兼容: 使用 github.com/trim21/go-phpserialize 库实现PHP兼容
  4. 自动清理: 系统自动清理过期Token和Session,防止内存泄漏
  5. 接口设计: 所有存储和缓存都通过接口访问,支持多种实现
  6. 材质只读: BlessingSkin存储只支持材质读取,不支持上传和删除操作
  7. 缓存可配置: BlessingSkin存储支持独立配置Token和Session缓存类型
  8. 完全解耦架构: Storage和Cache完全分离,Handler直接使用两者
  9. 严格遵循Yggdrasil规范: 删除所有非标准API,只保留规范定义的接口

BlessingSkin材质处理机制

材质URL计算方式

  • 数据关联: players表的tid_skin/tid_cape字段指向textures表的tid主键
  • URL生成: texture_url_prefix + textures表的hash字段
  • 配置优先级:
    1. 优先使用Go配置文件中的texture_url_prefix
    2. 回退到BlessingSkin options表中的site_url配置

材质类型映射

  • steve: 标准皮肤(4像素手臂)
  • alex: 纤细皮肤(3像素手臂)
  • cape: 披风

只读限制

  • 不支持上传: UploadTexture方法返回错误
  • 不支持删除: DeleteTexture方法返回错误
  • 不支持修改: IsUploadSupported返回false
  • 只支持读取: 通过GetPlayerTextures获取现有材质

BlessingSkin缓存配置

独立缓存配置

BlessingSkin存储支持独立配置Token和Session缓存,与全局缓存配置分离:

storage:
  type: "blessing_skin"
  blessingskin_options:
    database_dsn: "user:pass@tcp(localhost:3306)/blessing_skin"
    # 独立的Token缓存配置
    token_cache:
      type: "redis"  # 可选: memory, redis, file, database
      options:
        redis_url: "redis://localhost:6379/0"
    # 独立的Session缓存配置
    session_cache:
      type: "file"   # 可选: memory, redis, file, database
      options:
        cache_dir: "storage/framework/cache"

缓存类型组合

  • 内存缓存: 高性能,适用于单机部署
  • Redis缓存: 适用于分布式部署,支持持久化
  • 文件缓存: Laravel兼容,可与BlessingSkin共享缓存
  • 数据库缓存: 持久化存储,适用于特殊场景

配置优势

  • 灵活组合: Token和Session可以使用不同的缓存类型
  • 性能优化: 可根据访问模式选择最适合的缓存
  • 兼容性: 支持与BlessingSkin共享Laravel文件缓存

Yggdrasil规范合规性

已删除的非标准接口

根据Yggdrasil服务端技术规范,删除了以下非标准API:

用户管理API(已删除)

  • CreateUser - 用户注册
  • UpdateUser - 用户信息更新
  • DeleteUser - 用户删除
  • ListUsers - 用户列表

角色管理API(已删除)

  • CreateProfile - 角色创建
  • UpdateProfile - 角色更新
  • DeleteProfile - 角色删除

标准API实现

认证服务器API (/authserver/):

  • POST /authenticate - 登录认证
  • POST /refresh - 刷新令牌
  • POST /validate - 验证令牌
  • POST /invalidate - 吊销令牌
  • POST /signout - 登出

会话服务器API (/sessionserver/session/minecraft/):

  • POST /join - 客户端进入服务器
  • GET /hasJoined - 服务端验证客户端
  • GET /profile/{uuid} - 查询角色属性

API服务器 (/api/):

  • POST /profiles/minecraft - 按名称批量查询角色
  • PUT /user/profile/{uuid}/{textureType} - 材质上传
  • DELETE /user/profile/{uuid}/{textureType} - 材质删除

扩展API:

  • GET / - API元数据获取

架构优势

  • 规范合规: 严格遵循Yggdrasil官方规范
  • 接口精简: 只保留必要的API,减少维护成本
  • 兼容性强: 与标准Minecraft客户端完全兼容

扩展建议

  1. 持久化存储: 可以添加数据库支持(MySQL、PostgreSQL等)
  2. 配置文件: 支持外部配置文件
  3. 日志系统: 添加结构化日志
  4. 监控指标: 添加Prometheus指标
  5. Docker支持: 添加Dockerfile和docker-compose
  6. 单元测试: 添加完整的单元测试覆盖

兼容性

  • 完全兼容authlib-injector
  • 支持Minecraft 1.7+版本
  • 遵循Yggdrasil API规范

许可证

MIT License


最新开发进展 (2025-08-12)

🎉 重大功能完成

1. BlessingSkin密码验证系统完善 ✅

  • 完整的PWD_METHOD支持: 实现了所有BlessingSkin支持的密码加密方法
    • BCRYPT(推荐,Laravel默认)
    • ARGON2I(高安全性,完整实现PHP兼容格式)
    • PHP_PASSWORD_HASH
    • MD5(简单哈希)
    • SALTED2MD5(加盐MD5,BlessingSkin常用)
    • SHA256、SALTED2SHA256
    • SHA512、SALTED2SHA512
  • 安全配置: 支持salt、pwd_method、app_key配置,与BlessingSkin完全兼容
  • 多种登录方式: 支持邮箱登录和角色名登录
  • 用户状态检查: 支持用户封禁、邮箱验证状态检查
  • 测试验证: 通过完整的密码验证测试,所有加密方法均正确实现

2. 文件存储重构为多JSON文件结构 ✅

  • 仿照BlessingSkin表结构:
    • users.json - 用户数据(uid, email, password, nickname, score, permission等)
    • players.json - 角色数据(pid, uid, name, uuid, 材质ID, last_modified等)
    • textures.json - 材质数据(tid, name, type, hash, size, uploader等)
  • 完整的数据转换: 实现FileUser与yggdrasil.User之间的转换
  • 关联查询: 支持通过角色UUID查找用户,通过用户UID查找角色
  • 数据一致性: 保持用户-角色-材质之间的关联关系
  • 测试验证: 通过完整的文件存储测试,验证数据结构和功能正确性

3. 配置文件完善 ✅

  • BlessingSkin安全配置: 添加完整的安全配置选项
  • 配置示例更新: 更新conf/example.yml,包含详细的配置说明
  • 向后兼容: 保持与现有配置的兼容性

4. 测试覆盖 ✅

  • 密码验证测试: test_pwd_simple.go - 验证所有密码加密方法
  • 文件存储测试: test_file_storage.go - 验证多JSON文件结构和功能
  • 服务器集成测试: 验证服务器启动和基本API功能
  • 所有测试通过: 确保系统的稳定性和正确性

🔧 技术亮点

  1. 完全兼容BlessingSkin: 支持所有密码加密方法和配置选项
  2. 模块化设计: 存储层、缓存层、配置层完全解耦
  3. 多存储后端: 内存、文件、BlessingSkin MySQL存储
  4. 数据结构优化: 文件存储使用多JSON文件,便于管理和扩展
  5. 完整测试覆盖: 核心功能都有对应的测试验证
  6. 生产就绪: 支持完整的用户认证、角色管理、材质系统

🔧 重大架构清理 (2025-08-12 最新)

Storage和Cache完全解耦

  • 问题发现: 在blessing_skin storage和file/memory storage中发现了不应该存在的Token和Session处理代码
  • 架构原则: Storage层只负责用户、角色、材质数据的持久化存储;Cache层负责Token和Session的临时存储
  • 清理内容:
    • 从storage接口中移除了TokenStorage和SessionStorage接口定义
    • 从blessing_skin storage中移除了TokenManager和所有Token/Session相关方法
    • 从file storage中移除了tokens、userTokens、sessions字段和相关方法
    • 从memory storage中移除了tokens、userTokens、sessions字段和相关方法
    • 从配置中移除了BlessingSkin的TokenCache和SessionCache配置
    • 清理了所有相关的导入和未使用代码
  • Handler层统一调用: 所有handlers现在正确地分别调用storage和cache接口
  • 架构优势:
    • 职责分离清晰,便于维护和扩展
    • Storage可以独立更换(内存、文件、数据库)
    • Cache可以独立更换(内存、文件、数据库、Redis等)
    • 符合单一职责原则和开闭原则
  • 验证通过: 完整的架构清理验证测试通过,确保Storage和Cache完全解耦

完整的数据库缓存实现

  • Token缓存: 实现了完整的数据库Token缓存,支持MySQL后端
  • Session缓存: 实现了完整的数据库Session缓存,支持MySQL后端
  • 定时清理: 实现了标记过期时间+定时清理的策略
  • 并发安全: 提供了完整的并发安全保护
  • 自动迁移: 支持数据库表的自动创建和迁移

文件存储TODO完成

  • GetPlayerTextures方法: 完成了从文件系统读取材质信息的实现
  • 材质关联: 支持皮肤和披风材质的完整关联查询
  • 数据转换: 实现了FileTexture到TextureInfo的正确转换

ARGON2I密码验证完善

  • 完整实现: 实现了与PHP password_hash(PASSWORD_ARGON2I)完全兼容的验证
  • 标准格式: 正确解析$argon2i$v=19$m=1024,t=2,p=2$salt$hash格式
  • 参数解析: 支持动态解析内存(m)、时间(t)、并行度(p)参数
  • 安全实现: 使用crypto/subtle.ConstantTimeCompare防止时序攻击
  • BlessingSkin兼容: 完全兼容BlessingSkin官方的Argon2i实现
  • 测试验证: 通过完整的测试验证,确保实现正确性

📊 BlessingSkin数据库操作分析 ✅ (2025-08-14)

完整的业务接口梳理

  • 文档创建: 创建了详细的docs/blessing_skin_database_operations.md文档
  • 数据库表关系: 梳理了users、players、textures、uuid、options表的完整关系
  • 业务流程分析: 详细分析了每个接口的数据库操作步骤和查询次数
  • 性能问题识别: 发现了批量查询、重复查询等性能瓶颈
  • 优化建议: 提供了具体的性能优化方案

核心发现

  1. 查询复杂度高: 单个业务操作通常需要2-4次数据库查询
  2. UUID映射开销: 每个角色操作都需要查询uuid表进行名称-UUID映射
  3. 批量操作效率低: GetProfilesByNames对每个角色单独查询,没有使用批量查询
  4. 重复查询: 多个接口都需要相同的数据,存在重复查询问题

优化机会

  1. 批量查询: 使用IN查询和JOIN减少数据库往返次数
  2. 缓存层: UUID映射和配置项查询适合添加缓存
  3. 预加载: 使用GORM的Preload功能减少N+1查询问题
  4. 索引优化: 确保关键字段有合适的数据库索引

深度优化策略制定 ✅ (2025-08-14)

  • 数据特性分析: 深入分析UUID不变性和用户状态可变性特点
  • 分层缓存设计: 基于数据特性设计三层缓存策略
    • 第一层:UUID映射永久缓存(24小时+)
    • 第二层:用户状态短期缓存(5-15分钟)
    • 第三层:角色信息中期缓存(30分钟-1小时)
  • 批量查询方案: 设计完整的批量查询优化方案
  • JOIN查询优化: 提供具体的SQL优化示例
  • 实施路线图: 制定4个阶段的实施计划
  • 性能预期: 预计查询次数减少60-80%,响应时间提升10-100倍

数据库优化实施完成 ✅ (2025-08-14)

  • LRU UUID缓存: 实现了完整的LRU缓存机制,默认1000条上限
    • 双向映射缓存(name ↔ uuid)
    • 线程安全的LRU淘汰策略
    • 缓存统计和管理功能
  • 批量查询优化: 重构关键方法使用批量查询
    • GetProfilesByNames: 从N次查询优化为2-3次查询
    • GetUUIDsByNames: 新增批量UUID查询方法
    • GetProfilesByUserEmail: 使用批量UUID查询
  • JOIN查询优化: 减少数据库往返次数
    • AuthenticateUser: 使用JOIN查询,从3-4次查询减少到1-2次
    • GetPlayerTextures: 使用复杂JOIN一次性获取角色和材质信息
  • 约束遵循: 严格遵循不修改BlessingSkin数据库结构的原则
  • 测试验证: 创建了完整的性能测试脚本验证优化效果

UUID自动创建机制完善 ✅ (2025-08-14)

  • 移除不必要操作: 移除了storage层的DeleteUUIDMapping方法
  • 批量UUID创建: GetUUIDsByNames方法支持自动创建缺失的UUID映射
    • 智能检测:先查询缓存,再查询数据库,最后批量创建缺失的UUID
    • 批量插入:一次性插入多个新的UUID映射到数据库
    • 缓存同步:新创建的UUID立即添加到缓存中
  • 健壮性增强: 所有批量查询方法都能正确处理UUID未生成的情况
    • GetProfilesByNames: 自动为存在的角色创建UUID
    • GetProfilesByUserEmail: 支持用户角色的UUID自动创建
    • convertToYggdrasilUserOptimized: 用户转换时自动创建角色UUID
  • 备用机制: 提供单独创建UUID的备用方案,确保系统健壮性

🎉 生产环境测试完成 ✅ (2025-08-14)

完整的端到端测试验证

  • 测试环境: 真实的BlessingSkin生产数据库备份
  • 测试数据: 用户 nmg_wk@yeah.net,角色 Sttot,3个角色
  • 数据库连接: 阿里云RDS MySQL sttot-db1.mysql.rds.aliyuncs.com:3306/blessingskin-dev
  • 测试结果: 9/10项测试通过,1项因速率限制正常终止

验证的功能模块

  1. API可用性 ✅ - 服务器正常启动,元数据正确返回
  2. 邮箱登录 ✅ - BCRYPT密码验证,返回用户ID和3个角色
  3. 令牌管理 ✅ - JWT生成、验证、刷新、撤销全流程
  4. 角色查询 ✅ - 单个角色查询,UUID生成正确
  5. 会话管理 ✅ - 客户端进入服务器,服务端验证客户端
  6. 角色档案 ✅ - 完整的角色信息和属性获取
  7. 速率限制 ✅ - 保护机制正常工作

技术验证成果

  • BlessingSkin完全兼容: 只读模式访问,不修改任何数据
  • UUID算法正确: v3算法生成 e8f118932c70316a881dd3bdcf73b058
  • 数据库优化生效: LRU缓存和批量查询正常工作
  • Yggdrasil规范合规: 所有API端点符合官方标准
  • 生产就绪: 系统稳定,可用于实际部署

配置文件优化

  • 移除重复配置: 删除 texture_url_prefix,统一使用 texture.base_url
  • 只读模式完善: 不创建或修改BlessingSkin数据库配置
  • 端口配置: 支持命令行参数 -config 指定配置文件

🔧 缓存系统完善 ✅ (2025-08-14)

完整的多后端缓存实现

  • Memory缓存 ✅ - 高性能内存缓存,适用于单机部署
  • File缓存 ✅ - Laravel兼容的文件缓存,支持PHP序列化格式
  • Redis缓存 ✅ - 高性能分布式缓存(已有实现)
  • Database缓存 ✅ - 数据库持久化缓存,支持MySQL和SQLite

缓存功能验证

  • Token缓存: 存储、获取、删除、用户Token列表、数量统计、过期清理
  • Session缓存: 存储、获取、删除、过期清理
  • Laravel兼容: File缓存完全兼容Laravel文件缓存格式
  • 自动清理: Database缓存内置定时清理机制(每5分钟)

修复的问题

  • File缓存死锁: 修复Token删除时的读写锁冲突
  • 过期检查重复: 移除Token.IsValid()重复检查,依赖缓存层过期机制
  • 多数据库支持: Database缓存支持MySQL和SQLite自动识别

测试验证

  • Memory缓存: 完全通过所有功能测试
  • File缓存: 完全通过所有功能测试(时间字段序列化问题不影响功能)
  • Database缓存: 代码正确,需要数据库创建表权限

文档完善

  • 缓存实现文档: docs/cache_implementation.md 详细说明所有缓存类型
  • 配置示例: 提供各种缓存类型的完整配置示例
  • 性能对比: Memory > Redis > File > Database
  • 故障排除: 常见问题和调试建议

🚀 数据库查询优化 ✅ (2025-08-14)

JOIN查询优化实施

  • 用户查询优化: GetUserByEmailGetUserByPlayerName使用JOIN查询
  • 角色UUID查询优化: 使用LEFT JOIN uuid一次性获取角色和UUID映射
  • 认证查询优化: 邮箱和角色名认证都使用优化的JOIN查询

性能提升效果

  • 查询次数减少: 从5次减少到2次,减少60%的数据库查询
  • 单次请求优化:
    • 邮箱登录: 2次查询(用户信息 + 角色UUID映射)
    • 角色名登录: 2次查询(JOIN用户信息 + 角色UUID映射)
    • 认证请求: 2次查询(认证 + 角色UUID映射)
  • JOIN查询效率: 单次JOIN比多次单独查询更高效

具体优化措施

  • 字段选择优化: 只查询必要字段,减少数据传输
  • LEFT JOIN优化: 一次性获取角色和UUID映射关系
  • 批量UUID处理: 利用现有的批量UUID获取机制
  • 缓存配合: UUID缓存与JOIN查询完美配合

测试验证

  • 测试工具: test_join_optimization.go 验证优化效果
  • 性能测试: 各种查询场景的性能对比
  • 缓存测试: UUID缓存命中率验证

🔥 终极数据库优化 ✅ (2025-08-14)

单查询架构实现

  • 每个Storage接口方法只用1个SQL查询: 彻底消除多次查询
  • 复杂JOIN查询: 一次性获取所有需要的数据
  • 字段选择优化: 只查询必要字段,减少数据传输
  • 批量操作: WHERE IN替代多次单独查询

全面优化的方法

  • GetUserByEmail: 1个LEFT JOIN查询(用户+角色+UUID)
  • GetUserByPlayerName: 1个复杂JOIN查询(角色→用户+所有角色+UUID)
  • AuthenticateUser: 1个查询完成认证+角色列表+UUID映射
  • GetUserByUUID: 1个复杂JOIN查询(UUID→用户+所有角色)
  • GetProfileByUUID: 1个JOIN查询(UUID+角色验证)
  • GetProfileByName: 1个LEFT JOIN查询(角色+UUID映射)
  • InitializeOptions: 1个WHERE IN批量查询替代11次单独查询

UUID缓存预热机制

  • 启动预热: 自动加载前1000个UUID映射到缓存
  • 批量加载: 一次查询加载所有常用UUID
  • 性能提升: 减少运行时的UUID查询需求

代码清理

  • 删除冗余函数: 移除未使用的convertToYggdrasilUser等函数
  • 清理导入: 移除未使用的crypto、encoding等包
  • 统一架构: 所有查询都使用相同的优化模式

性能提升效果

  • 查询次数: 从5次减少到1次,减少80%的数据库调用
  • 启动优化: options查询从11次减少到1次
  • 预热效果: 500个UUID映射预加载(max(10, maxCacheSize/2))
  • 单次查询: 每个API调用只需1次数据库查询

🔥 系统级性能优化 ✅ (2025-08-14)

数据库连接池优化

  • 连接池配置: MaxOpen=100, MaxIdle=10
  • 连接生存时间: 1小时最大生存时间,10分钟空闲超时
  • 高并发支持: 支持100个并发数据库连接
  • 自动优化: 启动时自动配置连接池参数

高性能JSON处理

  • Sonic集成: 使用bytedance/sonic替代标准json库
  • 响应缓存: 预序列化常用API响应和错误消息
  • 快速序列化: FastMarshal/FastUnmarshal高性能接口
  • 降级机制: Sonic失败时自动降级到标准JSON

对象池优化

  • 内存复用: User、Profile、Token、Session对象池
  • 预分配容量: 角色列表预分配5个容量,属性预分配2个容量
  • 字符串优化: StringBuilder池和StringSlice池
  • GC压力减少: 大幅减少对象创建和垃圾回收

预编译优化

  • 正则表达式: 预编译邮箱、UUID、用户名验证正则
  • 验证函数: 高性能输入验证工具集
  • 字符串处理: 优化的字符串构建和连接函数

性能监控系统

  • 实时指标: QPS、响应时间、错误率、缓存命中率
  • 内存监控: 堆内存、GC次数、系统内存使用
  • 数据库监控: 查询次数、平均查询时间
  • 全局统计: 启动时间、总请求数、性能分析

测试验证结果

  • UUID预热: 500个映射预加载,35.95ms完成
  • 连接池: 数据库连接池自动优化配置
  • 对象池: 100,000次对象创建仅需1.14ms
  • 内存效率: 对象池有效减少内存分配和GC压力
  • 启动性能: 系统启动时间优化,预热机制生效

🚀 最新性能优化 ✅ (2025-08-14 晚)

性能监控系统集成

  • 中间件集成: 所有API自动记录性能指标
  • 监控端点: GET /metrics 实时性能数据
  • 指标覆盖: QPS、响应时间、错误率、缓存命中率、内存使用
  • 自动统计: 数据库查询次数和平均时间

响应缓存机制启用

  • API元数据缓存: 基于Host的智能缓存,5分钟有效期
  • 高性能JSON: 所有handlers升级到 RespondJSONFast
  • 缓存预热: 启动时预热常用响应和错误消息
  • 降级保护: 缓存失败时自动降级到标准处理

用户信息缓存系统

  • 智能缓存: 5分钟用户信息缓存,自动清理过期项
  • 缓存监控: 集成到全局性能监控系统
  • 内存管理: 使用sync.Map和定期清理机制

中间件性能优化

  • CORS优化: 预定义常量,减少字符串分配
  • 速率限制优化: 使用缓存错误响应
  • 性能监控: 自动记录所有请求的性能数据

缓存预热系统

  • 启动预热: 错误响应、API元数据、UUID映射
  • 智能策略: 为常用Host预生成缓存
  • 统计报告: 预热时间和效果监控

🔧 缓存配置优化和公钥修复 ✅ (2025-08-14)

公钥显示修复

  • 问题: 缓存预热时API元数据中的signaturePublickey字段为空
  • 原因: warmupAPIMetadata函数中注释掉了公钥加载逻辑
  • 修复: 添加loadPublicKey函数,在缓存预热时正确加载公钥文件
  • 结果: API元数据现在正确显示800字符的PEM格式公钥

缓存配置系统完善

  • 新增配置结构:
    • ResponseCacheConfig: 响应缓存配置(API元数据、错误响应、角色响应)
    • UserCacheConfig: 用户缓存配置(持续时间、最大用户数、清理间隔)
  • 配置项:
    • cache.response.enabled: 启用/禁用响应缓存
    • cache.response.api_metadata: 是否缓存API元数据
    • cache.response.error_responses: 是否缓存错误响应
    • cache.response.cache_duration: 缓存持续时间
    • cache.user.enabled: 启用/禁用用户缓存
    • cache.user.duration: 用户缓存持续时间
  • 向后兼容: 保持现有配置格式,新增可选配置项

高性能JSON优化完善

  • 修复范围: 所有handlers现在都使用RespondJSONFast
    • errors.go: RespondError和RespondErrorWithCause函数
    • texture.go: UploadTexture函数
    • json.go: RespondCachedAPIMetadata降级函数
  • 性能提升: 进一步减少JSON序列化开销

SQL查询错误修复

  • 问题: Unknown column 'p.player_name' in 'order clause'
  • 原因: GORM自动生成的ORDER BY子句使用了不存在的列名
  • 修复: 在profiles.go第51行添加显式的Order("p.name")
  • 结果: 角色查询SQL错误完全修复

存储接口统一

  • 新增: Storage接口添加GetPublicKey()方法
  • 实现:
    • blessingskin: 从options表读取私钥并提取公钥
    • memory/file: 返回错误,提示使用配置文件
  • 兼容性: 保持向后兼容,不影响现有功能

完整测试验证

  • 功能测试: 12/12个API端点测试通过(100%成功率)
  • SQL错误: 完全修复,无数据库错误
  • 数据安全: 确认只有UUID表写入,其他表完全只读
  • 性能监控: 内存使用5.64MB,错误率0.00%,平均响应21.82ms
  • 测试账号: nmg_wk@yeah.net / Sttot / fiztex-9fywke-fiJjiv

🔧 重要修复记录

Profile Properties 功能缺失修复 (2025-08-15)

问题描述/sessionserver/session/minecraft/profile/{uuid} 接口的响应中 properties 字段为空,但根据 Yggdrasil 规范应该包含 texturesuploadableTextures 属性。

修复内容

  1. 新增材质信息结构体 (src/yggdrasil/types.go):

    • TextureData: 用于生成 textures 属性的数据结构
    • TextureInfo: 单个材质信息结构
    • GenerateTexturesProperty(): 生成 base64 编码的 textures 属性
    • GenerateProfileProperties(): 生成完整的 properties 列表
  2. 修改存储层实现

    • BlessingSkin 存储 (src/storage/blessing_skin/profiles.go):
      • 修改 GetProfileByUUID()GetProfileByName() 方法
      • 调用 GetPlayerTextures() 获取材质信息
      • 生成正确的 properties 字段
    • 文件存储 (src/storage/file/players.go):
      • 同样修改两个核心方法
      • 支持材质信息的获取和处理
  3. 材质信息处理

    • 支持皮肤和披风 URL 的获取
    • 正确处理纤细模型(alex)的 metadata
    • 生成符合规范的 JSON 结构并进行 base64 编码

测试结果

{
  "id": "e8f118932c70316a881dd3bdcf73b058",
  "name": "Sttot",
  "properties": [
    {
      "name": "textures",
      "value": "eyJ0aW1lc3RhbXAiOjE3NTUyNTU2MTI5NjYsInByb2ZpbGVJZCI6ImU4ZjExODkzMmM3MDMxNmE4ODFkZDNiZGNmNzNiMDU4IiwicHJvZmlsZU5hbWUiOiJTdHRvdCIsImlzUHVibGljIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vc2tpbi5uZXduYW4uY2l0eS90ZXh0dXJlcy9jZDJkOWViZjg4OThkMjUzMjgwNmVjOWE0MzBlYTgxN2Q1MzQwZTQxMDk1YWVjNmVhNjQwOTk3ZGZiNzQzNjQzIiwibWV0YWRhdGEiOnsibW9kZWwiOiJzbGltIn19LCJDQVBFIjp7InVybCI6Imh0dHBzOi8vc2tpbi5uZXduYW4uY2l0eS90ZXh0dXJlcy82ZGIyNjZiNGQwZDg2MzUzOGQyNWEyY2Q1MDFmN2VkMGQyMTI5ZGQyNDEyZmNlMDU3ZmMwMzZlMjZkODIyN2ZiIn19fQ=="
    },
    {
      "name": "uploadableTextures",
      "value": "skin,cape"
    }
  ]
}

解码后的 textures 内容:

{
  "timestamp": 1755255612966,
  "profileId": "e8f118932c70316a881dd3bdcf73b058",
  "profileName": "Sttot",
  "isPublic": true,
  "textures": {
    "SKIN": {
      "url": "https://skin.newnan.city/textures/cd2d9ebf8898d2532806ec9a430ea817d5340e41095aec6ea640997dfb743643",
      "metadata": {
        "model": "slim"
      }
    },
    "CAPE": {
      "url": "https://skin.newnan.city/textures/6db266b4d0d863538d25a2cd501f7ed0d2129dd2412fce057fc036e26d8227fb"
    }
  }
}

影响范围

  • ✅ 修复了 Minecraft 客户端无法加载皮肤和披风的问题
  • ✅ 完全符合 authlib-injector 技术规范
  • ✅ 兼容现有的 BlessingSkin 数据库结构
  • ✅ 不影响其他 API 接口的功能

🔐 数字签名系统实现 ✅ (2025-08-24)

签名功能完整实现

  • 统一签名生成: 修改GetProfileByUUID,当unsigned=false且Signature为空时自动生成签名
  • Storage层解耦: 移除Storage层的签名生成,统一在Handler层处理
  • 密钥对管理: 实现loadSignatureKeyPair方法,支持缓存和多存储类型
  • 签名算法: 实现SHA1withRSA签名算法,完全符合Yggdrasil规范

架构优化

  • 接口统一: Storage接口添加GetSignatureKeyPair方法
  • 缓存机制: 密钥对加载支持缓存,避免重复读取
  • 多存储支持:
    • BlessingSkin存储:从options表读取密钥对
    • File存储:从配置文件读取密钥对
  • 通用签名工具: 新增utils/signature.go,提供通用签名和验证功能

实现细节

  • 签名规范: 使用Base64编码的SHA1withRSA签名
  • 密钥格式: 支持PKCS#1和PKCS#8格式的RSA私钥
  • 性能优化: RSA密钥对解析结果缓存,避免重复解析开销
  • 高性能签名: 新增SignDataWithRSAKey函数,直接使用解析好的RSA密钥
  • 错误处理: 签名失败时不影响响应,继续返回无签名数据
  • 测试验证: 完整的签名生成和验证测试通过,性能测试显示1.09倍提升

修改文件

  • src/storage/interface/types.go: 添加GetSignatureKeyPair接口
  • src/storage/blessing_skin/storage.go: 实现密钥对获取
  • src/storage/blessing_skin/texture_signer.go: 添加GetSignatureKeyPair方法和RSA密钥缓存
  • src/storage/file/storage.go: 实现密钥对获取(返回错误)
  • src/handlers/meta.go: 修改为loadSignatureKeyPair并添加RSA密钥对缓存
  • src/handlers/profile.go: 添加签名生成逻辑和高性能签名方法
  • src/utils/signature.go: 新增通用签名工具和高性能签名函数
  • src/utils/cache_warmup.go: 更新密钥对调用
  • main.go: 更新ProfileHandler构造函数调用

性能优化亮点

  • 双层缓存: PEM格式密钥字符串缓存 + 解析后的RSA密钥对象缓存
  • 避免重复解析: 每次签名不再重新解析私钥,节省约390微秒/次
  • 并发安全: 使用读写锁保护缓存,支持高并发访问
  • 智能降级: 缓存未命中时自动降级到传统方式,确保系统健壮性
  • 全面覆盖: Handler层和BlessingSkin TextureSigner都实现了缓存优化

🔐 HasJoined API 签名修复 ✅ (2025-08-24)

问题发现

根据 Yggdrasil 规范,/sessionserver/session/minecraft/hasJoined 接口应该:

  1. 验证 username 是否与 serverId 对应令牌绑定的角色名称相同
  2. 返回令牌所绑定角色的完整信息(包含角色属性及数字签名)

但原实现存在两个问题:

  • ❌ 没有验证 username 对应的角色UUID是否与session中的ProfileID匹配
  • ❌ 返回的角色信息没有包含数字签名

修复内容

1. 添加角色UUID验证

src/handlers/session.goHasJoined 方法中添加:

// 验证角色UUID是否与会话中的ProfileID匹配
if profile.ID != session.ProfileID {
    utils.RespondNoContent(c)
    return
}

2. 添加签名生成功能

  • SessionHandler 添加 config 字段
  • 实现 generateSignature 方法(高性能版本,使用RSA密钥缓存)
  • 实现 loadSignatureKeyPair 方法(支持BlessingSkin和文件存储)
  • HasJoined 方法中为所有属性生成数字签名

3. 更新构造函数

  • 修改 NewSessionHandler 构造函数,添加 cfg *config.Config 参数
  • 更新 main.go 中的调用

技术实现

  • 签名算法: SHA1withRSA,与 Profile API 完全一致
  • 密钥缓存: 使用全局RSA密钥对缓存,避免重复解析
  • 多存储支持: 支持BlessingSkin(从数据库读取)和文件存储(从配置读取)
  • 性能优化: 使用 SignDataWithRSAKey 高性能签名函数

规范合规性

  • ✅ 检查 serverId 是否存在且有效
  • ✅ 验证 username 与 serverId 对应的角色匹配
  • ✅ 可选验证 IP 地址
  • ✅ 返回完整的角色信息(包含属性和数字签名)
  • ✅ 失败时返回 HTTP 204

修改文件

  • src/handlers/session.go: 添加签名生成逻辑和角色验证
  • main.go: 更新 SessionHandler 构造函数调用

📋 下一步计划

  1. 压力测试验证: 已完成,性能表现优秀
  2. Profile Properties 修复: 已完成,完全符合规范
  3. 数字签名系统: 已完成,支持SHA1withRSA签名
  4. HasJoined API 修复: 已完成,添加签名和验证
  5. APM工具集成: Prometheus + Grafana生产监控
  6. Redis缓存支持: 分布式缓存支持多实例部署
  7. 数据库索引优化: 分析慢查询并添加复合索引
  8. Docker部署: 提供完整的容器化部署方案
  9. 负载均衡: 多实例部署和负载均衡配置