]> 127.0.0.1 Git - bili_danmu/.git/commitdiff
Improve 停止优化 (#182)
authorqydysky <qydysky@foxmail.com>
Sat, 8 Mar 2025 21:24:44 +0000 (05:24 +0800)
committerGitHub <noreply@github.com>
Sat, 8 Mar 2025 21:24:44 +0000 (05:24 +0800)
* Improve 捕获容器停止信号

* Add 停止同配置其他服务

* Add stop命令参数

* Improve stop windows 支持

* Improve windows优化

* Improve windows优化

* Improve windows优化

* Improve 默认不启用

CV/Var.go
README.md
bili_danmu.go
demo/config/config_K_v.json

index dea298425a92774ebba831ef3a5f50ddb6d6fc6b..c3a03ff3ed7e8992f3a4aed5a8a4eb884391c212 100644 (file)
--- 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) {
index 9cba1943a2028bfd35a973928bf5b3e12fb558d8..d593b57d4fc41a929b974968ce44a7d905e2afb3 100644 (file)
--- a/README.md
+++ b/README.md
 
 关于离线构建,详见章节`运行`及其`注意事项`
 
+#### 等待同配置其他服务停止
+添加配置项`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]
 ```
 
 #### 注意事项
index 4ee7288d08fcfcbf47508074d5f46ae2d53f3df8..bd40b988880a599836adeba716df869b84dfb77f 100644 (file)
@@ -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
index fc20fea396e7593832180fee1aa9bc4a30b2142d..c9c268da2363485391ca06232d5f1982c53b2b20 100644 (file)
     "下播后不记录人气观看人数":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",