这是一个简单的http/https/ws/wss均衡负载、故障转移路由/代理,通过定时刷新配置不中断地:
+- 监听占用等待
- 动态后端
- 路径继承
- 自定权重
config:
- *addr*: string 监听端口 例:`0.0.0.0:8081`
-- *matchRule*: string 匹配规则 `prefix`:当未匹配到时,返回最近的/匹配, `all`:当未匹配到时,返回404
+- *matchRule*: string 匹配规则,默认`prefix`。 `prefix`:当未匹配到时,返回最近的/匹配, `all`:当未匹配到时,返回404
- *copyBlocks*: int 转发的块数量,默认`1000`
- *retryBlocks*: {} 重试
- *sizeB*: int 重试的块大小,默认`1000000`
- *num*: int 重试的块数量,默认`1000`,为`-1`时停用重试
-- *tls*: {} 启用tls
+- *tls*: {} 启用tls, 默认空
- *pub*: string 公钥pem路径
- *key*: string 私钥pem路径
- routes: [] 路由
_ = done()
}()
- var matchfunc func(path string) (func(w http.ResponseWriter, r *http.Request), bool)
- switch t.MatchRule {
- case "all":
- matchfunc = t.routeP.Load
- default:
- matchfunc = t.routeP.LoadPerfix
- }
-
httpSer := http.Server{
Addr: t.Addr,
BaseContext: func(l net.Listener) context.Context { return ctx },
t.RetryBlocksI = pslice.NewBlocks[byte](t.RetryBlocks.SizeB, t.RetryBlocks.Num)
}
- syncWeb := pweb.NewSyncMap(&httpSer, &t.routeP, matchfunc)
- defer syncWeb.Shutdown()
+ defer logger.Info(`I:`, fmt.Sprintf("%v shutdown", t.Addr))
+
+ defer t.startServer(ctx, logger, &httpSer)()
t.SwapSign(ctx, logger)
logger.Info(`I:`, fmt.Sprintf("%v running", t.Addr))
<-ctx.Done()
- logger.Info(`I:`, fmt.Sprintf("%v shutdown", t.Addr))
+}
+
+func (t *Config) startServer(ctx context.Context, logger Logger, conf *http.Server) (shutdown func(ctx ...context.Context)) {
+ shutdown = func(ctx ...context.Context) {}
+
+ var matchfunc func(path string) (func(w http.ResponseWriter, r *http.Request), bool)
+ switch t.MatchRule {
+ case "all":
+ matchfunc = t.routeP.Load
+ default:
+ matchfunc = t.routeP.LoadPerfix
+ }
+
+ var notice = sync.OnceFunc(func() {
+ logger.Warn(`W:`, `Address already in use. Wait Release...`)
+ })
+
+ timer := time.NewTicker(time.Millisecond * 100)
+ defer timer.Stop()
+
+ for {
+ syncWeb, err := pweb.NewSyncMapNoPanic(conf, &t.routeP, matchfunc)
+ if err == nil {
+ shutdown = syncWeb.Shutdown
+ return
+ } else if strings.Contains(err.Error(), `address already in use`) {
+ select {
+ case <-ctx.Done():
+ return
+ case <-timer.C:
+ notice()
+ }
+ } else {
+ panic(err)
+ }
+ }
}
func (t *Config) SwapSign(ctx context.Context, logger Logger) {
require (
github.com/dustin/go-humanize v1.0.1
github.com/gorilla/websocket v1.5.3
- github.com/qydysky/part v0.28.20240828143014
+ github.com/qydysky/part v0.28.20241021164252
golang.org/x/net v0.28.0
)
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/qydysky/brotli v0.0.0-20240828134800-e9913a6e7ed9 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/qydysky/brotli v0.0.0-20240828134800-e9913a6e7ed9 h1:k451T+bpsLr+Dq9Ujo+Qtx0iomRA1XXS5ttlEojvfuQ=
github.com/qydysky/brotli v0.0.0-20240828134800-e9913a6e7ed9/go.mod h1:cI8/gy/wjy2Eb+p2IUj2ZuDnC8R5Vrx3O0VMPvMvphA=
-github.com/qydysky/part v0.28.20240828143014 h1:1fsUdLXyh03Swksf0BLRge/ObnLRx2cIVyNXaHxILMc=
-github.com/qydysky/part v0.28.20240828143014/go.mod h1:s3h7P6YdST5b9WoqjlS9w+JzDFdMeSENQOi8noYuopg=
+github.com/qydysky/part v0.28.20241021164252 h1:Jc1mWkZssxRlyqsgS8tJxjnNef43kvKMyoEeLlO44kw=
+github.com/qydysky/part v0.28.20241021164252/go.mod h1:s3h7P6YdST5b9WoqjlS9w+JzDFdMeSENQOi8noYuopg=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
-github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
-github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=