package server import ( "context" "log/slog" "os" "os/signal" "proxy-server/pkg/utils" "proxy-server/server/fwd" "proxy-server/server/pkg/env" "proxy-server/server/pkg/orm" "proxy-server/server/web" "syscall" "time" "github.com/joho/godotenv" "github.com/lmittmann/tint" "github.com/mattn/go-colorable" ) type Context struct { context.Context log *slog.Logger } func Start() { // 初始化 initLog() env.Init() orm.Init() // 启动服务 ctx, cancel := context.WithCancel(context.Background()) defer cancel() errQuit := make(chan error) defer close(errQuit) wg := utils.CountWaitGroup{} wg.Add(1) go func() { defer wg.Done() err := startFwdServer(ctx) if err != nil { slog.Error("代理服务发生错误", "err", err) } errQuit <- err }() // 等待退出信号 osQuit := make(chan os.Signal) signal.Notify(osQuit, os.Interrupt, syscall.SIGTERM) select { case <-osQuit: slog.Info("服务关闭") case <-errQuit: slog.Error("服务异常退出") } // 等待子服务退出 cancel() timeout, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() wgCh := utils.ChanWgWait(timeout, &wg) select { case <-timeout.Done(): slog.Error("关闭超时,强制关闭") case <-wgCh: slog.Info("服务已退出") } } func initLog() { slog.SetLogLoggerLevel(slog.LevelDebug) } func startFwdServer(ctx context.Context) error { server := fwd.New(nil) go func() { <-ctx.Done() server.Close() }() server.Run(ctx) return nil } func startMntServer(ctx context.Context) { } func startWebServer(ctx context.Context) { } func Start2() { defer func() { err := recover() if err != nil { slog.Error("服务由于意外的 panic 导致退出", err) } }() ctx := context.Background() // 初始化环境变量 err := godotenv.Load() if err != nil { slog.Debug("没有本地环境变量文件") } // 配置日志 writer := colorable.NewColorable(os.Stdout) logger := slog.New(tint.NewHandler(writer, &tint.Options{ Level: slog.LevelDebug, ReplaceAttr: func(_ []string, attr slog.Attr) slog.Attr { err, ok := attr.Value.Any().(error) if !ok { return attr } return tint.Err(err) }, })) slog.SetDefault(logger) // 初始化公共组件 orm.Init() // 启动子服务 goCount := 1 errChan := make(chan error, goCount) ctxC, cancel := context.WithCancel(ctx) defer cancel() go web.Start(ctxC, errChan) // go monitor.Start2(ctxC, errChan) slog.Info("服务启动成功") // 监听异常 well := true for i := 0; i < goCount; i++ { err := <-errChan if err != nil { slog.Error("服务异常退出", err) if well { // 第一次出错时取消其他服务 well = false cancel() } } } close(errChan) slog.Info("服务已全部退出") }