• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

go多端口重用,平滑重启

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
package main

import (
	"context"
	"fmt"
	"github.com/cloudflare/tableflip"
	"io"
	l "log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

var log = l.New(os.Stderr, "", l.LstdFlags|l.Llongfile)

func prefork(addr1, addr2 string) {
	upg, err := tableflip.New(tableflip.Options{})
	if err != nil {
		panic(err)
	}

	defer upg.Stop()

	// kill 升级
	go func() {
		sig := make(chan os.Signal, 1)
		signal.Notify(sig, syscall.SIGHUP, syscall.SIGTERM)
		for range sig {
			if err := upg.Upgrade(); err != nil {
				log.Println("Upgrade failed:", err)
				continue
			}
			log.Println("Upgrade succeeded")
		}
	}()

	ln, err := upg.Listen("tcp", "localhost:8080")
	if err != nil {
		log.Fatalln("Can't listen:", err)
	}

	var server http.Server
	go server.Serve(ln)

	// 退出清理
	go func() {
		<-upg.Exit()
		_ = server.Shutdown(context.Background())
		<-time.AfterFunc(time.Second*10, func() {
			os.Exit(0)
		}).C
	}()

	if err := upg.Ready(); err != nil {
		panic(err)
	}

	select {}
}

// hello world, the web server
func HelloServer(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, "hello, world!\n")
}

func main() {
	http.HandleFunc("/hello", HelloServer)
	fmt.Println(os.Getpid())
	prefork(":8080", ":8081")
}
package main

import (
	"fmt"
	"io"
	l "log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
)

var log = l.New(os.Stderr, "", l.LstdFlags|l.Llongfile)

func isChild() bool {
	for _, d := range os.Args {
		if strings.Contains(d, "child") {
			return true
		}
	}
	return false
}

func prefork(addr1, addr2 string) (ln net.Listener, err error) {
	var files []*os.File
	if !isChild() {
		{
			// Master proc
			addr, err := net.ResolveTCPAddr("tcp", addr1)
			if err != nil {
				log.Fatal(err)
				return ln, err
			}
			tcplistener, err := net.ListenTCP("tcp", addr)
			if err != nil {
				log.Fatal(err)
				return ln, err
			}
			fl, err := tcplistener.File()
			if err != nil {
				log.Fatal(err)
				return ln, err
			}
			files = append(files, fl)

			go func() {
				server := &http.Server{Addr: "", Handler: nil}
				if err := server.Serve(tcplistener); err != nil {
					log.Fatal(err)
				}
			}()
		}

		{
			// Master proc
			addr, err := net.ResolveTCPAddr("tcp", addr2)
			if err != nil {
				return ln, err
			}
			tcplistener, err := net.ListenTCP("tcp", addr)
			if err != nil {
				return ln, err
			}
			fl, err := tcplistener.File()
			if err != nil {
				return ln, err
			}
			files = append(files, fl)

			go func() {
				server := &http.Server{Addr: addr2, Handler: nil}
				if err := server.Serve(tcplistener); err != nil {
					log.Fatal(err)
				}
			}()
		}

	}

	if isChild() {
		go func() {
			f := os.NewFile(3, "")
			listener, err := net.FileListener(f)
			if err != nil {
				log.Fatal(err)
			}

			server := &http.Server{Addr: "", Handler: nil}
			if err := server.Serve(listener); err != nil {
				log.Fatal(err)
			}
		}()

		go func() {
			f := os.NewFile(4, "")
			listener, err := net.FileListener(f)
			if err != nil {
				log.Fatal(err)
			}

			server := &http.Server{Addr: "", Handler: nil}
			if err := server.Serve(listener); err != nil {
				log.Fatal(err)
			}
		}()
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP, syscall.SIGTERM)
	fmt.Println(<-c)

	childs := make([]*exec.Cmd, 1)
	for i := range childs {
		childs[i] = exec.Command(os.Args[0], append(os.Args[1:], "-prefork", "-child")...)
		childs[i].Stdout = os.Stdout
		childs[i].Stderr = os.Stderr
		childs[i].ExtraFiles = files
		if err := childs[i].Start(); err != nil {
			log.Fatal(err)
			return ln, err
		}
	}

	for k := range childs {
		if err := childs[k].Wait(); err != nil {
			log.Fatal(err)
			return ln, err
		}
	}

	os.Exit(0)

	return ln, err
}

// hello world, the web server
func HelloServer(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, "hello, world!\n")
}

func main() {
	http.HandleFunc("/hello", HelloServer)
	//go http.ListenAndServe(":8080", nil)
	//go http.ListenAndServe(":8081", nil)

	fmt.Println(os.Getpid())

	fmt.Println(prefork(":8080", ":8081"))
}

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap