优化 添加信号量 清空缓存

This commit is contained in:
xing 2022-11-15 16:36:21 +08:00
parent 875cc554dc
commit 210f8f39c5
11 changed files with 107 additions and 50 deletions

View File

@ -45,7 +45,7 @@ func PostComment(c *gin.Context) {
m := c.PostForm("email") m := c.PostForm("email")
comment := c.PostForm("comment") comment := c.PostForm("comment")
c.Request.Body = io.NopCloser(bytes.NewBuffer(data)) c.Request.Body = io.NopCloser(bytes.NewBuffer(data))
req, err := http.NewRequest("POST", config.Conf.PostCommentUrl, strings.NewReader(c.Request.PostForm.Encode())) req, err := http.NewRequest("POST", config.Conf.Load().PostCommentUrl, strings.NewReader(c.Request.PostForm.Encode()))
if err != nil { if err != nil {
return return
} }
@ -70,7 +70,7 @@ func PostComment(c *gin.Context) {
err = er err = er
return return
} }
cu, er := url.Parse(config.Conf.PostCommentUrl) cu, er := url.Parse(config.Conf.Load().PostCommentUrl)
if er != nil { if er != nil {
err = er err = er
return return
@ -104,8 +104,8 @@ func PostComment(c *gin.Context) {
return return
} }
su := fmt.Sprintf("%s: %s[%s]发表了评论对文档[%v]的评论", config.Options.Value("siteurl"), author, m, post.PostTitle) su := fmt.Sprintf("%s: %s[%s]发表了评论对文档[%v]的评论", config.Options.Value("siteurl"), author, m, post.PostTitle)
err = mail.SendMail([]string{config.Conf.Mail.User}, su, comment) err = mail.SendMail([]string{config.Conf.Load().Mail.User}, su, comment)
logs.ErrPrintln(err, "发送邮件", config.Conf.Mail.User, su, comment) logs.ErrPrintln(err, "发送邮件", config.Conf.Load().Mail.User, su, comment)
}() }()
s, er := io.ReadAll(ress.Body) s, er := io.ReadAll(ress.Body)

View File

