package httpserver import ( "context" "fmt" "net/http" "os" "os/exec" "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) { go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatal("listen: %v", err) return } }() // 注册服务 go func() { err := registerSD(ip, port) if err != nil { logger.Fatal("registerSD: %v", err) return } setServerStatusFD(ServerStatusFDRun) }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-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) if err := srv.Shutdown(ctx); err != nil { logger.Fatal("Server Shutdown:", err) } defer cancel() 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) { serverStatusFdPath := "/app/SERVER_STATUS_FD" cmd := exec.Command("sh", "-c", fmt.Sprintf("echo %s > %s", status, serverStatusFdPath)) err := cmd.Run() if err != nil { logger.Info("run cmd fail, p: %v, err: %v", serverStatusFdPath, err) return } logger.Info("SetServerStatusFD success: %v", status) } func StartOfflineHttpServer(srv *http.Server, cfg *configcenter.DefaultConfig) { go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatal("listen: %v", err) } }() logger.Info("Server %s start at %s", cfg.App.AppName, srv.Addr) quit := make(chan os.Signal) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit logger.Info("Shutdown Server ...") ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server Shutdown:", err) } select { case <-ctx.Done(): logger.Info("timeout of 1 seconds.") } logger.Info("Server exited") }