新进来的请求怎么办?
- fork一个子进程,继承父进程的监听socket
- 子进程启动成功之后,接收新的连接
- 父进程停止接收新的连接,等已有的请求处理完毕,退出
- 优雅重启成功
子进程如何继承父进程的文件句柄?
- 通过os.Cmd对象中的ExtraFiles参数进行传递
- 通过os.Cmd对象中的ExtraFiles参数进行传递
- 文件句柄继承实例分析
- 使用go1.8版本的shutdown方法进行优雅关闭
- 使用socket继承实现,子进程接管父进程的监听socket
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"time"
)
var (
child *bool
)
func init() {
child = flag.Bool("child", false, "继承于父进程(internal use only)")
flag.Parse()
}
func readFromParent() {
//fd = 0,标准输出
//fd = 1,标准输入
//fd = 2,标准错误输出
//fd = 3, ==> ExtraFiles[0]
//fd = 4, ==> ExtraFiles[1]
//第一个参数文件句柄的下标,就是ExtraFiles[0], 第二个参数名字可以随便取
f := os.NewFile(3, "")
count := 0
for {
//格式化字符串
str := fmt.Sprintf("hello, i‘child process, write: %d line \n", count)
count++
//写入到这个文件
_, err := f.WriteString(str)
if err != nil {
fmt.Printf("write string failed, err: %v\n", err)
time.Sleep(time.Second)
continue
}
//每一秒写下文件
time.Sleep(time.Second)
}
}
//启动子进程
func startChild(file *os.File) {
args := []string{"-child"}
//os.Args[0]是文件路径,带上-child选项
cmd := exec.Command(os.Args[0], args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
//放socket fd在第一个entry,只要把父进程传递过来的放在这里
cmd.ExtraFiles = []*os.File{file}
//到main函数
err := cmd.Start()
if err != nil {
fmt.Printf("start child failed, err: %v\n", err.Error())
return
}
}
func main() {
//表示已经是一个子进程了
if child != nil && *child == true {
fmt.Printf("继承于父进程的文件句柄\n")
//子进程
readFromParent()
return
}
//父进程的逻辑,打开文件句柄
file, err := os.OpenFile("./test.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
fmt.Printf("open file failed, err:%v\n", err)
return
}
//启动一个子进程,把文件句柄给子进程
startChild(file)
fmt.Println("父进程退出")
}
踩
(0)
赞
(0)
举报
评论 一句话评论(0)