gohttp/server/manager.go

209 lines
4.1 KiB
Go
Raw Normal View History

2023-12-07 23:34:34 +08:00
package server
import (
"context"
2025-05-30 18:42:53 +08:00
"errors"
2023-12-07 23:34:34 +08:00
"fmt"
"net"
"net/http"
2023-12-08 22:02:36 +08:00
"strings"
2025-05-30 18:42:53 +08:00
"time"
2023-12-08 22:02:36 +08:00
"bufio"
"io"
2023-12-07 23:34:34 +08:00
2023-12-13 09:22:05 +08:00
"git.pyer.club/kingecg/gohttpd/model"
2023-12-07 23:34:34 +08:00
logger "git.pyer.club/kingecg/gologger"
2025-05-30 21:35:19 +08:00
"git.pyer.club/kingecg/cmux"
2023-12-07 23:34:34 +08:00
)
var ServerManager map[string]*ServerListener = make(map[string]*ServerListener)
2023-12-10 01:08:39 +08:00
func makeMatcher(name string, s *ServerListener) cmux.Matcher {
2023-12-08 22:02:36 +08:00
return func(r io.Reader) bool {
2023-12-10 01:08:39 +08:00
if s.ServerCount() == 1 {
return true
}
2023-12-08 22:02:36 +08:00
req, err := http.ReadRequest(bufio.NewReader(r))
if err != nil {
return false
}
return strings.HasPrefix(req.Host, name)
}
}
2025-05-30 18:42:53 +08:00
type sl struct {
net.Listener
closed bool
}
func (sl *sl) Accept() (net.Conn, error) {
if sl.closed {
return nil, errors.New("closed")
}
return sl.Listener.Accept()
}
func (sl *sl) Close() error {
sl.closed = true
return nil
}
2023-12-13 09:22:05 +08:00
type Server struct {
2025-05-30 18:42:53 +08:00
Conf *model.HttpServerConfig
Closed bool
2023-12-13 09:22:05 +08:00
*http.Server
2025-05-30 18:42:53 +08:00
l *sl
}
func (s *Server) Renew() {
s.Server = &http.Server{
Handler: s.Handler,
}
2023-12-13 09:22:05 +08:00
}
2025-05-30 18:42:53 +08:00
2023-12-07 23:34:34 +08:00
type ServerListener struct {
2023-12-10 19:26:09 +08:00
port int
2023-12-07 23:34:34 +08:00
listener cmux.CMux
2023-12-13 09:22:05 +08:00
servers map[string]*Server
2023-12-07 23:34:34 +08:00
}
2023-12-13 09:22:05 +08:00
func (s *ServerListener) AddServer(name string, server *Server) {
2023-12-07 23:34:34 +08:00
s.servers[name] = server
}
2023-12-10 01:08:39 +08:00
func (s *ServerListener) ServerCount() int {
return len(s.servers)
}
2025-05-30 18:42:53 +08:00
func (s *ServerListener) StartServer(name string) {
2023-12-07 23:34:34 +08:00
server, ok := s.servers[name]
2025-05-30 18:42:53 +08:00
serverName := server.Conf.ServerName
2023-12-07 23:34:34 +08:00
if !ok {
panic("No named server")
}
2025-05-30 18:42:53 +08:00
go func() {
var err error
defer func() {
l := logger.GetLogger("ServerListener")
if err != nil {
if err == http.ErrServerClosed {
server.Closed = true
} else {
l.Error("Server error:", err)
}
}
l.Info("Server stopped:", name)
}()
if server.Closed {
server.Renew()
}
if server.l == nil {
server.l = &sl{
Listener: s.listener.Match(makeMatcher(serverName, s)),
}
}
if server.Conf.CertFile != "" && server.Conf.KeyFile != "" {
err = server.ServeTLS(server.l, server.Conf.CertFile, server.Conf.KeyFile)
} else {
err = server.Serve(server.l)
}
}()
// return server.Serve(l)
}
func (s *ServerListener) StopServer(name string) error {
server, ok := s.servers[name]
if !ok {
return nil
2023-12-13 09:22:05 +08:00
}
2025-05-30 18:42:53 +08:00
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
return server.Shutdown(ctx)
2023-12-07 23:34:34 +08:00
}
2025-05-30 18:42:53 +08:00
// Start 方法用于并发启动 ServerListener 中所有注册的服务器。
// 它会为每个服务器创建一个新的 goroutine 来启动,以确保各个服务器可以独立运行。
2023-12-07 23:34:34 +08:00
func (s *ServerListener) Start() {
2025-05-30 18:42:53 +08:00
// 遍历 ServerListener 中所有注册的服务器
2023-12-07 23:34:34 +08:00
for name, _ := range s.servers {
2025-05-30 18:42:53 +08:00
// 为每个服务器启动一个新的 goroutine 来执行启动操作
s.StartServer(name)
2023-12-07 23:34:34 +08:00
}
}
func (s *ServerListener) ShutDown() {
// may need add wait group
for _, server := range s.servers {
server.Shutdown(context.Background())
}
2023-12-10 01:08:39 +08:00
s.listener.Close()
2023-12-07 23:34:34 +08:00
}
func (s *ServerListener) Serve() {
2023-12-13 09:22:05 +08:00
l := logger.GetLogger("Listener")
2023-12-10 19:26:09 +08:00
l.Debug("listen on :", s.port)
2023-12-07 23:34:34 +08:00
go s.listener.Serve()
}
func NewServerListener(port int) *ServerListener {
listenStr := fmt.Sprintf(":%d", port)
l, err := net.Listen("tcp", listenStr)
if err != nil {
l := logger.GetLogger("ServerListener")
l.Error("Listen error:", err)
}
muxer := cmux.New(l)
2023-12-13 09:22:05 +08:00
s := &ServerListener{port: port, listener: muxer, servers: make(map[string]*Server)}
2023-12-07 23:34:34 +08:00
return s
}
2023-12-08 22:02:36 +08:00
2023-12-13 09:22:05 +08:00
func AddServer(name string, server *Server, port int) {
2023-12-08 22:02:36 +08:00
listenStr := fmt.Sprintf(":%d", port)
listener, ok := ServerManager[listenStr]
if !ok {
listener = NewServerListener(port)
ServerManager[listenStr] = listener
}
listener.AddServer(name, server)
}
2025-05-30 18:42:53 +08:00
func AddServerWithConfig(conf *model.HttpServerConfig) {
mux := NewServeMux(conf)
s := &http.Server{
Handler: mux,
}
name := conf.Name
port := conf.Port
ss := &Server{
Server: s,
Conf: conf,
}
AddServer(name, ss, port)
}
func StopServer(name string, port int) {
listenStr := fmt.Sprintf(":%d", port)
listener, ok := ServerManager[listenStr]
if !ok {
return
}
listener.StopServer(name)
}
func StartServer(name string, port int) {
listenStr := fmt.Sprintf(":%d", port)
listener, ok := ServerManager[listenStr]
if !ok {
return
}
listener.StartServer(name)
}