service/server.go

89 lines
1.7 KiB
Go

package service
import (
"apigo.cc/go/log"
"context"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
// AsyncServer 异步服务实例
type AsyncServer struct {
server *http.Server
listener net.Listener
Addr string
stopChan chan os.Signal
startChan chan bool
}
// AsyncStart 异步启动服务
func AsyncStart() *AsyncServer {
as := &AsyncServer{
startChan: make(chan bool, 1),
stopChan: make(chan os.Signal, 1),
}
go as.start()
<-as.startChan
return as
}
func (as *AsyncServer) start() {
if Config.Listen == "" {
Config.Listen = ":8080" // 默认端口
}
listener, err := net.Listen("tcp", Config.Listen)
if err != nil {
log.DefaultLogger.Error("failed to listen", "addr", Config.Listen, "error", err.Error())
as.startChan <- false
return
}
as.listener = listener
as.Addr = listener.Addr().String()
serverAddr = as.Addr
as.server = &http.Server{
Handler: &routeHandler{},
}
signal.Notify(as.stopChan, os.Interrupt, syscall.SIGTERM)
go func() {
log.DefaultLogger.Info("service starting", "addr", as.Addr)
as.startChan <- true
if err := as.server.Serve(listener); err != nil && err != http.ErrServerClosed {
log.DefaultLogger.Error("server error", "error", err.Error())
}
}()
}
// Stop 停止服务
func (as *AsyncServer) Stop() {
log.DefaultLogger.Info("service stopping")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := as.server.Shutdown(ctx); err != nil {
log.DefaultLogger.Error("server shutdown error", "error", err.Error())
}
log.DefaultLogger.Info("service stopped")
}
// Wait 等待服务结束 (信号监听)
func (as *AsyncServer) Wait() {
<-as.stopChan
as.Stop()
}
// Start 同步启动服务
func Start() {
AsyncStart().Wait()
}