部署优化
本章节将介绍博客系统的部署方案、性能优化和监控配置。
📋 学习目标
完成本章节后,你将能够:
- 使用Docker容器化应用
- 配置Nginx反向代理
- 实现数据库连接池优化
- 配置日志和监控
- 实现缓存策略
- 进行性能调优
🐳 Docker 部署
Dockerfile
创建 Dockerfile:
dockerfile
# 构建阶段
FROM golang:1.21-alpine AS builder
WORKDIR /app
# 复制go mod文件
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -o blog-system cmd/server/main.go
# 运行阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
ENV TZ=Asia/Shanghai
WORKDIR /app
# 从构建阶段复制二进制文件
COPY --from=builder /app/blog-system .
# 复制配置文件
COPY --from=builder /app/config ./config
EXPOSE 8080
CMD ["./blog-system"]Docker Compose
创建 docker-compose.yml:
yaml
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- GIN_MODE=release
depends_on:
- mysql
- redis
volumes:
- ./uploads:/app/uploads
- ./logs:/app/logs
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: blog_db
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
volumes:
mysql_data:
redis_data:🔧 Nginx 配置
创建 nginx.conf:
nginx
upstream blog_backend {
server app:8080;
}
server {
listen 80;
server_name your-domain.com;
# 静态文件
location /uploads/ {
alias /app/uploads/;
expires 30d;
}
# API代理
location /api/ {
proxy_pass http://blog_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript;
}⚡ 性能优化
数据库连接池
go
func InitDB(dsn string) (*gorm.DB, error) {
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
return nil, err
}
sqlDB, err := db.DB()
if err != nil {
return nil, err
}
// 连接池配置
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
return db, nil
}Redis 缓存
go
import "github.com/go-redis/redis/v8"
func InitRedis(addr, password string, db int) (*redis.Client, error) {
rdb := redis.NewClient(&redis.Options{
Addr: addr,
Password: password,
DB: db,
})
ctx := context.Background()
_, err := rdb.Ping(ctx).Result()
if err != nil {
return nil, err
}
return rdb, nil
}缓存文章列表
go
func (s *ArticleServiceImpl) List(filter ArticleFilter) ([]Article, int64, error) {
// 生成缓存key
cacheKey := fmt.Sprintf("articles:list:%v", filter)
// 尝试从缓存获取
var cached []Article
if err := redis.Get(ctx, cacheKey).Scan(&cached); err == nil {
return cached, 0, nil
}
// 从数据库获取
articles, total, err := s.articleRepo.List(filter)
if err != nil {
return nil, 0, err
}
// 存入缓存
redis.Set(ctx, cacheKey, articles, time.Hour)
return articles, total, nil
}📊 日志配置
结构化日志
go
import "go.uber.org/zap"
func InitLogger() (*zap.Logger, error) {
config := zap.NewProductionConfig()
config.OutputPaths = []string{"stdout", "./logs/app.log"}
config.ErrorOutputPaths = []string{"stderr", "./logs/error.log"}
return config.Build()
}日志中间件
go
func LoggingMiddleware(logger *zap.Logger) gin.HandlerFunc {
return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
logger.Info("HTTP Request",
zap.String("method", param.Method),
zap.String("path", param.Path),
zap.Int("status", param.StatusCode),
zap.Duration("latency", param.Latency),
zap.String("ip", param.ClientIP),
)
return ""
})
}📈 监控配置
Prometheus 指标
go
import "github.com/prometheus/client_golang/prometheus"
var (
httpRequestsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
[]string{"method", "endpoint", "status"},
)
)
func init() {
prometheus.MustRegister(httpRequestsTotal)
}健康检查
go
func HealthCheck(c *gin.Context) {
// 检查数据库
if err := db.Ping(); err != nil {
c.JSON(http.StatusServiceUnavailable, gin.H{
"status": "unhealthy",
"error": "database connection failed",
})
return
}
// 检查Redis
if err := redis.Ping(ctx).Err(); err != nil {
c.JSON(http.StatusServiceUnavailable, gin.H{
"status": "unhealthy",
"error": "redis connection failed",
})
return
}
c.JSON(http.StatusOK, gin.H{
"status": "healthy",
})
}🚀 部署步骤
1. 构建镜像
bash
docker build -t blog-system:latest .2. 启动服务
bash
docker-compose up -d3. 查看日志
bash
docker-compose logs -f app4. 数据库迁移
bash
docker-compose exec app ./blog-system migrate💡 最佳实践
1. 安全配置
- 使用HTTPS
- 配置防火墙
- 限制数据库访问
- 使用环境变量存储敏感信息
2. 性能优化
- 启用Gzip压缩
- 使用CDN加速静态资源
- 配置缓存策略
- 优化数据库查询
3. 监控告警
- 配置应用监控
- 设置告警规则
- 定期检查日志
- 监控系统资源
📚 相关资源
🎉 部署优化完成! 恭喜你完成了整个博客系统的开发!
