package httpserver import ( "context" "fmt" "net/http" "os" "os/signal" "service/library/configcenter" "service/library/servicediscovery" "syscall" "time" "service/library/logger" ) const ( ServerStatusFDRun = "RUN" // 服务运行中 ServerStatusFDStop = "STOP" // 服务停止 ) func StartHttpServer(srv *http.Server, cfg *configcenter.DefaultConfig, ip string, port int) { quit := make(chan os.Signal) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatal("listen: %v", err) quit <- syscall.SIGTERM return } }() // 注册服务 go func() { err := registerSD(ip, port) if err != nil { quit <- syscall.SIGTERM return } setServerStatusFD(ServerStatusFDRun) }() <-quit logger.Info("Shutdown Server ...") if err := servicediscovery.DeRegister(ip, port); err != nil { logger.Fatal("DeRegister fail: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { logger.Fatal("Server Shutdown:", err) } select { case <-ctx.Done(): logger.Info("timeout of 1 seconds.") } logger.Info("Server exited") setServerStatusFD(ServerStatusFDStop) } func registerSD(ip string, port int) error { // 要等服务起来后再注册到consul,否则会有问题 // 方法:调用 healthcheck idx := 0 timer := time.NewTimer(time.Second * 5) timerRetry := time.NewTicker(time.Second * 1) for { select { case <-timer.C: return fmt.Errorf("registerSD fail, ip: %v, port: %v", ip, port) case <-timerRetry.C: idx += 1 resp, err := http.Get(fmt.Sprintf("http://%s:%v/healthcheck", ip, port)) if err != nil { logger.Error("healthcheck fail, err: %v", err) continue } if resp.StatusCode == http.StatusOK { if err := servicediscovery.Register(ip, port); err != nil { logger.Error("registerSD fail, ip: %v, port: %v, err: %v", ip, port, err) continue } return nil } } } } func setServerStatusFD(status string) { os.Setenv("SERVER_STATUS_FD", status) fmt.Println(os.Getenv("SERVER_STATUS_FD")) return serverStatusFdPath := "/Users/erwin/SERVER_STATUS_FD" file, err := os.OpenFile(serverStatusFdPath, os.O_RDWR|os.O_CREATE, 0666) if err != nil { logger.Info("OpenFile fail, p: %v, err: %v", serverStatusFdPath, err) return } defer func() { _ = file.Close() }() err = file.Truncate(0) if err != nil { logger.Info("file Truncate fail, p: %v, err: %v", serverStatusFdPath, err) return } _, err = file.WriteString(status) if err != nil { logger.Info("file WriteString fail, p: %v, v: %v, err: %v", serverStatusFdPath, status, err) return } logger.Info("SetServerStatusFD success: %v", status) }