完成ghttp.Server热重启特性的HTTP&HTTPS在Linux下的功能及稳定性测试

This commit is contained in:
John
2018-05-16 21:27:27 +08:00
parent 6ca634e85b
commit 5bbf411741
11 changed files with 53 additions and 30 deletions

View File

@ -127,7 +127,11 @@ func init() {
doneChan <- struct{}{}
if !gproc.IsChild() {
glog.Printfln("%d: all web server shutdown smoothly", gproc.Pid())
if serverMapping.Size() > 1 {
glog.Printfln("%d: all web servers shutdown", gproc.Pid())
} else {
glog.Printfln("%d: web server shutdown", gproc.Pid())
}
}
}()
}
@ -262,6 +266,7 @@ func (s *Server) startServer(fdMap listenerFdMap) {
} else {
s.servers = append(s.servers, s.newGracefulServer(addr))
}
s.servers[len(s.servers) - 1].isHttps = true
}
}
// ================

View File

@ -59,6 +59,7 @@ func onCommMainNewFork(pid int, data []byte) {
// 关闭服务,通知所有子进程退出(Kill强制性退出)
func onCommMainShutdown(pid int, data []byte) {
procManager.Send(formatMsgBuffer(gMSG_CLOSE, nil))
procManager.KillAll()
procManager.WaitAll()
}
@ -83,7 +84,7 @@ func handleMainProcessHeartbeat() {
}
}
}
// 如果所有子进程都退出,并且主进程未活动达到超时时间,那么主进程也没存在的必要
// (双保险)如果所有子进程都退出,并且主进程未活动达到超时时间,那么主进程也没存在的必要
if procManager.Size() == 0 && int(gtime.Millisecond()) - lastUpdateTime.Val() > gPROC_HEARTBEAT_TIMEOUT{
os.Exit(0)
}

View File

@ -34,6 +34,9 @@ func handleProcessSignal() {
// 进程终止,停止所有子进程运行
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGTERM:
sendProcessMsg(gproc.Pid(), gMSG_SHUTDOWN, nil)
if gproc.IsChild() {
sendProcessMsg(gproc.PPid(), gMSG_SHUTDOWN, nil)
}
return
// 用户信号,热重启服务

View File

@ -7,19 +7,14 @@
package ghttp
import (
"os"
"fmt"
"net"
"os"
"context"
"net/http"
"crypto/tls"
"gitee.com/johng/gf/g/os/glog"
"gitee.com/johng/gf/g/os/gproc"
"time"
)
const (
gGRACEFUL_SHUTDOWN_TIMEOUT = 10*time.Second // 优雅关闭链接时的超时时间
)
// 优雅的Web Server对象封装
@ -27,8 +22,8 @@ type gracefulServer struct {
fd uintptr
addr string
httpServer *http.Server
rawln *net.TCPListener // 原始listener
listener net.Listener // 接口化封装的listener
rawListener net.Listener // 原始listener
listener net.Listener // 接口化封装的listener
isHttps bool
shutdownChan chan bool
}
@ -40,6 +35,7 @@ func (s *Server) newGracefulServer(addr string, fd...int) *gracefulServer {
httpServer : s.newHttpServer(addr),
shutdownChan : make(chan bool),
}
// 是否有继承的文件描述符
if len(fd) > 0 && fd[0] > 0 {
gs.fd = uintptr(fd[0])
}
@ -65,19 +61,15 @@ func (s *gracefulServer) ListenAndServe() error {
if err != nil {
return err
}
//file, err := ln.(*net.TCPListener).File()
//if err != nil {
// return err
//}
//s.fd = file.Fd()
s.listener = ln
s.listener = ln
s.rawListener = ln
return s.doServe()
}
// 获得文件描述符
func (s *gracefulServer) Fd() uintptr {
if s.listener != nil {
file, err := s.listener.(*net.TCPListener).File()
if s.rawListener != nil {
file, err := s.rawListener.(*net.TCPListener).File()
if err == nil {
return file.Fd()
}
@ -110,13 +102,9 @@ func (s *gracefulServer) ListenAndServeTLS(certFile, keyFile string) error {
if err != nil {
return err
}
//file, err := ln.(*net.TCPListener).File()
//if err != nil {
// return err
//}
//s.fd = file.Fd()
s.listener = tls.NewListener(ln, config)
s.isHttps = true
s.listener = tls.NewListener(ln, config)
s.rawListener = ln
return s.doServe()
}
@ -131,7 +119,11 @@ func (s *gracefulServer) getProto() string {
// 开始执行Web Server服务处理
func (s *gracefulServer) doServe() error {
glog.Printfln("%d: %s server started listening on [%s]", gproc.Pid(), s.getProto(), s.addr)
action := "started"
if s.fd != 0 {
action = "reloaded"
}
glog.Printfln("%d: %s server %s listening on [%s]", gproc.Pid(), s.getProto(), action, s.addr)
err := s.httpServer.Serve(s.listener)
<-s.shutdownChan
return err

View File

@ -31,14 +31,17 @@ func Pid() int {
return os.Getpid()
}
// 获取父进程ID(gproc父进程不存在时则使用系统父进程)
// 获取父进程ID(gproc父进程如果当前进程本身就是父进程那么返回自身的pid不存在时则使用系统父进程)
func PPid() int {
if !IsChild() {
return Pid()
}
// gPROC_ENV_KEY_PPID_KEY为gproc包自定义的父进程
ppidValue := os.Getenv(gPROC_ENV_KEY_PPID_KEY)
if ppidValue != "" {
return gconv.Int(ppidValue)
}
return os.Getppid()
return PPidOS()
}
// 获取父进程ID(系统父进程)

View File

@ -11,7 +11,8 @@ func main() {
r.Response.Writeln("您可以同时通过HTTP和HTTPS方式看到该内容")
})
s.EnableHTTPS("/home/john/temp/server.crt", "/home/john/temp/server.key")
s.SetHTTPSPort(8198)
s.SetPort(8199)
s.SetHTTPSPort(8198, 8199)
s.SetPort(8200, 8300)
s.EnableAdmin()
s.Run()
}

View File

@ -0,0 +1,18 @@
package main
import (
"gitee.com/johng/gf/g/net/ghttp"
)
func main() {
s := ghttp.GetServer()
s.EnableAdmin()
s.BindHandler("/", func(r *ghttp.Request){
r.Response.Writeln("您可以同时通过HTTP和HTTPS方式看到该内容")
})
s.EnableHTTPS("/home/john/temp/server.crt", "/home/john/temp/server.key")
s.SetHTTPSPort(8198, 8199)
s.SetPort(8200, 8300)
s.EnableAdmin()
s.Run()
}