Files
tyapi-server/docs/最佳实践指南.md

537 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 📋 最佳实践指南
## 开发最佳实践
### 1. 代码规范
```bash
# 格式化代码
gofmt -w .
goimports -w .
# 代码检查
golangci-lint run
# 生成文档
godoc -http=:6060
```
**编码标准**
- 遵循 Go 官方编码规范
- 使用有意义的变量和函数名
- 保持函数简洁,单一职责
- 添加必要的注释和文档
### 2. Git 工作流
```bash
# 功能分支开发
git checkout -b feature/user-profile
git add .
git commit -m "feat: add user profile management"
git push origin feature/user-profile
# 代码审查后合并
git checkout main
git merge feature/user-profile
git push origin main
```
**提交规范**
- `feat`: 新功能
- `fix`: 修复问题
- `docs`: 文档更新
- `style`: 代码格式修改
- `refactor`: 代码重构
- `test`: 测试相关
- `chore`: 构建过程或辅助工具的变动
### 3. 测试策略
```bash
# 运行所有测试
make test
# 只运行单元测试
go test ./internal/domains/...
# 运行集成测试
go test -tags=integration ./test/integration/...
# 生成覆盖率报告
make test-coverage
open coverage.html
```
**测试金字塔**
- **单元测试**70% - 测试单个函数/方法
- **集成测试**20% - 测试模块间交互
- **端到端测试**10% - 测试完整用户流程
### 4. 错误处理
```go
// 统一错误处理
func (s *userService) CreateUser(ctx context.Context, req *dto.CreateUserRequest) (*dto.UserResponse, error) {
// 参数验证
if err := req.Validate(); err != nil {
return nil, errors.NewValidationError("invalid request", err)
}
// 业务逻辑
user, err := s.userRepo.Create(ctx, req.ToEntity())
if err != nil {
s.logger.Error("failed to create user", zap.Error(err))
return nil, errors.NewInternalError("failed to create user")
}
return dto.ToUserResponse(user), nil
}
```
### 5. 日志记录
```go
// 结构化日志
logger.Info("user created successfully",
zap.String("user_id", user.ID),
zap.String("username", user.Username),
zap.Duration("duration", time.Since(start)))
// 错误日志
logger.Error("database connection failed",
zap.Error(err),
zap.String("host", dbHost),
zap.String("database", dbName))
```
**日志级别使用**
- `DEBUG`: 详细调试信息
- `INFO`: 一般信息记录
- `WARN`: 警告信息
- `ERROR`: 错误信息
- `FATAL`: 致命错误
## 安全最佳实践
### 1. 认证和授权
```go
// JWT 令牌配置
type JWTConfig struct {
Secret string `yaml:"secret"`
AccessTokenTTL time.Duration `yaml:"access_token_ttl"`
RefreshTokenTTL time.Duration `yaml:"refresh_token_ttl"`
Issuer string `yaml:"issuer"`
}
// 密码加密
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
```
### 2. 输入验证
```go
// 请求验证
type CreateUserRequest struct {
Username string `json:"username" validate:"required,min=3,max=20,alphanum"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8,containsany=!@#$%^&*"`
}
func (r *CreateUserRequest) Validate() error {
validate := validator.New()
return validate.Struct(r)
}
```
### 3. SQL 注入防护
```go
// 使用参数化查询
func (r *userRepository) FindByEmail(ctx context.Context, email string) (*entities.User, error) {
var user entities.User
err := r.db.WithContext(ctx).
Where("email = ?", email). // 参数化查询
First(&user).Error
return &user, err
}
```
### 4. HTTPS 配置
```yaml
# 生产环境配置
server:
tls:
enabled: true
cert_file: "/etc/ssl/certs/server.crt"
key_file: "/etc/ssl/private/server.key"
min_version: "1.2"
```
## 性能最佳实践
### 1. 数据库优化
```go
// 连接池配置
func setupDB(config *config.DatabaseConfig) (*gorm.DB, error) {
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
return nil, err
}
sqlDB, err := db.DB()
if err != nil {
return nil, err
}
// 连接池设置
sqlDB.SetMaxOpenConns(config.MaxOpenConns) // 最大连接数
sqlDB.SetMaxIdleConns(config.MaxIdleConns) // 最大空闲连接
sqlDB.SetConnMaxLifetime(config.ConnMaxLifetime) // 连接最大生命周期
return db, nil
}
```
**查询优化**
```sql
-- 添加索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created_at ON users(created_at);
-- 复合索引
CREATE INDEX idx_users_status_created ON users(status, created_at);
```
### 2. 缓存策略
```go
// 多级缓存
type CacheService struct {
localCache cache.Cache
redisCache redis.Client
ttl time.Duration
}
func (c *CacheService) Get(ctx context.Context, key string) (string, error) {
// L1: 本地缓存
if value, ok := c.localCache.Get(key); ok {
return value.(string), nil
}
// L2: Redis 缓存
value, err := c.redisCache.Get(ctx, key).Result()
if err == nil {
c.localCache.Set(key, value, c.ttl)
return value, nil
}
return "", cache.ErrCacheMiss
}
```
### 3. 异步处理
```go
// 使用工作池处理任务
type WorkerPool struct {
workers int
jobQueue chan Job
wg sync.WaitGroup
}
func (wp *WorkerPool) Start() {
for i := 0; i < wp.workers; i++ {
wp.wg.Add(1)
go wp.worker()
}
}
func (wp *WorkerPool) Submit(job Job) {
wp.jobQueue <- job
}
```
### 4. 内存管理
```go
// 对象池减少GC压力
var bufferPool = sync.Pool{
New: func() interface{} {
return make([]byte, 4096)
},
}
func processData(data []byte) error {
buffer := bufferPool.Get().([]byte)
defer bufferPool.Put(buffer)
// 使用buffer处理数据
return nil
}
```
## 运维最佳实践
### 1. 监控告警
**关键指标监控**
```yaml
# Prometheus 告警规则
groups:
- name: tyapi-server
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.01
labels:
severity: critical
annotations:
summary: "High error rate detected"
- alert: HighResponseTime
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 0.5
labels:
severity: warning
annotations:
summary: "High response time detected"
```
### 2. 备份策略
```bash
#!/bin/bash
# 数据库备份脚本
BACKUP_DIR="/backups/tyapi"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/tyapi_backup_$DATE.sql"
# 创建备份
pg_dump -h localhost -U postgres tyapi_prod > $BACKUP_FILE
# 压缩备份文件
gzip $BACKUP_FILE
# 保留最近7天的备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
# 上传到云存储
aws s3 cp $BACKUP_FILE.gz s3://tyapi-backups/
```
### 3. 配置管理
```yaml
# 生产环境配置模板
server:
port: 8080
mode: release
read_timeout: 30s
write_timeout: 30s
database:
host: ${DB_HOST}
port: ${DB_PORT}
user: ${DB_USER}
password: ${DB_PASSWORD}
name: ${DB_NAME}
max_open_conns: 100
max_idle_conns: 10
redis:
host: ${REDIS_HOST}
port: ${REDIS_PORT}
password: ${REDIS_PASSWORD}
pool_size: 10
security:
jwt_secret: ${JWT_SECRET}
bcrypt_cost: 12
logging:
level: info
format: json
output: stdout
```
### 4. 容器化最佳实践
```dockerfile
# 多阶段构建 Dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/api
FROM alpine:3.18
# 安全加固
RUN adduser -D -s /bin/sh appuser
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/
COPY --from=builder /app/main .
COPY --from=builder /app/config.yaml .
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/api/v1/health || exit 1
CMD ["./main"]
```
## 团队协作最佳实践
### 1. 代码审查
**审查检查清单**
- [ ] 代码符合项目规范
- [ ] 测试覆盖率充足
- [ ] 错误处理正确
- [ ] 性能影响评估
- [ ] 安全漏洞检查
- [ ] 文档更新
### 2. CI/CD 流程
```yaml
# GitHub Actions 示例
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.21
- name: Run tests
run: |
go test -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
- name: Upload coverage
uses: codecov/codecov-action@v3
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to production
run: |
echo "Deploying to production..."
```
### 3. 文档维护
- **API 文档**:使用 Swagger/OpenAPI 自动生成
- **架构文档**:定期更新系统架构图
- **运维手册**:记录部署和运维流程
- **故障手册**:记录常见问题和解决方案
### 4. 版本管理
```bash
# 语义化版本控制
git tag v1.2.3
# 版本发布流程
git checkout main
git pull origin main
git tag v1.2.3
git push origin v1.2.3
```
**版本号规则**
- **MAJOR**:不兼容的 API 修改
- **MINOR**:向下兼容的功能性新增
- **PATCH**:向下兼容的问题修正
## 扩展性最佳实践
### 1. 微服务拆分
**拆分原则**
- 按业务边界拆分
- 保持服务自治
- 数据库分离
- 独立部署
### 2. 事件驱动架构
```go
// 事件发布
type EventBus interface {
Publish(ctx context.Context, event Event) error
Subscribe(eventType string, handler EventHandler) error
}
// 事件处理
func (h *UserEventHandler) HandleUserCreated(ctx context.Context, event *UserCreatedEvent) error {
// 发送欢迎邮件
return h.emailService.SendWelcomeEmail(ctx, event.UserID)
}
```
### 3. 配置外部化
```go
// 配置热重载
type ConfigManager struct {
config *Config
watchers []ConfigWatcher
}
func (cm *ConfigManager) Watch() {
for {
if changed := cm.checkConfigChange(); changed {
cm.reloadConfig()
cm.notifyWatchers()
}
time.Sleep(time.Second * 10)
}
}
```
### 4. 服务治理
- **服务注册与发现**
- **负载均衡**
- **熔断器**
- **限流器**
- **链路追踪**
通过遵循这些最佳实践,可以确保 TYAPI Server 项目的高质量、高性能和高可维护性。