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

11 KiB
Raw Blame History

📋 最佳实践指南

开发最佳实践

1. 代码规范

# 格式化代码
gofmt -w .
goimports -w .

# 代码检查
golangci-lint run

# 生成文档
godoc -http=:6060

编码标准

  • 遵循 Go 官方编码规范
  • 使用有意义的变量和函数名
  • 保持函数简洁,单一职责
  • 添加必要的注释和文档

2. Git 工作流

# 功能分支开发
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. 测试策略

# 运行所有测试
make test

# 只运行单元测试
go test ./internal/domains/...

# 运行集成测试
go test -tags=integration ./test/integration/...

# 生成覆盖率报告
make test-coverage
open coverage.html

测试金字塔

  • 单元测试70% - 测试单个函数/方法
  • 集成测试20% - 测试模块间交互
  • 端到端测试10% - 测试完整用户流程

4. 错误处理

// 统一错误处理
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. 日志记录

// 结构化日志
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. 认证和授权

// 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. 输入验证

// 请求验证
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 注入防护

// 使用参数化查询
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 配置

# 生产环境配置
server:
    tls:
        enabled: true
        cert_file: "/etc/ssl/certs/server.crt"
        key_file: "/etc/ssl/private/server.key"
        min_version: "1.2"

性能最佳实践

1. 数据库优化

// 连接池配置
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
}

查询优化

-- 添加索引
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. 缓存策略

// 多级缓存
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. 异步处理

// 使用工作池处理任务
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. 内存管理

// 对象池减少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. 监控告警

关键指标监控

# 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. 备份策略

#!/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. 配置管理

# 生产环境配置模板
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
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 流程

# 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. 版本管理

# 语义化版本控制
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. 事件驱动架构

// 事件发布
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. 配置外部化

// 配置热重载
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 项目的高质量、高性能和高可维护性。