feat(架构): 完善基础架构设计

This commit is contained in:
2025-07-02 16:17:59 +08:00
parent 03e615a8fd
commit 5b4392894f
89 changed files with 18555 additions and 3521 deletions

View File

@@ -0,0 +1,668 @@
# 📋 Makefile 命令详细执行逻辑指南
本文档详细说明了 TYAPI 项目中每个 Make 命令的**执行逻辑、具体步骤和背后原理**。
## 🚀 快速开始
```bash
# 查看所有可用命令
make help
# 设置开发环境
make setup
# 启动开发依赖服务
make dev-up
# 开发模式运行应用
make dev
```
---
## 📖 命令详细执行逻辑
### 🔍 **信息查看命令**
#### `make help`
**执行逻辑**:
```bash
# 1. 检测操作系统类型
# 2. 输出预定义的帮助信息
@echo "TYAPI Server Makefile"
@echo "Usage: make [target]"
@echo "Main targets:"
@echo " help Show this help message"
# ... 更多帮助信息
```
**实际效果**:
- 📄 直接打印硬编码的帮助文本
- 🚫 不执行任何文件操作
- ⚡ 瞬间完成,无依赖
#### `make version`
**执行逻辑**:
```bash
# 步骤1: 自动执行 make build (依赖检查)
# 步骤2: 执行构建好的二进制文件
./bin/tyapi-server -version
```
**详细步骤**:
1. **依赖检查**: 检查是否需要重新构建 (通过 make build)
2. **参数传递**: 向应用程序传递 `-version` 标志
3. **读取构建信息**: 应用程序输出编译时注入的版本信息
- `main.version` (来自 Makefile 的 VERSION 变量)
- `main.commit` (来自 git rev-parse --short HEAD)
- `main.date` (来自构建时间)
**相关文件**: `bin/tyapi-server`, `cmd/api/main.go`
---
### 🏗️ **构建相关命令**
#### `make build`
**执行逻辑**:
```bash
# 步骤1: 检测操作系统
ifeq ($(OS),Windows_NT)
# Windows: 创建bin目录 (如果不存在)
@if not exist "bin" mkdir "bin"
else
# Unix: 创建bin目录
@mkdir -p bin
endif
# 步骤2: 构建Go应用程序
go build -ldflags "-X main.version=1.0.0 -X main.commit=abc123 -X main.date=2025-01-01T00:00:00Z" -o bin/tyapi-server cmd/api/main.go
```
**详细步骤**:
1. **环境检测**: 通过 `$(OS)` 变量检测操作系统
2. **目录创建**:
- Windows: `if not exist "bin" mkdir "bin"`
- Unix: `mkdir -p bin`
3. **版本信息收集**:
- `BUILD_TIME`: PowerShell/date 命令获取当前时间
- `GIT_COMMIT`: git 命令获取当前 commit hash
- `VERSION`: 硬编码版本号 1.0.0
4. **编译执行**:
- 使用 `go build` 命令
- `-ldflags` 注入版本信息到可执行文件
- 输出文件到 `bin/tyapi-server`
**生成文件**: `bin/tyapi-server` (Windows 下为 `.exe`)
#### `make build-prod`
**执行逻辑**:
```bash
# 步骤1: 创建bin目录 (同build)
# 步骤2: 生产环境构建
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "..." -a -installsuffix cgo -o bin/tyapi-server-linux-amd64 cmd/api/main.go
```
**关键参数解析**:
- `CGO_ENABLED=0`: 禁用 CGO生成纯静态二进制
- `GOOS=linux GOARCH=amd64`: 强制 Linux 64 位平台
- `-a`: 重新构建所有包
- `-installsuffix cgo`: 避免缓存冲突
- **结果**: 生成可在任何 Linux x64 环境运行的静态二进制文件
#### `make build-all`
**执行逻辑**:
```bash
# 步骤1: 创建bin目录
# 步骤2: 循环构建5个平台
# Linux AMD64
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ... -o bin/tyapi-server-linux-amd64
# Linux ARM64
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build ... -o bin/tyapi-server-linux-arm64
# macOS Intel
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build ... -o bin/tyapi-server-darwin-amd64
# macOS Apple Silicon
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build ... -o bin/tyapi-server-darwin-arm64
# Windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build ... -o bin/tyapi-server-windows-amd64.exe
```
**生成的 5 个文件**:
- `bin/tyapi-server-linux-amd64`
- `bin/tyapi-server-linux-arm64`
- `bin/tyapi-server-darwin-amd64`
- `bin/tyapi-server-darwin-arm64`
- `bin/tyapi-server-windows-amd64.exe`
---
### ▶️ **运行相关命令**
#### `make run`
**执行逻辑**:
```bash
# 步骤1: 执行make build (依赖)
# 步骤2: 直接运行构建好的二进制文件
./bin/tyapi-server
```
**详细流程**:
1. **依赖检查**: Make 自动检查 build 目标是否需要重新执行
2. **文件存在性检查**: 确认 `bin/tyapi-server` 存在
3. **权限检查**: Unix 系统检查执行权限
4. **进程启动**: 启动 Gin HTTP 服务器
5. **端口监听**: 默认监听 8080 端口
**运行环境**: 需要 PostgreSQL 和 Redis 服务可用
#### `make dev`
**执行逻辑**:
```bash
# 直接执行 (已去掉air检查)
go run cmd/api/main.go
```
**详细步骤**:
1. **源码编译**: Go 编译器实时编译 main.go 及其依赖
2. **内存运行**: 不生成磁盘文件,直接在内存中运行
3. **依赖加载**: 自动下载并编译所有 import 的包
4. **服务启动**: 启动 HTTP 服务器监听 8080 端口
**与 build 的区别**:
- ✅ 无需预先构建
- ✅ 代码变更后需手动重启
- ❌ 每次启动都需要重新编译
---
### 🛠️ **开发工具命令**
#### `make deps`
**执行逻辑**:
```bash
# 步骤1: 下载依赖
go mod download
# 步骤2: 整理依赖
go mod tidy
```
**详细步骤**:
1. **go mod download**:
- 读取 `go.mod` 文件
- 下载所有依赖包到 `$GOPATH/pkg/mod/`
- 验证包的 checksum (通过 go.sum)
- 不修改 go.mod 文件
2. **go mod tidy**:
- 扫描所有.go 文件中的 import 语句
- 添加缺失的依赖到 go.mod
- 移除未使用的依赖
- 更新 go.sum 文件
**影响的文件**: `go.mod`, `go.sum`, `$GOPATH/pkg/mod/`
#### `make fmt`
**执行逻辑**:
```bash
go fmt ./...
```
**详细步骤**:
1. **递归扫描**: 扫描当前目录及所有子目录的.go 文件
2. **格式化规则应用**:
- 统一缩进 (tab)
- 统一换行
- 移除行尾空格
- 规范化大括号位置
3. **文件修改**: 直接修改源文件 (in-place)
4. **报告**: 输出被修改的文件列表
**影响的文件**: 所有.go 源码文件
#### `make lint`
**执行逻辑**:
```bash
# 检查golangci-lint是否安装
@if command -v golangci-lint >/dev/null 2>&1; then \
golangci-lint run; \
else \
echo "golangci-lint not installed, skipping lint check"; \
fi
```
**详细步骤**:
1. **工具检查**: 使用 `command -v` 检查 golangci-lint 是否在 PATH 中
2. **如果已安装**:
- 读取 `.golangci.yml` 配置 (如果存在)
- 运行多个 linter 检查 (默认包括: errcheck, gosimple, govet, ineffassign 等)
- 分析所有.go 文件
- 输出问题报告
3. **如果未安装**: 显示提示信息并跳过
**检查项目**: 代码质量、潜在 bug、性能问题、安全问题等
---
### 🧪 **测试相关命令**
#### `make test`
**执行逻辑**:
```bash
go test -v -race -coverprofile=coverage.out ./...
```
**参数详解**:
- `-v`: 详细输出,显示每个测试的名称和结果
- `-race`: 启用竞态条件检测器
- `-coverprofile=coverage.out`: 生成覆盖率数据文件
- `./...`: 递归测试所有包
**详细步骤**:
1. **包发现**: 递归扫描所有包含\*\_test.go 的目录
2. **编译测试**: 为每个包编译测试二进制文件
3. **竞态检测**: 启用 Go race detector
4. **执行测试**: 逐个运行 Test\*函数
5. **覆盖率收集**: 记录每行代码是否被执行
6. **生成报告**: 输出到 coverage.out 文件
**生成文件**: `coverage.out`
#### `make coverage`
**执行逻辑**:
```bash
# 步骤1: 执行make test (依赖)
# 步骤2: 生成HTML报告
go tool cover -html=coverage.out -o coverage.html
# 步骤3: 提示用户
@echo "Coverage report generated: coverage.html"
```
**详细步骤**:
1. **依赖检查**: 确保 coverage.out 文件存在
2. **HTML 生成**:
- 读取 coverage.out 二进制数据
- 生成带颜色标记的 HTML 页面
- 绿色 = 已覆盖,红色 = 未覆盖
3. **文件输出**: 生成 coverage.html 文件
**生成文件**: `coverage.html` (可在浏览器中打开)
---
### 🗂️ **环境管理命令**
#### `make env`
**执行逻辑**:
```bash
# Windows环境
ifeq ($(OS),Windows_NT)
@if not exist ".env" ( \
echo Creating .env file... && \
copy env.example .env && \
echo .env file created, please modify configuration as needed \
) else ( \
echo .env file already exists \
)
# Unix环境
else
@if [ ! -f .env ]; then \
echo "Creating .env file..."; \
cp env.example .env; \
echo ".env file created, please modify configuration as needed"; \
else \
echo ".env file already exists"; \
fi
endif
```
**详细步骤**:
1. **文件检查**: 检查.env 文件是否已存在
2. **如果不存在**:
- Windows: 使用 `copy` 命令复制
- Unix: 使用 `cp` 命令复制
- 复制 `env.example``.env`
3. **如果已存在**: 显示提示信息,不覆盖现有文件
**相关文件**: `env.example``.env`
#### `make setup`
**执行逻辑**:
```bash
# 依赖: make deps env
# 然后执行:
@echo "Setting up development environment..."
@echo "1. Dependencies installed"
@echo "2. .env file created"
@echo "3. Please ensure PostgreSQL and Redis are running"
@echo "4. Run 'make migrate' to create database tables"
@echo "5. Run 'make dev' to start development server"
```
**详细步骤**:
1. **执行 make deps**: 安装 Go 依赖
2. **执行 make env**: 创建环境配置文件
3. **输出设置指南**: 显示后续步骤提示
**完成后状态**: 开发环境基本就绪,需要手动启动数据库服务
---
### 🐳 **Docker 相关命令**
#### `make docker-build`
**执行逻辑**:
```bash
docker build -t tyapi-server:1.0.0 -t tyapi-server:latest .
```
**详细步骤**:
1. **读取 Dockerfile**: 从当前目录读取 Dockerfile
2. **构建上下文**: 将当前目录作为构建上下文发送给 Docker daemon
3. **镜像构建**:
- 执行 Dockerfile 中的每个指令
- 逐层构建镜像
- 缓存中间层以提高构建速度
4. **标签应用**: 同时打上版本标签和 latest 标签
**生成镜像**: `tyapi-server:1.0.0`, `tyapi-server:latest`
#### `make docker-run`
**执行逻辑**:
```bash
docker run -d --name tyapi-server -p 8080:8080 --env-file .env tyapi-server:latest
```
**详细步骤**:
1. **环境检查**: 确认.env 文件存在
2. **容器创建**: 基于 latest 镜像创建容器
3. **参数应用**:
- `-d`: 后台运行 (detached mode)
- `--name tyapi-server`: 设置容器名称
- `-p 8080:8080`: 端口映射 (主机:容器)
- `--env-file .env`: 加载环境变量文件
4. **容器启动**: 启动应用程序进程
**结果**: 后台运行的 Docker 容器,端口 8080 可访问
---
### 🔧 **服务管理命令**
#### `make services-up` / `make dev-up`
**执行逻辑**:
```bash
# 检查docker-compose.dev.yml文件
# Windows:
@if exist "docker-compose.dev.yml" ( \
docker-compose -f docker-compose.dev.yml up -d \
) else ( \
echo docker-compose.dev.yml not found \
)
```
**详细步骤**:
1. **文件检查**: 验证 docker-compose.dev.yml 文件存在
2. **Docker Compose 启动**:
- 读取 docker-compose.dev.yml 配置
- 拉取所需的 Docker 镜像 (如果本地不存在)
- 创建 Docker 网络 (tyapi-network)
- 创建数据卷 (postgres_data, redis_data 等)
- 按依赖顺序启动服务:
- PostgreSQL (端口 5432)
- Redis (端口 6379)
- pgAdmin (端口 5050)
- Prometheus (端口 9090)
- Grafana (端口 3000)
- Jaeger (端口 16686)
- MinIO (端口 9000/9001)
- MailHog (端口 8025)
**启动的 8 个服务**: 数据库、缓存、监控、管理工具等完整开发环境
#### `make services-down` / `make dev-down`
**执行逻辑**:
```bash
docker-compose -f docker-compose.dev.yml down
```
**详细步骤**:
1. **容器停止**: 优雅停止所有服务容器 (发送 SIGTERM)
2. **容器删除**: 删除所有相关容器
3. **网络清理**: 删除自定义网络
4. **数据保留**: 保留数据卷 (数据不丢失)
**保留的资源**: 数据卷、镜像
**删除的资源**: 容器、网络
---
### 🗃️ **数据库相关命令**
#### `make migrate`
**执行逻辑**:
```bash
# 步骤1: 执行make build (依赖)
# 步骤2: 运行迁移
./bin/tyapi-server -migrate
```
**详细步骤**:
1. **应用程序启动**: 以迁移模式启动应用
2. **数据库连接**: 连接到 PostgreSQL 数据库
3. **迁移文件扫描**: 扫描 migrations 目录下的 SQL 文件
4. **版本检查**: 检查数据库中的迁移版本表
5. **增量执行**: 只执行未应用的迁移文件
6. **版本更新**: 更新迁移版本记录
7. **应用退出**: 迁移完成后程序退出
**相关文件**: `internal/domains/user/migrations/`, PostgreSQL 数据库
#### `make health`
**执行逻辑**:
```bash
# 步骤1: 执行make build (依赖)
# 步骤2: 运行健康检查
./bin/tyapi-server -health
```
**详细步骤**:
1. **健康检查启动**: 以健康检查模式启动应用
2. **组件检查**:
- PostgreSQL 数据库连接
- Redis 缓存连接
- 关键配置项验证
- 必要文件存在性检查
3. **状态报告**: 输出每个组件的健康状态
4. **退出码**: 成功返回 0失败返回非零
**检查项目**: 数据库、缓存、配置、权限等
---
### 🧹 **清理命令**
#### `make clean`
**执行逻辑**:
```bash
# 步骤1: Go缓存清理
go clean
# 步骤2: 文件删除 (根据操作系统)
# Windows:
@if exist "bin" rmdir /s /q "bin" 2>nul || echo ""
@if exist "coverage.out" del /f /q "coverage.out" 2>nul || echo ""
@if exist "coverage.html" del /f /q "coverage.html" 2>nul || echo ""
```
**详细步骤**:
1. **Go 清理**:
- 清理编译缓存
- 删除临时构建文件
- 清理测试缓存
2. **目录删除**:
- 删除整个 bin 目录及内容
- Windows: `rmdir /s /q`
- Unix: `rm -rf`
3. **文件删除**:
- 删除 coverage.out 测试覆盖率文件
- 删除 coverage.html 覆盖率报告
4. **错误抑制**: 使用 `2>nul``2>/dev/null` 忽略"文件不存在"错误
**删除的内容**: `bin/`, `coverage.out`, `coverage.html`, Go 构建缓存
---
### 🚀 **流水线命令**
#### `make ci`
**执行逻辑**:
```bash
# 顺序执行5个步骤:
make deps # 安装依赖
make fmt # 代码格式化
make lint # 代码检查
make test # 运行测试
make build # 构建应用
```
**详细流程**:
1. **deps**: 确保所有依赖最新且完整
2. **fmt**: 统一代码格式,确保可读性
3. **lint**: 静态代码分析,发现潜在问题
4. **test**: 运行所有测试,确保功能正确
5. **build**: 验证代码可以成功编译
**失败策略**: 任何一步失败,立即停止后续步骤
#### `make release`
**执行逻辑**:
```bash
# 顺序执行3个步骤:
make ci # 完整CI检查
make build-all # 交叉编译所有平台
make docker-build # 构建Docker镜像
```
**详细流程**:
1. **CI 检查**: 确保代码质量和功能正确性
2. **多平台构建**: 生成 5 个平台的可执行文件
3. **Docker 镜像**: 构建容器化版本
**输出产物**:
- 5 个平台的二进制文件
- Docker 镜像 (2 个标签)
- 测试覆盖率报告
---
## 💡 **命令执行顺序和依赖关系**
### 🔗 **依赖关系图**
```
version ─────► build
health ──────► build
run ─────────► build
migrate ─────► build
coverage ────► test
ci ──────────► deps → fmt → lint → test → build
release ─────► ci → build-all → docker-build
setup ───────► deps → env
```
### ⚡ **执行时机建议**
#### **每次开发前**
```bash
make setup # 首次使用
make dev-up # 启动依赖服务
make dev # 开始开发
```
#### **提交代码前**
```bash
make ci # 完整检查
```
#### **发布版本前**
```bash
make release # 完整构建
```
---
**这个指南详细说明了每个命令背后的具体操作逻辑,帮助您完全理解 Makefile 的工作原理!** 🎯

