init
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"skeleton/config"
|
||||
"skeleton/database"
|
||||
"skeleton/middlewares"
|
||||
"skeleton/models"
|
||||
"skeleton/routes"
|
||||
_ "skeleton/routes/rest" // 导入触发 init() 自动注册路由
|
||||
"skeleton/utils"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/MUKE-coder/gin-docs/gindocs"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 加载配置
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
log.Fatal("加载配置失败:", err)
|
||||
}
|
||||
|
||||
// 初始化日志系统
|
||||
if err := middlewares.InitLogger(&cfg.Logger); err != nil {
|
||||
log.Fatal("初始化日志系统失败:", err)
|
||||
}
|
||||
|
||||
// 初始化JWT配置
|
||||
middlewares.InitJWT(cfg.JWT.Secret, cfg.JWT.ExpireHours, cfg.JWT.Issuer)
|
||||
|
||||
// 确保在程序退出时同步日志缓冲区
|
||||
defer middlewares.Sync()
|
||||
|
||||
// 使用结构化日志记录启动信息
|
||||
zap.L().Info("应用程序启动",
|
||||
zap.String("version", cfg.App.Version),
|
||||
zap.String("environment", cfg.App.Environment),
|
||||
zap.Bool("debug", cfg.App.Debug),
|
||||
)
|
||||
|
||||
// 初始化时区
|
||||
if err := utils.InitTimezone(cfg.App.Timezone); err != nil {
|
||||
zap.L().Warn("时区初始化警告", zap.Error(err))
|
||||
} else {
|
||||
zap.L().Info("时区设置成功", zap.String("timezone", cfg.App.Timezone))
|
||||
}
|
||||
|
||||
// 初始化数据库
|
||||
if err := database.Init(&cfg.Database, zap.L()); err != nil {
|
||||
zap.L().Fatal("数据库初始化失败", zap.Error(err))
|
||||
}
|
||||
|
||||
// 初始化Redis服务
|
||||
if err := database.InitRedis(cfg, zap.L()); err != nil {
|
||||
zap.L().Fatal("Redis服务初始化失败", zap.Error(err))
|
||||
}
|
||||
|
||||
// 设置路由
|
||||
r := routes.SetupRoutes(cfg)
|
||||
|
||||
// 挂载接口文档
|
||||
gindocs.Mount(r, database.GetDB(), gindocs.Config{
|
||||
Title: "Skeleton API",
|
||||
Description: "Skeleton API documentation",
|
||||
Version: cfg.App.Version,
|
||||
Models: []interface{}{
|
||||
models.User{},
|
||||
},
|
||||
})
|
||||
|
||||
// 创建HTTP服务器
|
||||
srv := &http.Server{
|
||||
Addr: cfg.GetAddr(),
|
||||
Handler: r,
|
||||
}
|
||||
|
||||
// 启动服务器
|
||||
go func() {
|
||||
zap.L().Info("HTTP 服务器启动",
|
||||
zap.String("address", cfg.GetAddr()),
|
||||
zap.String("version", cfg.App.Version),
|
||||
zap.String("environment", cfg.App.Environment),
|
||||
zap.Bool("debug", cfg.App.Debug),
|
||||
)
|
||||
|
||||
fmt.Printf("服务器启动在: %s (版本: %s, 环境: %s)\n",
|
||||
cfg.GetAddr(), cfg.App.Version, cfg.App.Environment)
|
||||
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
zap.L().Fatal("启动服务器失败", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
// 等待关闭信号
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
|
||||
zap.L().Info("正在关闭服务器...")
|
||||
gracefulShutdown(srv)
|
||||
}
|
||||
|
||||
// gracefulShutdown 执行优雅关闭
|
||||
func gracefulShutdown(srv *http.Server) {
|
||||
// 设置关闭超时
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// 1. 关闭HTTP服务器
|
||||
zap.L().Info("正在关闭HTTP服务器...")
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
zap.L().Error("HTTP服务器关闭失败", zap.Error(err))
|
||||
// 强制关闭
|
||||
if err := srv.Close(); err != nil {
|
||||
zap.L().Error("强制关闭HTTP服务器失败", zap.Error(err))
|
||||
}
|
||||
} else {
|
||||
zap.L().Info("HTTP服务器关闭成功")
|
||||
}
|
||||
|
||||
// 2. 关闭数据库连接
|
||||
if err := database.Close(); err != nil {
|
||||
zap.L().Error("关闭数据库连接失败", zap.Error(err))
|
||||
} else {
|
||||
zap.L().Info("数据库连接已关闭")
|
||||
}
|
||||
|
||||
// 3. 关闭Redis连接
|
||||
if redisClient := database.GetRedisClient(); redisClient != nil {
|
||||
if err := redisClient.Close(); err != nil {
|
||||
zap.L().Error("关闭Redis连接失败", zap.Error(err))
|
||||
} else {
|
||||
zap.L().Info("Redis连接已关闭")
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 同步日志缓冲区
|
||||
middlewares.Sync()
|
||||
|
||||
zap.L().Info("应用程序已优雅关闭")
|
||||
}
|
||||
Reference in New Issue
Block a user