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" "sync" "syscall" "time" "github.com/lmittmann/tint" "github.com/mattn/go-colorable" ) type Context struct { context.Context log *slog.Logger } func Start() { // 初始化 initLog() env.Init() orm.Init() // 退出信号 osQuit := make(chan os.Signal) signal.Notify(osQuit, os.Interrupt, syscall.SIGTERM) errQuit := make(chan struct{}) defer close(errQuit) // 启动服务 slog.Info("启动服务") ctx, cancel := context.WithCancel(context.Background()) defer cancel() wg := sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() err := startFwdServer(ctx) if err != nil { slog.Error("代理服务发生错误", "err", err) } errQuit <- struct{}{} }() // 等待退出信号 select { case <-osQuit: slog.Info("服务主动退出") case <-errQuit: slog.Warn("服务异常退出") } // 退出服务 cancel() timeout, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() wgCh := utils.ChanWgWait(timeout, &wg) close(wgCh) select { case <-wgCh: slog.Info("服务已退出") case <-timeout.Done(): slog.Warn("退出超时,强制退出") } time.Sleep(3 * time.Second) } func initLog() { 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) } func startFwdServer(ctx context.Context) error { server := fwd.New(nil) go func() { <-ctx.Done() server.Close() }() server.Run() return nil } func startWebServer(ctx context.Context) { }