From c83429600b94a0bef517989224b27f57db44beac Mon Sep 17 00:00:00 2001 From: xing Date: Wed, 16 Nov 2022 10:17:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E9=97=B4=E4=BB=B6=20reload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 94 +++++++++++++++++++++----------- middleware/validateservername.go | 28 +++++++--- route/route.go | 10 +++- safety/safemap.go | 26 +++++++++ 4 files changed, 116 insertions(+), 42 deletions(-) diff --git a/main.go b/main.go index 4568ab4..237a7d3 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "github/fthvgb1/wp-go/actions/common" "github/fthvgb1/wp-go/config" "github/fthvgb1/wp-go/db" + "github/fthvgb1/wp-go/logs" "github/fthvgb1/wp-go/mail" "github/fthvgb1/wp-go/models" "github/fthvgb1/wp-go/plugins" @@ -19,26 +20,13 @@ import ( "time" ) +var confPath string + func init() { - var c string - flag.StringVar(&c, "c", "config.yaml", "config file") + flag.StringVar(&confPath, "c", "config.yaml", "config file") flag.Parse() rand.Seed(time.Now().UnixNano()) - err := config.InitConfig(c) - if err != nil { - panic(err) - } - - err = db.InitDb() - if err != nil { - panic(err) - } - models.InitDB(db.NewSqlxDb(db.Db)) - err = config.InitOptions() - if err != nil { - panic(err) - } - err = config.InitTerms() + err := initConf(confPath) if err != nil { panic(err) } @@ -48,6 +36,28 @@ func init() { go cronClearCache() } +func initConf(c string) (err error) { + err = config.InitConfig(c) + if err != nil { + return + } + + err = db.InitDb() + if err != nil { + return + } + models.InitDB(db.NewSqlxDb(db.Db)) + err = config.InitOptions() + if err != nil { + return + } + err = config.InitTerms() + if err != nil { + return + } + return +} + func cronClearCache() { t := time.NewTicker(config.Conf.Load().CrontabClearCacheTime) for { @@ -60,30 +70,50 @@ func cronClearCache() { } } +func flushCache() { + defer func() { + if r := recover(); r != nil { + err := mail.SendMail([]string{config.Conf.Load().Mail.User}, "清空缓存失败", fmt.Sprintf("err:[%s]", r)) + logs.ErrPrintln(err, "发邮件失败") + } + }() + common.FlushCache() + plugins.FlushCache() + actions.FlushCache() + log.Println("清除缓存成功") +} + +func reload() { + defer func() { + if r := recover(); r != nil { + log.Println(r) + } + }() + err := config.InitConfig(confPath) + logs.ErrPrintln(err, "获取配置文件失败", confPath) + err = config.InitOptions() + logs.ErrPrintln(err, "获取网站设置WpOption失败") + err = config.InitTerms() + logs.ErrPrintln(err, "获取WpTerms表失败") + middleWareReloadFn() + log.Println("reload complete") +} + func signalNotify() { c := make(chan os.Signal) signal.Notify(c, syscall.SIGUSR1, syscall.SIGUSR2) - conf := config.Conf.Load() for { switch <-c { case syscall.SIGUSR1: - //todo 更新配置 + go reload() case syscall.SIGUSR2: - go func() { - defer func() { - if r := recover(); r != nil { - mail.SendMail([]string{conf.Mail.User}, "清空缓存失败", fmt.Sprintf("err:[%s]", r)) - } - }() - common.FlushCache() - plugins.FlushCache() - actions.FlushCache() - log.Println("清除缓存成功") - }() + go flushCache() } } } +var middleWareReloadFn func() + func main() { c := config.Conf.Load() if c.Port == "" { @@ -91,7 +121,9 @@ func main() { config.Conf.Store(c) } go signalNotify() - err := route.SetupRouter().Run(c.Port) + Gin, reloadFn := route.SetupRouter() + middleWareReloadFn = reloadFn + err := Gin.Run(c.Port) if err != nil { panic(err) } diff --git a/middleware/validateservername.go b/middleware/validateservername.go index d28be43..3c5c726 100644 --- a/middleware/validateservername.go +++ b/middleware/validateservername.go @@ -3,21 +3,33 @@ package middleware import ( "github.com/gin-gonic/gin" "github/fthvgb1/wp-go/config" - "github/fthvgb1/wp-go/helper" + "github/fthvgb1/wp-go/safety" "net/http" "strings" ) -func ValidateServerNames() func(ctx *gin.Context) { - serverName := helper.SimpleSliceToMap(config.Conf.Load().TrustServerNames, func(v string) string { - return v - }) +func ValidateServerNames() (func(ctx *gin.Context), func()) { + var serverName safety.Map[string, struct{}] + fn := func() { + r := config.Conf.Load().TrustServerNames + if len(r) > 0 { + for _, name := range r { + serverName.Store(name, struct{}{}) + } + } else { + serverName.Flush() + } + + } + fn() return func(c *gin.Context) { - if len(serverName) > 0 { - if _, ok := serverName[strings.Split(c.Request.Host, ":")[0]]; !ok { + if serverName.Len() > 0 { + if _, ok := serverName.Load(strings.Split(c.Request.Host, ":")[0]); !ok { c.Status(http.StatusForbidden) c.Abort() + return } } - } + c.Next() + }, fn } diff --git a/route/route.go b/route/route.go index a3a78ed..0fc209b 100644 --- a/route/route.go +++ b/route/route.go @@ -16,7 +16,7 @@ import ( "time" ) -func SetupRouter() *gin.Engine { +func SetupRouter() (*gin.Engine, func()) { // Disable Console Color // gin.DisableConsoleColor() r := gin.New() @@ -39,9 +39,10 @@ func SetupRouter() *gin.Engine { return config.Options.Value(k) }, }).SetTemplate() + validServerName, reloadValidServerNameFn := middleware.ValidateServerNames() r.Use( gin.Logger(), - middleware.ValidateServerNames(), + validServerName, middleware.RecoverAndSendMail(gin.DefaultErrorWriter), middleware.FlowLimit(c.MaxRequestSleepNum, c.MaxRequestNum, c.SleepTime), middleware.SetStaticFileCache, @@ -52,6 +53,9 @@ func SetupRouter() *gin.Engine { "/wp-includes/", "/wp-content/", }))) } + fn := func() { + reloadValidServerNameFn() + } f := static.Fs{FS: static.FsEx, Path: "wp-includes"} r.StaticFileFS("/favicon.ico", "favicon.ico", http.FS(static.FsEx)) r.StaticFS("/wp-includes", http.FS(f)) @@ -78,5 +82,5 @@ func SetupRouter() *gin.Engine { if gin.Mode() != gin.ReleaseMode { pprof.Register(r, "dev/pprof") } - return r + return r, fn } diff --git a/safety/safemap.go b/safety/safemap.go index 5f5f6dc..b76199f 100644 --- a/safety/safemap.go +++ b/safety/safemap.go @@ -318,6 +318,32 @@ func (e *entry[V]) delete(px unsafe.Pointer) (value V, ok bool) { } } +func (m *Map[K, V]) Flush() { + m.mu.Lock() + m.missLocked() + m.mu.Unlock() +} + +func (m *Map[K, V]) Len() int { + read, _ := m.read.Load().(readOnly[K, V]) + if read.amended { + // m.dirty contains keys not in read.m. Fortunately, Range is already O(N) + // (assuming the caller does not break out early), so a call to Range + // amortizes an entire copy of the map: we can promote the dirty copy + // immediately! + m.mu.Lock() + read, _ = m.read.Load().(readOnly[K, V]) + if read.amended { + read = readOnly[K, V]{m: m.dirty} + m.read.Store(read) + m.dirty = nil + m.misses = 0 + } + m.mu.Unlock() + } + return len(read.m) +} + // Range calls f sequentially for each key and value present in the map. // If f returns false, range stops the iteration. //