@ -28,34 +28,35 @@ var usersCache *cache.MapCache[uint64, wp.Users]
var commentsCache *cache.MapCache[uint64, wp.Comments] var commentsCache *cache.MapCache[uint64, wp.Comments]
func InitActionsCommonCache() { func InitActionsCommonCache() {
c := config.Conf.Load()
archivesCaches = &Arch{ archivesCaches = &Arch{
mutex: &sync.Mutex{}, mutex: &sync.Mutex{},
setCacheFunc: archives, setCacheFunc: archives,
} }
searchPostIdsCache = cache.NewMapCacheByFn[string, PostIds](searchPostIds, config.Conf.SearchPostCacheTime) searchPostIdsCache = cache.NewMapCacheByFn[string, PostIds](searchPostIds, c.SearchPostCacheTime)
postListIdsCache = cache.NewMapCacheByFn[string, PostIds](searchPostIds, config.Conf.PostListCacheTime) postListIdsCache = cache.NewMapCacheByFn[string, PostIds](searchPostIds, c.PostListCacheTime)
monthPostsCache = cache.NewMapCacheByFn[string, []uint64](monthPost, config.Conf.MonthPostCacheTime) monthPostsCache = cache.NewMapCacheByFn[string, []uint64](monthPost, c.MonthPostCacheTime)
postContextCache = cache.NewMapCacheByFn[uint64, PostContext](getPostContext, config.Conf.ContextPostCacheTime) postContextCache = cache.NewMapCacheByFn[uint64, PostContext](getPostContext, c.ContextPostCacheTime)
postsCache = cache.NewMapCacheByBatchFn[uint64, wp.Posts](getPostsByIds, config.Conf.PostDataCacheTime) postsCache = cache.NewMapCacheByBatchFn[uint64, wp.Posts](getPostsByIds, c.PostDataCacheTime)
categoryCaches = cache.NewSliceCache[wp.WpTermsMy](categories, config.Conf.CategoryCacheTime) categoryCaches = cache.NewSliceCache[wp.WpTermsMy](categories, c.CategoryCacheTime)
recentPostsCaches = cache.NewSliceCache[wp.Posts](recentPosts, config.Conf.RecentPostCacheTime) recentPostsCaches = cache.NewSliceCache[wp.Posts](recentPosts, c.RecentPostCacheTime)
recentCommentsCaches = cache.NewSliceCache[wp.Comments](recentComments, config.Conf.RecentCommentsCacheTime) recentCommentsCaches = cache.NewSliceCache[wp.Comments](recentComments, c.RecentCommentsCacheTime)
postCommentCaches = cache.NewMapCacheByFn[uint64, []uint64](postComments, config.Conf.PostCommentsCacheTime) postCommentCaches = cache.NewMapCacheByFn[uint64, []uint64](postComments, c.PostCommentsCacheTime)
maxPostIdCache = cache.NewSliceCache[uint64](getMaxPostId, config.Conf.MaxPostIdCacheTime) maxPostIdCache = cache.NewSliceCache[uint64](getMaxPostId, c.MaxPostIdCacheTime)
usersCache = cache.NewMapCacheByBatchFn[uint64, wp.Users](getUsers, config.Conf.UserInfoCacheTime) usersCache = cache.NewMapCacheByBatchFn[uint64, wp.Users](getUsers, c.UserInfoCacheTime)
commentsCache = cache.NewMapCacheByBatchFn[uint64, wp.Comments](getCommentByIds, config.Conf.CommentsCacheTime) commentsCache = cache.NewMapCacheByBatchFn[uint64, wp.Comments](getCommentByIds, c.CommentsCacheTime)
} }
func ClearCache() { func ClearCache() {
@ -68,6 +69,16 @@ func ClearCache() {
usersCache.ClearExpired() usersCache.ClearExpired()
commentsCache.ClearExpired() commentsCache.ClearExpired()
} }
func FlushCache() {
searchPostIdsCache.Flush()
postsCache.Flush()
postsCache.Flush()
postListIdsCache.Flush()
monthPostsCache.Flush()
postContextCache.Flush()
usersCache.Flush()
commentsCache.Flush()
}
type PostIds struct { type PostIds struct {
Ids []uint64 Ids []uint64

View File

@ -41,6 +41,10 @@ func ClearCache() {
postFeedCache.ClearExpired() postFeedCache.ClearExpired()
commentCache.ClearExpired() commentCache.ClearExpired()
} }
func FlushCache() {
postFeedCache.Flush()
commentCache.Flush()
}
func isCacheExpired(c *gin.Context, lastTime time.Time) bool { func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
eTag := helper.StringMd5(lastTime.Format(tmp)) eTag := helper.StringMd5(lastTime.Format(tmp))

View File

@ -2,12 +2,13 @@ package config
import ( import (
"fmt" "fmt"
"github/fthvgb1/wp-go/safety"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"os" "os"
"time" "time"
) )
var Conf Config var Conf safety.Var[Config]
type Config struct { type Config struct {
Mysql Mysql `yaml:"mysql"` Mysql Mysql `yaml:"mysql"`
@ -61,10 +62,12 @@ func InitConfig(conf string) error {
if err != nil { if err != nil {
return err return err
} }
err = yaml.Unmarshal(file, &Conf) var c Config
err = yaml.Unmarshal(file, &c)
if err != nil { if err != nil {
return err return err
} }
Conf.Store(c)
return nil return nil
} }
@ -77,7 +80,7 @@ type Dsn struct {
Charset string `yaml:"charset"` Charset string `yaml:"charset"`
} }
func (m *Dsn) GetDsn() string { func (m Dsn) GetDsn() string {
if m.Charset == "" { if m.Charset == "" {
m.Charset = "utf8" m.Charset = "utf8"
} }

View File

@ -35,23 +35,24 @@ func (r SqlxDb) Get(ctx context.Context, dest any, sql string, params ...any) er
} }
func InitDb() error { func InitDb() error {
dsn := config.Conf.Mysql.Dsn.GetDsn() c := config.Conf.Load()
dsn := c.Mysql.Dsn.GetDsn()
var err error var err error
Db, err = sqlx.Open("mysql", dsn) Db, err = sqlx.Open("mysql", dsn)
if err != nil { if err != nil {
return err return err
} }
if config.Conf.Mysql.Pool.ConnMaxIdleTime != 0 { if c.Mysql.Pool.ConnMaxIdleTime != 0 {
Db.SetConnMaxIdleTime(config.Conf.Mysql.Pool.ConnMaxLifetime) Db.SetConnMaxIdleTime(c.Mysql.Pool.ConnMaxLifetime)
} }
if config.Conf.Mysql.Pool.MaxIdleConn != 0 { if c.Mysql.Pool.MaxIdleConn != 0 {
Db.SetMaxIdleConns(config.Conf.Mysql.Pool.MaxIdleConn) Db.SetMaxIdleConns(c.Mysql.Pool.MaxIdleConn)
} }
if config.Conf.Mysql.Pool.MaxOpenConn != 0 { if c.Mysql.Pool.MaxOpenConn != 0 {
Db.SetMaxOpenConns(config.Conf.Mysql.Pool.MaxOpenConn) Db.SetMaxOpenConns(c.Mysql.Pool.MaxOpenConn)
} }
if config.Conf.Mysql.Pool.ConnMaxLifetime != 0 { if c.Mysql.Pool.ConnMaxLifetime != 0 {
Db.SetConnMaxLifetime(config.Conf.Mysql.Pool.ConnMaxLifetime) Db.SetConnMaxLifetime(c.Mysql.Pool.ConnMaxLifetime)
} }
return err return err
} }

View File

@ -23,9 +23,10 @@ func SendMail(mailTo []string, subject string, body string, a ...AttacheFile) er
m := gomail.NewMessage( m := gomail.NewMessage(
gomail.SetEncoding(gomail.Base64), gomail.SetEncoding(gomail.Base64),
) )
c := config.Conf.Load()
m.SetHeader("From", m.SetHeader("From",
m.FormatAddress(config.Conf.Mail.User, m.FormatAddress(c.Mail.User,
config.Conf.Mail.Alias, c.Mail.Alias,
)) ))
m.SetHeader("To", mailTo...) m.SetHeader("To", mailTo...)
m.SetHeader("Subject", subject) m.SetHeader("Subject", subject)
@ -43,12 +44,12 @@ func SendMail(mailTo []string, subject string, body string, a ...AttacheFile) er
} }
d := gomail.NewDialer( d := gomail.NewDialer(
config.Conf.Mail.Host, c.Mail.Host,
config.Conf.Mail.Port, c.Mail.Port,
config.Conf.Mail.User, c.Mail.User,
config.Conf.Mail.Pass, c.Mail.Pass,
) )
if config.Conf.Mail.Ssl { if c.Mail.Ssl {
d.TLSConfig = &tls.Config{InsecureSkipVerify: true} d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
} }
err := d.DialAndSend(m) err := d.DialAndSend(m)

43
main.go
View File

@ -2,14 +2,20 @@ package main
import ( import (
"flag" "flag"
"fmt"
"github/fthvgb1/wp-go/actions" "github/fthvgb1/wp-go/actions"
"github/fthvgb1/wp-go/actions/common" "github/fthvgb1/wp-go/actions/common"
"github/fthvgb1/wp-go/config" "github/fthvgb1/wp-go/config"
"github/fthvgb1/wp-go/db" "github/fthvgb1/wp-go/db"
"github/fthvgb1/wp-go/mail"
"github/fthvgb1/wp-go/models" "github/fthvgb1/wp-go/models"
"github/fthvgb1/wp-go/plugins" "github/fthvgb1/wp-go/plugins"
"github/fthvgb1/wp-go/route" "github/fthvgb1/wp-go/route"
"log"
"math/rand" "math/rand"
"os"
"os/signal"
"syscall"
"time" "time"
) )
@ -43,7 +49,7 @@ func init() {
} }
func cronClearCache() { func cronClearCache() {
t := time.NewTicker(config.Conf.CrontabClearCacheTime) t := time.NewTicker(config.Conf.Load().CrontabClearCacheTime)
for { for {
select { select {
case <-t.C: case <-t.C:
@ -54,11 +60,38 @@ func cronClearCache() {
} }
} }
func main() { func signalNotify() {
if config.Conf.Port == "" { c := make(chan os.Signal)
config.Conf.Port = "80" signal.Notify(c, syscall.SIGUSR1, syscall.SIGUSR2)
conf := config.Conf.Load()
for {
switch <-c {
case syscall.SIGUSR1:
//todo 更新配置
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("清除缓存成功")
}()
}
} }
err := route.SetupRouter().Run(config.Conf.Port) }
func main() {
c := config.Conf.Load()
if c.Port == "" {
c.Port = "80"
config.Conf.Store(c)
}
go signalNotify()
err := route.SetupRouter().Run(c.Port)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -41,7 +41,7 @@ func RecoverAndSendMail(w io.Writer) func(ctx *gin.Context) {
) )
er := mail.SendMail( er := mail.SendMail(
[]string{config.Conf.Mail.User}, []string{config.Conf.Load().Mail.User},
fmt.Sprintf("%s%s %s 发生错误", fmt.Sprintf(config.Options.Value("siteurl")), c.FullPath(), time.Now().Format(time.RFC1123Z)), content) fmt.Sprintf("%s%s %s 发生错误", fmt.Sprintf(config.Options.Value("siteurl")), c.FullPath(), time.Now().Format(time.RFC1123Z)), content)
if er != nil { if er != nil {

View File

@ -9,7 +9,7 @@ import (
) )
func ValidateServerNames() func(ctx *gin.Context) { func ValidateServerNames() func(ctx *gin.Context) {
serverName := helper.SimpleSliceToMap(config.Conf.TrustServerNames, func(v string) string { serverName := helper.SimpleSliceToMap(config.Conf.Load().TrustServerNames, func(v string) string {
return v return v
}) })
return func(c *gin.Context) { return func(c *gin.Context) {

View File

@ -19,17 +19,20 @@ var digestCache *cache.MapCache[uint64, string]
var quto = regexp.MustCompile(`&quot; *|&amp; *|&lt; *|&gt; ?|&nbsp; *`) var quto = regexp.MustCompile(`&quot; *|&amp; *|&lt; *|&gt; ?|&nbsp; *`)
func InitDigestCache() { func InitDigestCache() {
digestCache = cache.NewMapCacheByFn[uint64](digestRaw, config.Conf.DigestCacheTime) digestCache = cache.NewMapCacheByFn[uint64](digestRaw, config.Conf.Load().DigestCacheTime)
} }
func ClearDigestCache() { func ClearDigestCache() {
digestCache.ClearExpired() digestCache.ClearExpired()
} }
func FlushCache() {
digestCache.Flush()
}
func digestRaw(arg ...any) (string, error) { func digestRaw(arg ...any) (string, error) {
str := arg[0].(string) str := arg[0].(string)
id := arg[1].(uint64) id := arg[1].(uint64)
limit := config.Conf.DigestWordCount limit := config.Conf.Load().DigestWordCount
if limit < 0 { if limit < 0 {
return str, nil return str, nil
} else if limit == 0 { } else if limit == 0 {

View File

@ -20,8 +20,9 @@ func SetupRouter() *gin.Engine {
// Disable Console Color // Disable Console Color
// gin.DisableConsoleColor() // gin.DisableConsoleColor()
r := gin.New() r := gin.New()
if len(config.Conf.TrustIps) > 0 { c := config.Conf.Load()
err := r.SetTrustedProxies(config.Conf.TrustIps) if len(c.TrustIps) > 0 {
err := r.SetTrustedProxies(c.TrustIps)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -42,11 +43,11 @@ func SetupRouter() *gin.Engine {
gin.Logger(), gin.Logger(),
middleware.ValidateServerNames(), middleware.ValidateServerNames(),
middleware.RecoverAndSendMail(gin.DefaultErrorWriter), middleware.RecoverAndSendMail(gin.DefaultErrorWriter),
middleware.FlowLimit(config.Conf.MaxRequestSleepNum, config.Conf.MaxRequestNum, config.Conf.SleepTime), middleware.FlowLimit(c.MaxRequestSleepNum, c.MaxRequestNum, c.SleepTime),
middleware.SetStaticFileCache, middleware.SetStaticFileCache,
) )
//gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用 //gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用
if config.Conf.Gzip { if c.Gzip {
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{ r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{
"/wp-includes/", "/wp-content/", "/wp-includes/", "/wp-content/",
}))) })))
@ -60,7 +61,7 @@ func SetupRouter() *gin.Engine {
})) }))
store := cookie.NewStore([]byte("secret")) store := cookie.NewStore([]byte("secret"))
r.Use(sessions.Sessions("go-wp", store)) r.Use(sessions.Sessions("go-wp", store))
r.GET("/", middleware.SearchLimit(config.Conf.SingleIpSearchNum), actions.Index) r.GET("/", middleware.SearchLimit(c.SingleIpSearchNum), actions.Index)
r.GET("/page/:page", actions.Index) r.GET("/page/:page", actions.Index)
r.GET("/p/category/:category", actions.Index) r.GET("/p/category/:category", actions.Index)
r.GET("/p/category/:category/page/:page", actions.Index) r.GET("/p/category/:category/page/:page", actions.Index)
@ -73,7 +74,7 @@ func SetupRouter() *gin.Engine {
r.GET("/p/:id/feed", actions.PostFeed) r.GET("/p/:id/feed", actions.PostFeed)
r.GET("/feed", actions.Feed) r.GET("/feed", actions.Feed)
r.GET("/comments/feed", actions.CommentsFeed) r.GET("/comments/feed", actions.CommentsFeed)
r.POST("/comment", middleware.FlowLimit(config.Conf.MaxRequestSleepNum, 5, config.Conf.SleepTime), actions.PostComment) r.POST("/comment", middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.SleepTime), actions.PostComment)
if gin.Mode() != gin.ReleaseMode { if gin.Mode() != gin.ReleaseMode {
pprof.Register(r, "dev/pprof") pprof.Register(r, "dev/pprof")
} }