115 lines
2.5 KiB
Go
115 lines
2.5 KiB
Go
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)
|
||
}()
|
||
|
||
done := make(chan int)
|
||
go func() {
|
||
quit := make(chan os.Signal)
|
||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||
for {
|
||
select {
|
||
case <-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)
|
||
}
|
||
|
||
select {
|
||
case <-ctx.Done():
|
||
logger.Info("timeout of 1 seconds.")
|
||
}
|
||
|
||
logger.Info("Server exited")
|
||
setServerStatusFD(ServerStatusFDStop)
|
||
cancel()
|
||
done <- 1
|
||
return
|
||
}
|
||
}
|
||
}()
|
||
|
||
<-done
|
||
logger.Info("Server done")
|
||
}
|
||
|
||
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)
|
||
}
|