8
docs/docs.go Normal file
View File

@@ -0,0 +1,8 @@
// Package docs 生成的API文档包
// 这个包导入了自动生成的Swagger文档
package docs
import (
// 导入生成的swagger文档
_ "tyapi-server/docs/swagger"
)

592
docs/swagger/docs.go Normal file
View File

@@ -0,0 +1,592 @@
// Package swagger Code generated by swaggo/swag. DO NOT EDIT
package swagger
import "github.com/swaggo/swag"
const docTemplate = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{escape .Description}}",
"title": "{{.Title}}",
"contact": {
"name": "API Support",
"url": "https://github.com/your-org/tyapi-server-gin",
"email": "support@example.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/users/login-password": {
"post": {
"description": "使用手机号和密码进行用户登录返回JWT令牌",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "用户密码登录",
"parameters": [
{
"description": "密码登录请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.LoginWithPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "登录成功",
"schema": {
"$ref": "#/definitions/dto.LoginResponse"
}
},
"400": {
"description": "请求参数错误",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"401": {
"description": "认证失败",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/login-sms": {
"post": {
"description": "使用手机号和短信验证码进行用户登录返回JWT令牌",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "用户短信验证码登录",
"parameters": [
{
"description": "短信登录请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.LoginWithSMSRequest"
}
}
],
"responses": {
"200": {
"description": "登录成功",
"schema": {
"$ref": "#/definitions/dto.LoginResponse"
}
},
"400": {
"description": "请求参数错误或验证码无效",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"401": {
"description": "认证失败",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/me": {
"get": {
"security": [
{
"Bearer": []
}
],
"description": "根据JWT令牌获取当前登录用户的详细信息",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户管理"
],
"summary": "获取当前用户信息",
"responses": {
"200": {
"description": "用户信息",
"schema": {
"$ref": "#/definitions/dto.UserResponse"
}
},
"401": {
"description": "未认证",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"404": {
"description": "用户不存在",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/me/password": {
"put": {
"security": [
{
"Bearer": []
}
],
"description": "使用旧密码、新密码确认和验证码修改当前用户的密码",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户管理"
],
"summary": "修改密码",
"parameters": [
{
"description": "修改密码请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.ChangePasswordRequest"
}
}
],
"responses": {
"200": {
"description": "密码修改成功",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"400": {
"description": "请求参数错误或验证码无效",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"401": {
"description": "未认证",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/register": {
"post": {
"description": "使用手机号、密码和验证码进行用户注册,需要确认密码",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "用户注册",
"parameters": [
{
"description": "用户注册请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.RegisterRequest"
}
}
],
"responses": {
"201": {
"description": "注册成功",
"schema": {
"$ref": "#/definitions/dto.UserResponse"
}
},
"400": {
"description": "请求参数错误或验证码无效",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"409": {
"description": "手机号已存在",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/send-code": {
"post": {
"description": "向指定手机号发送验证码,支持注册、登录、修改密码等场景",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "发送短信验证码",
"parameters": [
{
"description": "发送验证码请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.SendCodeRequest"
}
}
],
"responses": {
"200": {
"description": "验证码发送成功",
"schema": {
"$ref": "#/definitions/dto.SendCodeResponse"
}
},
"400": {
"description": "请求参数错误",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"429": {
"description": "请求频率限制",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
},
"definitions": {
"dto.ChangePasswordRequest": {
"type": "object",
"required": [
"code",
"confirm_new_password",
"new_password",
"old_password"
],
"properties": {
"code": {
"type": "string",
"example": "123456"
},
"confirm_new_password": {
"type": "string",
"example": "newpassword123"
},
"new_password": {
"type": "string",
"maxLength": 128,
"minLength": 6,
"example": "newpassword123"
},
"old_password": {
"type": "string",
"example": "oldpassword123"
}
}
},
"dto.LoginResponse": {
"type": "object",
"properties": {
"access_token": {
"type": "string",
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"expires_in": {
"type": "integer",
"example": 86400
},
"login_method": {
"description": "password 或 sms",
"type": "string",
"example": "password"
},
"token_type": {
"type": "string",
"example": "Bearer"
},
"user": {
"$ref": "#/definitions/dto.UserResponse"
}
}
},
"dto.LoginWithPasswordRequest": {
"type": "object",
"required": [
"password",
"phone"
],
"properties": {
"password": {
"type": "string",
"example": "password123"
},
"phone": {
"type": "string",
"example": "13800138000"
}
}
},
"dto.LoginWithSMSRequest": {
"type": "object",
"required": [
"code",
"phone"
],
"properties": {
"code": {
"type": "string",
"example": "123456"
},
"phone": {
"type": "string",
"example": "13800138000"
}
}
},
"dto.RegisterRequest": {
"type": "object",
"required": [
"code",
"confirm_password",
"password",
"phone"
],
"properties": {
"code": {
"type": "string",
"example": "123456"
},
"confirm_password": {
"type": "string",
"example": "password123"
},
"password": {
"type": "string",
"maxLength": 128,
"minLength": 6,
"example": "password123"
},
"phone": {
"type": "string",
"example": "13800138000"
}
}
},
"dto.SendCodeRequest": {
"type": "object",
"required": [
"phone",
"scene"
],
"properties": {
"phone": {
"type": "string",
"example": "13800138000"
},
"scene": {
"enum": [
"register",
"login",
"change_password",
"reset_password",
"bind",
"unbind"
],
"allOf": [
{
"$ref": "#/definitions/entities.SMSScene"
}
],
"example": "register"
}
}
},
"dto.SendCodeResponse": {
"type": "object",
"properties": {
"expires_at": {
"type": "string",
"example": "2024-01-01T00:05:00Z"
},
"message": {
"type": "string",
"example": "验证码发送成功"
}
}
},
"dto.UserResponse": {
"type": "object",
"properties": {
"created_at": {
"type": "string",
"example": "2024-01-01T00:00:00Z"
},
"id": {
"type": "string",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"phone": {
"type": "string",
"example": "13800138000"
},
"updated_at": {
"type": "string",
"example": "2024-01-01T00:00:00Z"
}
}
},
"entities.SMSScene": {
"type": "string",
"enum": [
"register",
"login",
"change_password",
"reset_password",
"bind",
"unbind"
],
"x-enum-comments": {
"SMSSceneBind": "绑定手机号",
"SMSSceneChangePassword": "修改密码",
"SMSSceneLogin": "登录",
"SMSSceneRegister": "注册",
"SMSSceneResetPassword": "重置密码",
"SMSSceneUnbind": "解绑手机号"
},
"x-enum-varnames": [
"SMSSceneRegister",
"SMSSceneLogin",
"SMSSceneChangePassword",
"SMSSceneResetPassword",
"SMSSceneBind",
"SMSSceneUnbind"
]
}
},
"securityDefinitions": {
"Bearer": {
"description": "Type \"Bearer\" followed by a space and JWT token.",
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
}
}`
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "1.0",
Host: "localhost:8080",
BasePath: "/api/v1",
Schemes: []string{},
Title: "TYAPI Server API",
Description: "基于DDD和Clean Architecture的企业级后端API服务\n采用Gin框架构建支持用户管理、JWT认证、事件驱动等功能",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}
func init() {
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}

568
docs/swagger/swagger.json Normal file
View File

@@ -0,0 +1,568 @@
{
"swagger": "2.0",
"info": {
"description": "基于DDD和Clean Architecture的企业级后端API服务\n采用Gin框架构建支持用户管理、JWT认证、事件驱动等功能",
"title": "TYAPI Server API",
"contact": {
"name": "API Support",
"url": "https://github.com/your-org/tyapi-server-gin",
"email": "support@example.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.0"
},
"host": "localhost:8080",
"basePath": "/api/v1",
"paths": {
"/users/login-password": {
"post": {
"description": "使用手机号和密码进行用户登录返回JWT令牌",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "用户密码登录",
"parameters": [
{
"description": "密码登录请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.LoginWithPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "登录成功",
"schema": {
"$ref": "#/definitions/dto.LoginResponse"
}
},
"400": {
"description": "请求参数错误",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"401": {
"description": "认证失败",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/login-sms": {
"post": {
"description": "使用手机号和短信验证码进行用户登录返回JWT令牌",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "用户短信验证码登录",
"parameters": [
{
"description": "短信登录请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.LoginWithSMSRequest"
}
}
],
"responses": {
"200": {
"description": "登录成功",
"schema": {
"$ref": "#/definitions/dto.LoginResponse"
}
},
"400": {
"description": "请求参数错误或验证码无效",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"401": {
"description": "认证失败",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/me": {
"get": {
"security": [
{
"Bearer": []
}
],
"description": "根据JWT令牌获取当前登录用户的详细信息",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户管理"
],
"summary": "获取当前用户信息",
"responses": {
"200": {
"description": "用户信息",
"schema": {
"$ref": "#/definitions/dto.UserResponse"
}
},
"401": {
"description": "未认证",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"404": {
"description": "用户不存在",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/me/password": {
"put": {
"security": [
{
"Bearer": []
}
],
"description": "使用旧密码、新密码确认和验证码修改当前用户的密码",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户管理"
],
"summary": "修改密码",
"parameters": [
{
"description": "修改密码请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.ChangePasswordRequest"
}
}
],
"responses": {
"200": {
"description": "密码修改成功",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"400": {
"description": "请求参数错误或验证码无效",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"401": {
"description": "未认证",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/register": {
"post": {
"description": "使用手机号、密码和验证码进行用户注册,需要确认密码",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "用户注册",
"parameters": [
{
"description": "用户注册请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.RegisterRequest"
}
}
],
"responses": {
"201": {
"description": "注册成功",
"schema": {
"$ref": "#/definitions/dto.UserResponse"
}
},
"400": {
"description": "请求参数错误或验证码无效",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"409": {
"description": "手机号已存在",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/users/send-code": {
"post": {
"description": "向指定手机号发送验证码,支持注册、登录、修改密码等场景",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"用户认证"
],
"summary": "发送短信验证码",
"parameters": [
{
"description": "发送验证码请求",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.SendCodeRequest"
}
}
],
"responses": {
"200": {
"description": "验证码发送成功",
"schema": {
"$ref": "#/definitions/dto.SendCodeResponse"
}
},
"400": {
"description": "请求参数错误",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"429": {
"description": "请求频率限制",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"500": {
"description": "服务器内部错误",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
},
"definitions": {
"dto.ChangePasswordRequest": {
"type": "object",
"required": [
"code",
"confirm_new_password",
"new_password",
"old_password"
],
"properties": {
"code": {
"type": "string",
"example": "123456"
},
"confirm_new_password": {
"type": "string",
"example": "newpassword123"
},
"new_password": {
"type": "string",
"maxLength": 128,
"minLength": 6,
"example": "newpassword123"
},
"old_password": {
"type": "string",
"example": "oldpassword123"
}
}
},
"dto.LoginResponse": {
"type": "object",
"properties": {
"access_token": {
"type": "string",
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"expires_in": {
"type": "integer",
"example": 86400
},
"login_method": {
"description": "password 或 sms",
"type": "string",
"example": "password"
},
"token_type": {
"type": "string",
"example": "Bearer"
},
"user": {
"$ref": "#/definitions/dto.UserResponse"
}
}
},
"dto.LoginWithPasswordRequest": {
"type": "object",
"required": [
"password",
"phone"
],
"properties": {
"password": {
"type": "string",
"example": "password123"
},
"phone": {
"type": "string",
"example": "13800138000"
}
}
},
"dto.LoginWithSMSRequest": {
"type": "object",
"required": [
"code",
"phone"
],
"properties": {
"code": {
"type": "string",
"example": "123456"
},
"phone": {
"type": "string",
"example": "13800138000"
}
}
},
"dto.RegisterRequest": {
"type": "object",
"required": [
"code",
"confirm_password",
"password",
"phone"
],
"properties": {
"code": {
"type": "string",
"example": "123456"
},
"confirm_password": {
"type": "string",
"example": "password123"
},
"password": {
"type": "string",
"maxLength": 128,
"minLength": 6,
"example": "password123"
},
"phone": {
"type": "string",
"example": "13800138000"
}
}
},
"dto.SendCodeRequest": {
"type": "object",
"required": [
"phone",
"scene"
],
"properties": {
"phone": {
"type": "string",
"example": "13800138000"
},
"scene": {
"enum": [
"register",
"login",
"change_password",
"reset_password",
"bind",
"unbind"
],
"allOf": [
{
"$ref": "#/definitions/entities.SMSScene"
}
],
"example": "register"
}
}
},
"dto.SendCodeResponse": {
"type": "object",
"properties": {
"expires_at": {
"type": "string",
"example": "2024-01-01T00:05:00Z"
},
"message": {
"type": "string",
"example": "验证码发送成功"
}
}
},
"dto.UserResponse": {
"type": "object",
"properties": {
"created_at": {
"type": "string",
"example": "2024-01-01T00:00:00Z"
},
"id": {
"type": "string",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"phone": {
"type": "string",
"example": "13800138000"
},
"updated_at": {
"type": "string",
"example": "2024-01-01T00:00:00Z"
}
}
},
"entities.SMSScene": {
"type": "string",
"enum": [
"register",
"login",
"change_password",
"reset_password",
"bind",
"unbind"
],
"x-enum-comments": {
"SMSSceneBind": "绑定手机号",
"SMSSceneChangePassword": "修改密码",
"SMSSceneLogin": "登录",
"SMSSceneRegister": "注册",
"SMSSceneResetPassword": "重置密码",
"SMSSceneUnbind": "解绑手机号"
},
"x-enum-varnames": [
"SMSSceneRegister",
"SMSSceneLogin",
"SMSSceneChangePassword",
"SMSSceneResetPassword",
"SMSSceneBind",
"SMSSceneUnbind"
]
}
},
"securityDefinitions": {
"Bearer": {
"description": "Type \"Bearer\" followed by a space and JWT token.",
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
}
}

397
docs/swagger/swagger.yaml Normal file
View File

@@ -0,0 +1,397 @@
basePath: /api/v1
definitions:
dto.ChangePasswordRequest:
properties:
code:
example: "123456"
type: string
confirm_new_password:
example: newpassword123
type: string
new_password:
example: newpassword123
maxLength: 128
minLength: 6
type: string
old_password:
example: oldpassword123
type: string
required:
- code
- confirm_new_password
- new_password
- old_password
type: object
dto.LoginResponse:
properties:
access_token:
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
type: string
expires_in:
example: 86400
type: integer
login_method:
description: password 或 sms
example: password
type: string
token_type:
example: Bearer
type: string
user:
$ref: '#/definitions/dto.UserResponse'
type: object
dto.LoginWithPasswordRequest:
properties:
password:
example: password123
type: string
phone:
example: "13800138000"
type: string
required:
- password
- phone
type: object
dto.LoginWithSMSRequest:
properties:
code:
example: "123456"
type: string
phone:
example: "13800138000"
type: string
required:
- code
- phone
type: object
dto.RegisterRequest:
properties:
code:
example: "123456"
type: string
confirm_password:
example: password123
type: string
password:
example: password123
maxLength: 128
minLength: 6
type: string
phone:
example: "13800138000"
type: string
required:
- code
- confirm_password
- password
- phone
type: object
dto.SendCodeRequest:
properties:
phone:
example: "13800138000"
type: string
scene:
allOf:
- $ref: '#/definitions/entities.SMSScene'
enum:
- register
- login
- change_password
- reset_password
- bind
- unbind
example: register
required:
- phone
- scene
type: object
dto.SendCodeResponse:
properties:
expires_at:
example: "2024-01-01T00:05:00Z"
type: string
message:
example: 验证码发送成功
type: string
type: object
dto.UserResponse:
properties:
created_at:
example: "2024-01-01T00:00:00Z"
type: string
id:
example: 123e4567-e89b-12d3-a456-426614174000
type: string
phone:
example: "13800138000"
type: string
updated_at:
example: "2024-01-01T00:00:00Z"
type: string
type: object
entities.SMSScene:
enum:
- register
- login
- change_password
- reset_password
- bind
- unbind
type: string
x-enum-comments:
SMSSceneBind: 绑定手机号
SMSSceneChangePassword: 修改密码
SMSSceneLogin: 登录
SMSSceneRegister: 注册
SMSSceneResetPassword: 重置密码
SMSSceneUnbind: 解绑手机号
x-enum-varnames:
- SMSSceneRegister
- SMSSceneLogin
- SMSSceneChangePassword
- SMSSceneResetPassword
- SMSSceneBind
- SMSSceneUnbind
host: localhost:8080
info:
contact:
email: support@example.com
name: API Support
url: https://github.com/your-org/tyapi-server-gin
description: |-
基于DDD和Clean Architecture的企业级后端API服务
采用Gin框架构建支持用户管理、JWT认证、事件驱动等功能
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
title: TYAPI Server API
version: "1.0"
paths:
/users/login-password:
post:
consumes:
- application/json
description: 使用手机号和密码进行用户登录返回JWT令牌
parameters:
- description: 密码登录请求
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.LoginWithPasswordRequest'
produces:
- application/json
responses:
"200":
description: 登录成功
schema:
$ref: '#/definitions/dto.LoginResponse'
"400":
description: 请求参数错误
schema:
additionalProperties: true
type: object
"401":
description: 认证失败
schema:
additionalProperties: true
type: object
"500":
description: 服务器内部错误
schema:
additionalProperties: true
type: object
summary: 用户密码登录
tags:
- 用户认证
/users/login-sms:
post:
consumes:
- application/json
description: 使用手机号和短信验证码进行用户登录返回JWT令牌
parameters:
- description: 短信登录请求
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.LoginWithSMSRequest'
produces:
- application/json
responses:
"200":
description: 登录成功
schema:
$ref: '#/definitions/dto.LoginResponse'
"400":
description: 请求参数错误或验证码无效
schema:
additionalProperties: true
type: object
"401":
description: 认证失败
schema:
additionalProperties: true
type: object
"500":
description: 服务器内部错误
schema:
additionalProperties: true
type: object
summary: 用户短信验证码登录
tags:
- 用户认证
/users/me:
get:
consumes:
- application/json
description: 根据JWT令牌获取当前登录用户的详细信息
produces:
- application/json
responses:
"200":
description: 用户信息
schema:
$ref: '#/definitions/dto.UserResponse'
"401":
description: 未认证
schema:
additionalProperties: true
type: object
"404":
description: 用户不存在
schema:
additionalProperties: true
type: object
"500":
description: 服务器内部错误
schema:
additionalProperties: true
type: object
security:
- Bearer: []
summary: 获取当前用户信息
tags:
- 用户管理
/users/me/password:
put:
consumes:
- application/json
description: 使用旧密码、新密码确认和验证码修改当前用户的密码
parameters:
- description: 修改密码请求
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.ChangePasswordRequest'
produces:
- application/json
responses:
"200":
description: 密码修改成功
schema:
additionalProperties: true
type: object
"400":
description: 请求参数错误或验证码无效
schema:
additionalProperties: true
type: object
"401":
description: 未认证
schema:
additionalProperties: true
type: object
"500":
description: 服务器内部错误
schema:
additionalProperties: true
type: object
security:
- Bearer: []
summary: 修改密码
tags:
- 用户管理
/users/register:
post:
consumes:
- application/json
description: 使用手机号、密码和验证码进行用户注册,需要确认密码
parameters:
- description: 用户注册请求
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.RegisterRequest'
produces:
- application/json
responses:
"201":
description: 注册成功
schema:
$ref: '#/definitions/dto.UserResponse'
"400":
description: 请求参数错误或验证码无效
schema:
additionalProperties: true
type: object
"409":
description: 手机号已存在
schema:
additionalProperties: true
type: object
"500":
description: 服务器内部错误
schema:
additionalProperties: true
type: object
summary: 用户注册
tags:
- 用户认证
/users/send-code:
post:
consumes:
- application/json
description: 向指定手机号发送验证码,支持注册、登录、修改密码等场景
parameters:
- description: 发送验证码请求
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.SendCodeRequest'
produces:
- application/json
responses:
"200":
description: 验证码发送成功
schema:
$ref: '#/definitions/dto.SendCodeResponse'
"400":
description: 请求参数错误
schema:
additionalProperties: true
type: object
"429":
description: 请求频率限制
schema:
additionalProperties: true
type: object
"500":
description: 服务器内部错误
schema:
additionalProperties: true
type: object
summary: 发送短信验证码
tags:
- 用户认证
securityDefinitions:
Bearer:
description: Type "Bearer" followed by a space and JWT token.
in: header
name: Authorization
type: apiKey
swagger: "2.0"

View File

@@ -221,17 +221,18 @@ iostat 1 5
## 开发环境问题
### 1. 热重载不工作
### 1. 开发服务器问题
```bash
# 检查文件监控
ls -la .air.toml
# 停止当前开发服务器
Ctrl+C
# 重开发服务器
make dev-restart
# 重新启动开发服务器
make dev
# 检查文件权限
chmod +x scripts/dev.sh
# 检查Go模块状态
go mod tidy
go mod download
```
### 2. 测试失败

View File

@@ -0,0 +1,145 @@
# 📚 TYAPI Server 文档中心
欢迎使用 TYAPI Server 文档中心!我们已将原本的使用指南拆分为多个专题文档,方便您按需查阅。
## 📋 文档导航
### 🚀 [快速开始指南](./快速开始指南.md)
- 前置要求
- 一键启动
- 验证安装
- 访问管理界面
### 🔧 [环境搭建指南](./环境搭建指南.md)
- 开发环境配置
- 生产环境配置
- 服务配置说明
- 常见配置问题
### 📋 [Makefile 命令指南](./MAKEFILE_GUIDE.md)
- 所有 Make 命令详细说明
- 常用工作流程
- 构建和部署命令
- 开发工具命令
- 故障排除技巧
### 👨‍💻 [开发指南](./开发指南.md)
- 项目结构理解
- 开发流程
- 测试编写
- 调试技巧
- 代码规范
### 🌐 [API 使用指南](./API使用指南.md)
- 认证机制
- 用户管理 API
- 响应格式
- HTTP 状态码
- API 测试
### 🚀 [部署指南](./部署指南.md)
- Docker 部署
- Kubernetes 部署
- 云平台部署
- 负载均衡配置
- 监控部署
### 📦 [生产环境部署指南](./生产环境部署指南.md)
- Docker + 私有 Registry 完整部署方案
- 多阶段构建生产级镜像
- 安全配置和资源限制
- 自动化部署脚本
- 监控和故障排除
### 🔍 [故障排除指南](./故障排除指南.md)
- 常见问题
- 日志分析
- 性能问题
- 紧急响应流程
### 📋 [最佳实践指南](./最佳实践指南.md)
- 开发最佳实践
- 安全最佳实践
- 性能最佳实践
- 运维最佳实践
- 团队协作
### 🔍 [链路追踪指南](./链路追踪指南.md)
- Jaeger 配置和使用
- OpenTelemetry 集成
- Grafana 可视化
- 性能监控和优化
- 故障排查技巧
## 🎯 快速索引
### 新手入门
1. [快速开始指南](./快速开始指南.md) - 5 分钟快速体验
2. [环境搭建指南](./环境搭建指南.md) - 配置开发环境
3. [Makefile 命令指南](./MAKEFILE_GUIDE.md) - 掌握所有开发命令
4. [开发指南](./开发指南.md) - 开始第一个功能
### 日常开发
- [Makefile 命令指南](./MAKEFILE_GUIDE.md) - 构建、测试、部署命令
- [API 使用指南](./API使用指南.md) - API 调用参考
- [开发指南](./开发指南.md) - 开发流程和规范
- [链路追踪指南](./链路追踪指南.md) - 性能监控和问题排查
- [故障排除指南](./故障排除指南.md) - 解决常见问题
### 生产部署
- [部署指南](./部署指南.md) - 生产环境部署
- [生产环境部署指南](./生产环境部署指南.md) - Docker + 私有 Registry 完整方案
- [最佳实践指南](./最佳实践指南.md) - 运维最佳实践
- [故障排除指南](./故障排除指南.md) - 生产问题排查
## 🔗 相关文档
### 技术文档
- [架构文档](./ARCHITECTURE.md) - 系统架构设计
- [API 规范](http://localhost:8080/swagger/) - 在线 API 文档
### 项目文档
- [README](../README.md) - 项目介绍
- [更新日志](../CHANGELOG.md) - 版本变更记录
## 📞 获取帮助
### 在线资源
- **Swagger UI**: http://localhost:8080/swagger/
- **健康检查**: http://localhost:8080/api/v1/health
- **监控面板**: http://localhost:3000 (Grafana)
- **链路追踪**: http://localhost:16686 (Jaeger)
### 社区支持
- **GitHub Issues**: 提交问题和建议
- **Wiki**: 查看详细技术文档
- **讨论区**: 参与技术讨论
## 🔄 文档更新
本文档会持续更新,如果您发现任何问题或有改进建议,请:
1. 提交 GitHub Issue
2. 发起 Pull Request
3. 联系维护团队
---
**提示**:建议将此页面加入书签,方便随时查阅相关文档。

View File

@@ -0,0 +1,338 @@
# TYAPI 生产环境部署指南
## 🎯 **部署架构概览**
```
┌─────────────────────────────────────────────────────────────┐
│ 生产环境架构 │
├─────────────────────────────────────────────────────────────┤
│ Nginx (80/443) ──► TYAPI App (8080) ──► PostgreSQL (5432) │
│ │ │ │ │
│ │ └──► Redis (6379) │ │
│ │ └──► Jaeger (4317) │ │
│ └──► Jaeger UI (16686) │ │
└─────────────────────────────────────────────────────────────┘
私有镜像仓库: docker-registry.tianyuanapi.com
```
## 📋 **部署清单**
### ✅ **已创建的文件**
- `Dockerfile` - 多阶段构建的生产级镜像
- `docker-compose.prod.yml` - 生产环境服务编排
- `.dockerignore` - Docker 构建忽略文件
- `deployments/docker/nginx.conf` - Nginx 反向代理配置
- `.env.production` - 生产环境配置模板
- `scripts/deploy.sh` - Linux/macOS 部署脚本
- `scripts/deploy.ps1` - Windows PowerShell 部署脚本
- `Makefile` - 新增生产环境相关命令
### 🛠 **服务组件**
1. **PostgreSQL** - 主数据库 (生产优化配置)
2. **Redis** - 缓存和会话存储 (密码保护)
3. **TYAPI App** - 主应用程序 (生产模式)
4. **Jaeger** - 链路追踪 (生产级配置)
5. **Nginx** - 反向代理和负载均衡
6. **Prometheus** - 监控数据收集和存储
7. **Grafana** - 监控数据可视化仪表盘
8. **MinIO** - S3 兼容对象存储服务
9. **pgAdmin** - PostgreSQL 数据库管理工具
## 🚀 **快速部署步骤**
### 1⃣ **环境准备**
```bash
# 确保服务器已安装
- Docker 20.10+
- Docker Compose 2.0+
- Git (可选)
# 检查版本
docker --version
docker-compose --version
```
### 2⃣ **获取代码**
```bash
# 克隆项目到服务器
git clone <your-repo-url> tyapi-server
cd tyapi-server
# 或直接上传项目文件
```
### 3⃣ **配置环境变量**
```bash
# 复制配置模板
cp .env.production .env
# 编辑配置文件
nano .env
```
**必须修改的关键配置:**
```bash
# 数据库配置
DB_PASSWORD=your_secure_database_password_here
# Redis配置
REDIS_PASSWORD=your_secure_redis_password_here
# JWT密钥 (至少32位)
JWT_SECRET=your_super_secure_jwt_secret_key_for_production_at_least_32_chars
# Grafana管理员配置
GRAFANA_ADMIN_PASSWORD=your_secure_grafana_password_here
# MinIO对象存储配置
MINIO_ROOT_PASSWORD=your_secure_minio_password_here
# pgAdmin数据库管理配置
PGADMIN_PASSWORD=your_secure_pgadmin_password_here
# 短信服务配置
SMS_ACCESS_KEY_ID=your_sms_access_key_id
SMS_ACCESS_KEY_SECRET=your_sms_access_key_secret
SMS_SIGN_NAME=your_sms_sign_name
SMS_TEMPLATE_CODE=your_sms_template_code
```
### 4⃣ **执行部署**
#### **Linux/macOS:**
```bash
# 给脚本执行权限
chmod +x scripts/deploy.sh
# 部署指定版本
./scripts/deploy.sh v1.0.0
# 或部署最新版本
./scripts/deploy.sh
```
#### **Windows:**
```powershell
# 执行部署脚本
.\scripts\deploy.ps1 -Version "v1.0.0"
# 或使用Makefile
make docker-build-prod
make docker-push-prod
make prod-up
```
## 📊 **部署脚本功能**
### 🔄 **自动化流程**
1. **环境检查** - 验证 Docker、docker-compose 等工具
2. **配置验证** - 检查关键配置项的安全性
3. **镜像构建** - 构建生产级 Docker 镜像
4. **镜像推送** - 推送到私有 Registry
5. **服务部署** - 启动所有生产服务
6. **健康检查** - 验证服务运行状态
7. **信息展示** - 显示访问地址和管理命令
### 🛡 **安全特性**
- **非 root 用户运行** - 容器内使用专用用户
- **资源限制** - CPU 和内存使用限制
- **健康检查** - 自动重启异常服务
- **网络隔离** - 独立的 Docker 网络
- **密码保护** - 数据库和 Redis 强制密码
- **SSL 就绪** - Nginx HTTPS 配置模板
## 🎛 **管理命令**
### **通过 Makefile 管理:**
```bash
# 构建生产镜像
make docker-build-prod
# 推送到Registry
make docker-push-prod
# 启动生产服务
make prod-up
# 停止生产服务
make prod-down
# 查看服务状态
make prod-status
# 查看实时日志
make prod-logs
```
### **通过 docker-compose 管理:**
```bash
# 启动所有服务
docker-compose -f docker-compose.prod.yml up -d
# 停止所有服务
docker-compose -f docker-compose.prod.yml down
# 查看服务状态
docker-compose -f docker-compose.prod.yml ps
# 查看日志
docker-compose -f docker-compose.prod.yml logs -f
# 重启特定服务
docker-compose -f docker-compose.prod.yml restart tyapi-app
```
## 🌐 **服务访问地址**
部署成功后,可以通过以下地址访问服务:
### **核心服务**
- **API 服务**: `http://your-server:8080`
- **API 文档**: `http://your-server:8080/swagger/index.html`
- **健康检查**: `http://your-server:8080/health`
### **监控和追踪**
- **Grafana 仪表盘**: `http://your-server:3000`
- **Prometheus 监控**: `http://your-server:9090`
- **Jaeger 链路追踪**: `http://your-server:16686`
### **管理工具**
- **pgAdmin 数据库管理**: `http://your-server:5050`
- **MinIO 对象存储**: `http://your-server:9000` (API)
- **MinIO 控制台**: `http://your-server:9001` (管理界面)
### **通过 Nginx 代理访问**
如果启用了 Nginx也可以通过以下路径访问
- **根目录**: `http://your-server/` → 重定向到 API 文档
- **API 服务**: `http://your-server/api/`
- **Grafana**: `http://your-server/grafana/`
- **Prometheus**: `http://your-server/prometheus/`
- **Jaeger**: `http://your-server/jaeger/`
- **MinIO API**: `http://your-server/minio/`
- **MinIO 控制台**: `http://your-server/minio-console/`
- **pgAdmin**: `http://your-server/pgadmin/`
## 🔍 **监控和故障排除**
### **查看日志:**
```bash
# 查看应用日志
docker-compose -f docker-compose.prod.yml logs tyapi-app
# 查看数据库日志
docker-compose -f docker-compose.prod.yml logs postgres
# 查看所有服务日志
docker-compose -f docker-compose.prod.yml logs
```
### **健康检查:**
```bash
# 检查服务状态
curl -f http://localhost:8080/health
# 检查Jaeger
curl -f http://localhost:16686
# 查看容器状态
docker ps
```
### **常见问题:**
1. **镜像拉取失败**
```bash
# 检查Registry连接
docker pull docker-registry.tianyuanapi.com/tyapi-server:latest
```
2. **数据库连接失败**
```bash
# 检查数据库配置
docker-compose -f docker-compose.prod.yml logs postgres
```
3. **应用启动失败**
```bash
# 查看应用日志
docker-compose -f docker-compose.prod.yml logs tyapi-app
```
## 🔧 **配置优化**
### **性能调优:**
1. **数据库优化** - 根据服务器配置调整 PostgreSQL 参数
2. **Redis 优化** - 配置内存和持久化策略
3. **应用调优** - 调整连接池大小和超时时间
4. **Nginx 优化** - 配置缓存和压缩
### **扩展配置:**
1. **HTTPS 配置** - 添加 SSL 证书支持
2. **域名配置** - 绑定自定义域名
3. **备份策略** - 配置数据库自动备份
4. **日志收集** - 集成 ELK 或其他日志系统
## 🔄 **版本更新**
### **零停机更新:**
```bash
# 构建新版本
./scripts/deploy.sh v1.1.0
# 或渐进式更新
docker-compose -f docker-compose.prod.yml pull tyapi-app
docker-compose -f docker-compose.prod.yml up -d --no-deps tyapi-app
```
### **回滚操作:**
```bash
# 回滚到指定版本
docker tag docker-registry.tianyuanapi.com/tyapi-server:v1.0.0 \
docker-registry.tianyuanapi.com/tyapi-server:latest
docker-compose -f docker-compose.prod.yml up -d --no-deps tyapi-app
```
## 📞 **技术支持**
如果在部署过程中遇到问题,请:
1. 检查本文档的故障排除部分
2. 查看服务日志定位问题
3. 确认配置文件的正确性
4. 验证网络和防火墙设置
---
**部署前请务必:**
- ✅ 测试配置文件
- ✅ 备份现有数据
- ✅ 验证 Registry 访问
- ✅ 确认服务器资源充足

View File

@@ -0,0 +1,338 @@
# TYAPI 项目链路追踪指南
## 概述
本项目使用 **Jaeger** 进行分布式链路追踪,通过 **OpenTelemetry** 标准实现数据收集,并在 **Grafana** 中进行可视化展示。
## 架构说明
```
应用程序 -> OpenTelemetry -> Jaeger -> Grafana 可视化
```
- **应用程序**:使用 OpenTelemetry Go SDK 生成链路追踪数据
- **Jaeger**:收集、存储和查询链路追踪数据
- **Grafana**:提供链路追踪数据的可视化界面
## 快速启动
### 1. 启动基础设施服务
```bash
# 启动所有服务包括Jaeger
docker-compose -f docker-compose.dev.yml up -d
# 检查服务状态
docker-compose -f docker-compose.dev.yml ps
```
### 2. 验证服务启动
- **Jaeger UI**: http://localhost:16686
- **Grafana**: http://localhost:3000 (admin/Gf7nB3xM9cV6pQ2w)
- **应用程序**: http://localhost:8080
### 3. 启动应用程序
```bash
# 确保配置正确
make run
```
## 配置说明
### 应用配置config.yaml
```yaml
monitoring:
metrics_enabled: true
metrics_port: "9090"
tracing_enabled: true # 启用链路追踪
tracing_endpoint: "http://localhost:4317" # OTLP gRPC 端点
sample_rate: 0.1 # 采样率10%
```
### Jaeger 配置
- **UI 端口**: 16686
- **OTLP gRPC**: 4317
- **OTLP HTTP**: 4318
- **传统 gRPC**: 14250
- **传统 HTTP**: 14268
### 采样策略
项目使用智能采样策略(配置在 `deployments/docker/jaeger-sampling.json`
- **默认采样率**: 10%
- **健康检查接口**: 1%(减少噪音)
- **关键业务接口**: 50%(如注册、登录)
- **错误请求**: 100%(所有 4xx 和 5xx 错误)
#### 错误优先采样
系统实现了错误优先采样策略,确保所有出现错误的请求都被 100%采样记录,即使它们不在高采样率的关键业务接口中。这包括:
- 所有返回 4xx 状态码的客户端错误(如 404、400、403 等)
- 所有返回 5xx 状态码的服务器错误(如 500、503 等)
- 所有抛出异常的数据库操作
- 所有失败的缓存操作
- 所有失败的外部 API 调用
这种策略确保了在出现问题时,相关的链路追踪数据始终可用,便于问题排查和根因分析。
## 使用指南
### 在 Grafana 中查看链路追踪
1. **访问 Grafana**: http://localhost:3000
2. **登录**: admin / Gf7nB3xM9cV6pQ2w
3. **导航**: Dashboard → TYAPI 链路追踪监控
4. **数据源**:
- Jaeger 数据源已自动配置
- URL: http://jaeger:16686
### 在 Jaeger UI 中查看链路追踪
1. **访问 Jaeger**: http://localhost:16686
2. **选择服务**: TYAPI Server
3. **查询追踪**:
- 按时间范围筛选
- 按操作类型筛选
- 按标签筛选
- 按错误状态筛选(使用标签`error=true`
### 生成测试数据
```bash
# 注册用户(会生成链路追踪数据)
curl -X POST http://localhost:8080/api/v1/users/send-sms \
-H "Content-Type: application/json" \
-d '{"phone": "13800138000"}'
# 用户注册
curl -X POST http://localhost:8080/api/v1/users/register \
-H "Content-Type: application/json" \
-d '{
"phone": "13800138000",
"password": "Test123456",
"sms_code": "123456"
}'
# 用户登录
curl -X POST http://localhost:8080/api/v1/users/login \
-H "Content-Type: application/json" \
-d '{
"phone": "13800138000",
"password": "Test123456"
}'
# 生成错误请求(测试错误采样)
curl -X GET http://localhost:8080/api/v1/not-exist-path
```
## 链路追踪功能特性
### 自动追踪的操作
1. **HTTP 请求**: 所有入站 HTTP 请求
2. **数据库查询**: GORM 操作
3. **缓存操作**: Redis 读写
4. **外部调用**: 短信服务等
5. **业务逻辑**: 用户注册、登录等
### 追踪数据包含的信息
- **请求信息**: URL、HTTP 方法、状态码
- **时间信息**: 开始时间、持续时间
- **错误信息**: 异常堆栈和错误消息
- **上下文信息**: TraceID、SpanID
- **自定义标签**: 服务名、操作类型等
### TraceID 传播
应用程序会在 HTTP 响应头中返回 TraceID
```
X-Trace-ID: 4bf92f3577b34da6a3ce929d0e0e4736
```
通过这个 ID可以在日志系统和 Jaeger UI 中关联同一请求的所有信息。
## 错误追踪与分析
### 错误链路的查询
在 Jaeger UI 中,可以通过以下方式查询错误链路:
1. 在查询界面选择"Tags"标签
2. 添加条件:`error=true``operation.type=error`
3. 点击"Find Traces"按钮
这将显示所有被标记为错误的链路追踪数据,包括:
- 所有 HTTP 4xx/5xx 错误
- 所有数据库操作错误
- 所有缓存操作错误
- 所有外部 API 调用错误
### 错误根因分析
链路追踪系统记录了错误发生的完整上下文,包括:
- 错误发生的具体操作
- 错误的详细信息和堆栈
- 错误发生前的所有操作序列
- 相关的请求参数和环境信息
通过这些信息,可以快速定位问题根源,而不需要在多个日志文件中搜索。
## 性能优化建议
### 采样率配置
- **开发环境**: 10-50%(便于调试)
- **测试环境**: 5-10%
- **生产环境**: 1-5%(减少性能影响)
- **错误请求**: 始终保持 100%(所有环境)
### 批处理配置
生产环境建议使用批处理导出器:
```yaml
monitoring:
tracing_enabled: true
tracing_endpoint: "http://jaeger:4317"
sample_rate: 0.01 # 生产环境1%采样率
```
## 故障排除
### 常见问题
1. **链路追踪数据未显示**
- 检查应用配置中 `tracing_enabled: true`
- 确认 Jaeger 服务正常运行
- 检查网络连接和端口
2. **Grafana 无法连接 Jaeger**
- 确认 Jaeger 数据源配置正确
- 检查容器网络连接
- 验证 Jaeger UI 可访问
3. **性能影响过大**
- 降低采样率
- 检查批处理配置
- 监控内存和 CPU 使用率
4. **错误请求未被 100%采样**
- 检查 Jaeger 采样配置中是否包含`"operation": "error"`的配置
- 确认中间件正确设置了错误标记
- 验证错误处理逻辑是否正确调用了`SetSpanError`方法
### 调试命令
```bash
# 检查Jaeger健康状态
curl http://localhost:14269/health
# 检查容器日志
docker logs tyapi-jaeger
# 检查应用追踪配置
curl http://localhost:8080/health
```
## 监控仪表板
### 默认仪表板
项目提供了预配置的 Grafana 仪表板:
- **TYAPI 链路追踪监控**: 展示追踪概览和关键指标
- **HTTP 请求分析**: 请求速率和延迟分布
- **服务依赖图**: 服务间调用关系
- **错误分析**: 错误率和错误类型分布
### 自定义仪表板
可以根据业务需求创建自定义仪表板:
1. 在 Grafana 中创建新仪表板
2. 添加 Jaeger 查询面板
3. 配置告警规则
4. 导出仪表板配置
## 生产环境部署
### 环境变量配置
```bash
export JAEGER_ENDPOINT="http://jaeger:4317"
export TRACING_SAMPLE_RATE="0.01"
```
### Kubernetes 部署
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
config.yaml: |
monitoring:
tracing_enabled: true
tracing_endpoint: "http://jaeger-collector:4317"
sample_rate: 0.01
```
## 扩展功能
### 自定义追踪
```go
// 在业务代码中添加自定义追踪
ctx, span := tracer.StartSpan(ctx, "custom-operation")
defer span.End()
// 添加自定义属性
tracer.AddSpanAttributes(span,
attribute.String("user.id", userID),
attribute.String("operation.type", "business"),
)
// 记录错误
if err != nil {
tracer.SetSpanError(span, err)
}
```
### 业务指标集成
链路追踪数据可以与业务指标结合:
- 用户行为分析
- 性能瓶颈定位
- 错误率监控
- 服务依赖分析
## 最佳实践
1. **合理设置采样率**: 平衡数据完整性和性能影响
2. **添加有意义的标签**: 便于后续查询和分析
3. **处理敏感信息**: 避免在追踪数据中记录密码等敏感信息
4. **监控存储空间**: 定期清理过期的追踪数据
5. **设置告警规则**: 对异常追踪模式设置告警
6. **错误优先采样**: 确保所有错误请求都被记录,无论采样率如何
7. **关联日志系统**: 在日志中包含 TraceID便于关联查询
## 参考资料
- [OpenTelemetry Go 文档](https://opentelemetry.io/docs/instrumentation/go/)
- [Jaeger 官方文档](https://www.jaegertracing.io/docs/)
- [Grafana Jaeger 数据源](https://grafana.com/docs/grafana/latest/datasources/jaeger/)

View File

@@ -1,102 +0,0 @@
# 📚 TYAPI Server 文档中心
欢迎使用 TYAPI Server 文档中心!我们已将原本的使用指南拆分为多个专题文档,方便您按需查阅。
## 📋 文档导航
### 🚀 [快速开始指南](./快速开始指南.md)
- 前置要求
- 一键启动
- 验证安装
- 访问管理界面
### 🔧 [环境搭建指南](./环境搭建指南.md)
- 开发环境配置
- 生产环境配置
- 服务配置说明
- 常见配置问题
### 👨‍💻 [开发指南](./开发指南.md)
- 项目结构理解
- 开发流程
- 测试编写
- 调试技巧
- 代码规范
### 🌐 [API使用指南](./API使用指南.md)
- 认证机制
- 用户管理 API
- 响应格式
- HTTP 状态码
- API 测试
### 🚀 [部署指南](./部署指南.md)
- Docker 部署
- Kubernetes 部署
- 云平台部署
- 负载均衡配置
- 监控部署
### 🔍 [故障排除指南](./故障排除指南.md)
- 常见问题
- 日志分析
- 性能问题
- 紧急响应流程
### 📋 [最佳实践指南](./最佳实践指南.md)
- 开发最佳实践
- 安全最佳实践
- 性能最佳实践
- 运维最佳实践
- 团队协作
## 🎯 快速索引
### 新手入门
1. [快速开始指南](./快速开始指南.md) - 5分钟快速体验
2. [环境搭建指南](./环境搭建指南.md) - 配置开发环境
3. [开发指南](./开发指南.md) - 开始第一个功能
### 日常开发
- [API使用指南](./API使用指南.md) - API 调用参考
- [开发指南](./开发指南.md) - 开发流程和规范
- [故障排除指南](./故障排除指南.md) - 解决常见问题
### 生产部署
- [部署指南](./部署指南.md) - 生产环境部署
- [最佳实践指南](./最佳实践指南.md) - 运维最佳实践
- [故障排除指南](./故障排除指南.md) - 生产问题排查
## 🔗 相关文档
### 技术文档
- [架构文档](./ARCHITECTURE.md) - 系统架构设计
- [API 规范](http://localhost:8080/swagger/) - 在线 API 文档
### 项目文档
- [README](../README.md) - 项目介绍
- [更新日志](../CHANGELOG.md) - 版本变更记录
## 📞 获取帮助
### 在线资源
- **Swagger UI**: http://localhost:8080/swagger/
- **健康检查**: http://localhost:8080/api/v1/health
- **监控面板**: http://localhost:3000 (Grafana)
### 社区支持
- **GitHub Issues**: 提交问题和建议
- **Wiki**: 查看详细技术文档
- **讨论区**: 参与技术讨论
## 🔄 文档更新
本文档会持续更新,如果您发现任何问题或有改进建议,请:
1. 提交 GitHub Issue
2. 发起 Pull Request
3. 联系维护团队
---
**提示**:建议将此页面加入书签,方便随时查阅相关文档。