From 164ea468232f3cb57b8b46a59d1f842ba9b7fefc Mon Sep 17 00:00:00 2001 From: GoEdgeLab Date: Sun, 25 Jul 2021 17:14:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8Sock=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E5=90=AF=E5=81=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/edge-node/main.go | 23 ++----- go.mod | 1 + go.sum | 5 +- internal/apps/app_cmd.go | 71 +++++++++++--------- internal/apps/file_windows.go | 17 ----- internal/apps/pid.go | 119 ---------------------------------- internal/const/build.go | 8 +++ internal/const/build_plus.go | 8 +++ internal/nodes/node.go | 114 +++++++++++++++----------------- 9 files changed, 118 insertions(+), 248 deletions(-) delete mode 100644 internal/apps/file_windows.go delete mode 100644 internal/apps/pid.go create mode 100644 internal/const/build.go create mode 100644 internal/const/build_plus.go diff --git a/cmd/edge-node/main.go b/cmd/edge-node/main.go index db79173..5634125 100644 --- a/cmd/edge-node/main.go +++ b/cmd/edge-node/main.go @@ -5,15 +5,12 @@ import ( "github.com/TeaOSLab/EdgeNode/internal/apps" teaconst "github.com/TeaOSLab/EdgeNode/internal/const" "github.com/TeaOSLab/EdgeNode/internal/nodes" - "github.com/iwind/TeaGo/Tea" _ "github.com/iwind/TeaGo/bootstrap" "github.com/iwind/TeaGo/logs" - "github.com/iwind/TeaGo/types" - "io/ioutil" + "github.com/iwind/gosock/pkg/gosock" "net/http" _ "net/http/pprof" "os" - "syscall" ) func main() { @@ -40,25 +37,13 @@ func main() { fmt.Println("done") }) app.On("quit", func() { - pidFile := Tea.Root + "/bin/pid" - data, err := ioutil.ReadFile(pidFile) + var sock = gosock.NewTmpSock(teaconst.ProcessName) + _, err := sock.Send(&gosock.Command{Code: "quit"}) if err != nil { fmt.Println("[ERROR]quit failed: " + err.Error()) return } - pid := types.Int(string(data)) - if pid == 0 { - fmt.Println("[ERROR]quit failed: pid=0") - return - } - - process, err := os.FindProcess(pid) - if err != nil { - return - } - if process != nil { - _ = process.Signal(syscall.SIGQUIT) - } + fmt.Println("done") }) app.On("pprof", func() { // TODO 自己指定端口 diff --git a/go.mod b/go.mod index 6ff4379..d0d36be 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/golang/protobuf v1.5.2 github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060 github.com/iwind/gofcgi v0.0.0-20210528023741-a92711d45f11 + github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 github.com/lionsoul2014/ip2region v2.2.0-release+incompatible github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/mssola/user_agent v0.5.2 diff --git a/go.sum b/go.sum index 9abf335..e7b96a9 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,9 @@ github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060 h1:qdLtK4PDXxk2vMKkTWl github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= github.com/iwind/gofcgi v0.0.0-20210528023741-a92711d45f11 h1:DaQjoWZhLNxjhIXedVg4/vFEtHkZhK4IjIwsWdyzBLg= github.com/iwind/gofcgi v0.0.0-20210528023741-a92711d45f11/go.mod h1:JtbX20untAjUVjZs1ZBtq80f5rJWvwtQNRL6EnuYRnY= +github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c= +github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -77,9 +78,7 @@ github.com/lionsoul2014/ip2region v2.2.0-release+incompatible/go.mod h1:+ZBN7PBo github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mssola/user_agent v0.5.2 h1:CZkTUahjL1+OcZ5zv3kZr8QiJ8jy2H08vZIEkBeRbxo= github.com/mssola/user_agent v0.5.2/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= diff --git a/internal/apps/app_cmd.go b/internal/apps/app_cmd.go index 4f69aae..f762870 100644 --- a/internal/apps/app_cmd.go +++ b/internal/apps/app_cmd.go @@ -2,8 +2,11 @@ package apps import ( "fmt" - "github.com/iwind/TeaGo/Tea" + teaconst "github.com/TeaOSLab/EdgeNode/internal/const" "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "github.com/iwind/gosock/pkg/gosock" "os" "os/exec" "runtime" @@ -11,7 +14,7 @@ import ( "time" ) -// App命令帮助 +// AppCmd App命令帮助 type AppCmd struct { product string version string @@ -20,10 +23,14 @@ type AppCmd struct { appendStrings []string directives []*Directive + + sock *gosock.Sock } func NewAppCmd() *AppCmd { - return &AppCmd{} + return &AppCmd{ + sock: gosock.NewTmpSock(teaconst.ProcessName), + } } type CommandHelpOption struct { @@ -31,25 +38,25 @@ type CommandHelpOption struct { Description string } -// 产品 +// Product 产品 func (this *AppCmd) Product(product string) *AppCmd { this.product = product return this } -// 版本 +// Version 版本 func (this *AppCmd) Version(version string) *AppCmd { this.version = version return this } -// 使用方法 +// Usage 使用方法 func (this *AppCmd) Usage(usage string) *AppCmd { this.usage = usage return this } -// 选项 +// Option 选项 func (this *AppCmd) Option(code string, description string) *AppCmd { this.options = append(this.options, &CommandHelpOption{ Code: code, @@ -58,13 +65,13 @@ func (this *AppCmd) Option(code string, description string) *AppCmd { return this } -// 附加内容 +// Append 附加内容 func (this *AppCmd) Append(appendString string) *AppCmd { this.appendStrings = append(this.appendStrings, appendString) return this } -// 打印 +// Print 打印 func (this *AppCmd) Print() { fmt.Println(this.product + " v" + this.version) @@ -103,7 +110,7 @@ func (this *AppCmd) Print() { } } -// 添加指令 +// On 添加指令 func (this *AppCmd) On(arg string, callback func()) { this.directives = append(this.directives, &Directive{ Arg: arg, @@ -111,7 +118,7 @@ func (this *AppCmd) On(arg string, callback func()) { }) } -// 运行 +// Run 运行 func (this *AppCmd) Run(main func()) { // 获取参数 args := os.Args[1:] @@ -161,7 +168,7 @@ func (this *AppCmd) Run(main func()) { // 版本号 func (this *AppCmd) runVersion() { - fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH+")") + fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH, teaconst.Tag+")") } // 帮助 @@ -171,9 +178,9 @@ func (this *AppCmd) runHelp() { // 启动 func (this *AppCmd) runStart() { - proc := this.checkPid() - if proc != nil { - fmt.Println(this.product+" already started, pid:", proc.Pid) + var pid = this.getPID() + if pid > 0 { + fmt.Println(this.product+" already started, pid:", pid) return } @@ -189,18 +196,15 @@ func (this *AppCmd) runStart() { // 停止 func (this *AppCmd) runStop() { - proc := this.checkPid() - if proc == nil { + var pid = this.getPID() + if pid == 0 { fmt.Println(this.product + " not started yet") return } - // 停止进程 - _ = proc.Kill() + _, _ = this.sock.Send(&gosock.Command{Code: "stop"}) - // 在Windows上经常不能及时释放资源 - _ = DeletePid(Tea.Root + "/bin/pid") - fmt.Println(this.product+" stopped ok, pid:", proc.Pid) + fmt.Println(this.product+" stopped ok, pid:", types.String(pid)) } // 重启 @@ -212,15 +216,24 @@ func (this *AppCmd) runRestart() { // 状态 func (this *AppCmd) runStatus() { - proc := this.checkPid() - if proc == nil { + var pid = this.getPID() + if pid == 0 { fmt.Println(this.product + " not started yet") - } else { - fmt.Println(this.product + " is running, pid: " + fmt.Sprintf("%d", proc.Pid)) + return } + + fmt.Println(this.product + " is running, pid: " + types.String(pid)) } -// 检查PID -func (this *AppCmd) checkPid() *os.Process { - return CheckPid(Tea.Root + "/bin/pid") +// 获取当前的PID +func (this *AppCmd) getPID() int { + if !this.sock.IsListening() { + return 0 + } + + reply, err := this.sock.Send(&gosock.Command{Code: "pid"}) + if err != nil { + return 0 + } + return maps.NewMap(reply.Params).GetInt("pid") } diff --git a/internal/apps/file_windows.go b/internal/apps/file_windows.go deleted file mode 100644 index fa2028f..0000000 --- a/internal/apps/file_windows.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build windows - -package apps - -import ( - "errors" - "os" -) - -// lock file -func LockFile(fp *os.File) error { - return errors.New("not implemented on windows") -} - -func UnlockFile(fp *os.File) error { - return errors.New("not implemented on windows") -} diff --git a/internal/apps/pid.go b/internal/apps/pid.go deleted file mode 100644 index 6c57a34..0000000 --- a/internal/apps/pid.go +++ /dev/null @@ -1,119 +0,0 @@ -package apps - -import ( - "fmt" - "github.com/TeaOSLab/EdgeNode/internal/events" - "github.com/iwind/TeaGo/Tea" - "github.com/iwind/TeaGo/types" - "io/ioutil" - "os" - "runtime" -) - -var pidFileList = []*os.File{} - -// 检查Pid -func CheckPid(path string) *os.Process { - // windows上打开的文件是不能删除的 - if runtime.GOOS == "windows" { - if os.Remove(path) == nil { - return nil - } - } - - file, err := os.Open(path) - if err != nil { - return nil - } - - defer func() { - _ = file.Close() - }() - - // 是否能取得Lock - err = LockFile(file) - if err == nil { - _ = UnlockFile(file) - return nil - } - - pidBytes, err := ioutil.ReadAll(file) - if err != nil { - return nil - } - pid := types.Int(string(pidBytes)) - - if pid <= 0 { - return nil - } - - proc, _ := os.FindProcess(pid) - return proc -} - -// 写入Pid -func WritePid() error { - path := Tea.Root + "/bin/pid" - fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) - if err != nil { - return err - } - events.On(events.EventQuit, func() { - _ = fp.Close() - }) - - if runtime.GOOS != "windows" { - err = LockFile(fp) - if err != nil { - return err - } - } - pidFileList = append(pidFileList, fp) // hold the file pointers - - _, err = fp.WriteString(fmt.Sprintf("%d", os.Getpid())) - if err != nil { - return err - } - - return nil -} - -// 写入Ppid -func WritePpid(path string) error { - fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) - if err != nil { - return err - } - - if runtime.GOOS != "windows" { - err = LockFile(fp) - if err != nil { - return err - } - } - pidFileList = append(pidFileList, fp) // hold the file pointers - - _, err = fp.WriteString(fmt.Sprintf("%d", os.Getppid())) - if err != nil { - return err - } - - return nil -} - -// 删除Pid -func DeletePid(path string) error { - _, err := os.Stat(path) - if err != nil { - if !os.IsNotExist(err) { - return nil - } - return err - } - - for _, fp := range pidFileList { - _ = UnlockFile(fp) - _ = fp.Close() - } - return os.Remove(path) -} diff --git a/internal/const/build.go b/internal/const/build.go new file mode 100644 index 0000000..71c7180 --- /dev/null +++ b/internal/const/build.go @@ -0,0 +1,8 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. +// +build community + +package teaconst + +const BuildCommunity = true +const BuildPlus = false +const Tag = "community" diff --git a/internal/const/build_plus.go b/internal/const/build_plus.go new file mode 100644 index 0000000..d2c1c88 --- /dev/null +++ b/internal/const/build_plus.go @@ -0,0 +1,8 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. +// +build plus + +package teaconst + +const BuildCommunity = false +const BuildPlus = true +const Tag = "plus" diff --git a/internal/nodes/node.go b/internal/nodes/node.go index d6f0e38..46d6832 100644 --- a/internal/nodes/node.go +++ b/internal/nodes/node.go @@ -6,7 +6,6 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" - "github.com/TeaOSLab/EdgeNode/internal/apps" "github.com/TeaOSLab/EdgeNode/internal/caches" "github.com/TeaOSLab/EdgeNode/internal/configs" teaconst "github.com/TeaOSLab/EdgeNode/internal/const" @@ -21,14 +20,14 @@ import ( "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/lists" "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/gosock/pkg/gosock" "io/ioutil" "log" "net" "os" "os/exec" - "os/signal" "runtime" - "syscall" "time" ) @@ -40,6 +39,7 @@ var DaemonPid = 0 // Node 节点 type Node struct { isLoaded bool + sock *gosock.Sock } func NewNode() *Node { @@ -73,9 +73,6 @@ func (this *Node) Start() { // 启动事件 events.Notify(events.EventStart) - // 处理信号 - this.listenSignals() - // 本地Sock err := this.listenSock() if err != nil { @@ -152,13 +149,6 @@ func (this *Node) Start() { return } - // 写入PID - err = apps.WritePid() - if err != nil { - remotelogs.Error("NODE", "write pid failed: "+err.Error()) - return - } - // hold住进程 select {} } @@ -229,32 +219,6 @@ func (this *Node) InstallSystemService() error { return nil } -// 处理信号 -func (this *Node) listenSignals() { - signals := make(chan os.Signal) - signal.Notify(signals, syscall.SIGQUIT) - go func() { - for s := range signals { - switch s { - case syscall.SIGQUIT: - events.Notify(events.EventQuit) - - // 监控连接数,如果连接数为0,则退出进程 - go func() { - for { - countActiveConnections := sharedListenerManager.TotalActiveConnections() - if countActiveConnections <= 0 { - os.Exit(0) - return - } - time.Sleep(1 * time.Second) - } - }() - } - } - }() -} - // 循环 func (this *Node) loop() error { // 检查api.yaml是否存在 @@ -493,37 +457,65 @@ func (this *Node) checkClusterConfig() error { // 监听本地sock func (this *Node) listenSock() error { - path := os.TempDir() + "/edge-node.sock" + this.sock = gosock.NewTmpSock(teaconst.ProcessName) - // 检查是否已经存在 - _, err := os.Stat(path) - if err == nil { - conn, err := net.Dial("unix", path) - if err != nil { - _ = os.Remove(path) + // 检查是否在运行 + if this.sock.IsListening() { + reply, err := this.sock.Send(&gosock.Command{Code: "pid"}) + if err == nil { + return errors.New("error: the process is already running, pid: " + maps.NewMap(reply.Params).GetString("pid")) } else { - _ = conn.Close() + return errors.New("error: the process is already running") } } - // 新的监听任务 - listener, err := net.Listen("unix", path) - if err != nil { - return err - } - events.On(events.EventQuit, func() { - remotelogs.Println("NODE", "quit unix sock") - _ = listener.Close() - }) - + // 启动监听 go func() { - for { - _, err := listener.Accept() - if err != nil { - return + this.sock.OnCommand(func(cmd *gosock.Command) { + switch cmd.Code { + case "pid": + _ = cmd.Reply(&gosock.Command{ + Code: "pid", + Params: map[string]interface{}{ + "pid": os.Getpid(), + }, + }) + case "stop": + _ = cmd.ReplyOk() + + // 退出主进程 + events.Notify(events.EventQuit) + os.Exit(0) + case "quit": + _ = cmd.ReplyOk() + _ = this.sock.Close() + + events.Notify(events.EventQuit) + + // 监控连接数,如果连接数为0,则退出进程 + go func() { + for { + countActiveConnections := sharedListenerManager.TotalActiveConnections() + if countActiveConnections <= 0 { + os.Exit(0) + return + } + time.Sleep(1 * time.Second) + } + }() } + }) + + err := this.sock.Listen() + if err != nil { + logs.Println("NODE", err.Error()) } }() + events.On(events.EventQuit, func() { + logs.Println("NODE", "quit unix sock") + _ = this.sock.Close() + }) + return nil }