From: qydysky Date: Sat, 8 Mar 2025 21:24:44 +0000 (+0800) Subject: Improve 停止优化 (#182) X-Git-Tag: v0.16.4~2 X-Git-Url: http://127.0.0.1:8081/?a=commitdiff_plain;h=936450a57bc6b403baee1ef05f9cfe81ae542ca2;p=bili_danmu%2F.git Improve 停止优化 (#182) * Improve 捕获容器停止信号 * Add 停止同配置其他服务 * Add stop命令参数 * Improve stop windows 支持 * Improve windows优化 * Improve windows优化 * Improve windows优化 * Improve 默认不启用 --- diff --git a/CV/Var.go b/CV/Var.go index dea2984..c3a03ff 100644 --- a/CV/Var.go +++ b/CV/Var.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "math" + "net" "net/http" "net/url" "os" @@ -381,6 +382,7 @@ func (t *Common) Init() *Common { ckv = flag.String("ckv", "", "自定义配置KV文件,将会覆盖config_K_v配置") roomIdP = flag.Int("r", 0, "roomid") genKey = flag.Bool("genKey", false, "生成cookie加密公私钥") + stop = flag.Bool("stop", false, "向当前配置发送退出信号") ) testing.Init() flag.Parse() @@ -452,10 +454,48 @@ func (t *Common) Init() *Common { } { - // 启动时显示ip + r := reqf.New() showIpOnBoot, _ := t.K_v.LoadV("启动时显示ip").(bool) + stopPath, _ := t.K_v.LoadV("stop路径").(string) + waitStop, _ := t.K_v.LoadV("停止其他服务超时").(float64) + if waitStop <= 0 { + waitStop = 100 + } for ip := range sys.GetIpByCidr() { - if showIpOnBoot { + if ip.IsLinkLocalUnicast() { + continue + } + // 停止同配置其他服务 + if stopPath != "" { + var rval = reqf.Rval{Method: http.MethodOptions, Timeout: 500} + if ip.To4() != nil { + rval.Url = fmt.Sprintf("http://%s:%s%s", ip.String(), port, stopPath) + } else { + rval.Url = fmt.Sprintf("http://[%s]:%s%s", ip.String(), port, stopPath) + } + if err := r.Reqf(rval); err == nil { + rval.Method = http.MethodGet + for i := int(waitStop); i > 0; i-- { + fmt.Printf("\r停止服务: %s %3ds", rval.Url, i) + _ = r.Reqf(rval) + if conn, err := net.Dial("tcp", serUrl.Host); err != nil { + stopPath = "" + break + } else { + conn.Close() + } + time.Sleep(time.Second) + } + if stopPath == "" { + fmt.Printf("\n停止服务: 成功\n") + } else { + fmt.Printf("\n停止服务: 超时\n") + } + } + } + + // 启动时显示ip + if !*stop && showIpOnBoot { if ip.To4() != nil { fmt.Printf("当前地址 http://%s:%s\n", ip.String(), port) } else { @@ -463,6 +503,10 @@ func (t *Common) Init() *Common { } } } + + if *stop { + os.Exit(0) + } } var ( @@ -504,6 +548,19 @@ func (t *Common) Init() *Common { } } + if val, ok := t.K_v.LoadV("stop路径").(string); ok && val != "" { + t.SerF.Store(val, func(w http.ResponseWriter, r *http.Request) { + if DefaultHttpFunc(t, w, r, http.MethodGet, http.MethodOptions) { + return + } + if r.Method == http.MethodOptions { + w.Header().Set("Allow", "GET") + return + } + t.Danmu_Main_mq.Push_tag(`interrupt`, nil) + }) + } + if val, ok := t.K_v.LoadV("ip路径").(string); ok && val != "" { t.SerF.Store(val, func(w http.ResponseWriter, r *http.Request) { if DefaultHttpFunc(t, w, r, http.MethodGet) { diff --git a/README.md b/README.md index 9cba194..d593b57 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,33 @@ 关于离线构建,详见章节`运行`及其`注意事项` +#### 等待同配置其他服务停止 +添加配置项`stop路径`、`停止其他服务超时`(>v0.16.3)。 + +当配置了`Web服务地址`及`stop路径`之后,将在启动时,检测是否存在同`Web服务地址`+`stop路径`的服务,并先尝试停止它。 + +1. 这可以在容器启动时,优雅的停止同配置其他服务。 + +2. 添加命令行参数`-stop`(>v0.16.3),用于停止服务。 + + 以下是k8s在退出时,优雅的停止服务示例[k8s pod-termination 文档](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination): + +``` yml +apiVersion: v1 +kind: Pod +metadata: + name: lifecycle-demo +spec: + containers: + - name: lifecycle-demo-container + image: bili + lifecycle: + preStop: + exec: + command: ["/bin/sh","-c","main -stop"] + +``` + #### 环境变量覆盖配置项 添加配置项`从环境变量覆盖`(>v0.14.26)。将在配置文件都加载后,用环境变量覆盖配置项。 @@ -1105,8 +1132,8 @@ windows: set CGO_ENABLED=0;go build . clone/下载本项目。进入`demo`目录(文件夹),运行: ``` -linux: CGO_ENABLED=0 go run . [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] -windows: set CGO_ENABLED=0;go run . [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] +linux: CGO_ENABLED=0 go run . [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] +windows: set CGO_ENABLED=0;go run . [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] ``` 3. docker部署 @@ -1133,8 +1160,8 @@ go build . 前往[releases](https://github.com/qydysky/bili_danmu/releases)页下载对应系统版本。解压后进入`demo`目录(文件夹),运行`main`(`main.exe`)。 ``` -./main [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] -./main.exe [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] +./main [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] +./main.exe [-r 房间ID] [-ckv 自定义config_K_v.json] [-genKey] [-stop] ``` #### 注意事项 diff --git a/bili_danmu.go b/bili_danmu.go index 4ee7288..bd40b98 100644 --- a/bili_danmu.go +++ b/bili_danmu.go @@ -9,6 +9,7 @@ import ( "os" "os/signal" "strconv" + "syscall" "time" c "github.com/qydysky/bili_danmu/CV" @@ -60,8 +61,8 @@ func Start() { //ctrl+c退出 go func() { var interrupt = make(chan os.Signal, 2) - //捕获ctrl+c退出 - signal.Notify(interrupt, os.Interrupt) + //捕获ctrl+c、容器退出 + signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) danmulog.L(`I: `, "3s内2次ctrl+c退出") for { <-interrupt diff --git a/demo/config/config_K_v.json b/demo/config/config_K_v.json index fc20fea..c9c268d 100644 --- a/demo/config/config_K_v.json +++ b/demo/config/config_K_v.json @@ -225,12 +225,16 @@ "下播后不记录人气观看人数":true, "debug模式-help":"启用额外调试信息", "debug模式":false, - "debug路径-help":"当Web服务地址不为空时, 访问此路径可以获取调试信息,为空时关闭,需要/结尾", + "debug路径-help":"当Web服务地址不为空时, 访问此路径可以获取调试信息,为空时关闭,需要/开头及结尾", "debug路径":"", - "性能路径-help":"当Web服务地址不为空时, 访问此路径可以获取性能信息,为空时关闭", + "性能路径-help":"当Web服务地址不为空时, 访问此路径可以获取性能信息,为空时关闭,需要/开头及结尾", "性能路径":"/state/", - "ip路径-help":"当Web服务地址不为空时, 访问此路径可以获取当前客户端ip地址列表,为空时关闭", + "ip路径-help":"当Web服务地址不为空时, 访问此路径可以获取当前客户端ip地址列表,为空时关闭,需要/开头及结尾", "ip路径":"", + "stop路径-help":"当Web服务地址不为空时, 访问此路径可以停止当前服务,为空时关闭,需要/开头及结尾", + "stop路径":"", + "停止其他服务超时-help":"当Web服务地址、pid路径不为空时, 将等待n秒停止其他服务", + "停止其他服务超时": 100, "生成pgo-help":"将在退出后生成pgo文件在指定路径,default.pgo将有助于下次构建的优化,但会导致gc频繁,构建缓慢,为空时不生成", "生成pgo":"", "登陆二维码-白":"OO",