From 730664ee11bbbfc168f64fcddb6fd8437410fc68 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 16 May 2018 22:32:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90ghttp.Server=E7=83=AD?= =?UTF-8?q?=E9=87=8D=E5=90=AF=E6=9C=BA=E5=88=B6=E5=9C=A8Windows=E4=B8=8B?= =?UTF-8?q?=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/net/ghttp/ghttp_server.go | 15 ----- g/net/ghttp/ghttp_server_admin.go | 79 ++++++++++++++++++++++++-- g/net/ghttp/ghttp_server_comm_child.go | 2 +- g/net/ghttp/ghttp_server_comm_main.go | 4 +- 4 files changed, 77 insertions(+), 23 deletions(-) diff --git a/g/net/ghttp/ghttp_server.go b/g/net/ghttp/ghttp_server.go index 773155342..ed423a195 100644 --- a/g/net/ghttp/ghttp_server.go +++ b/g/net/ghttp/ghttp_server.go @@ -321,21 +321,6 @@ func (s *Server) startServer(fdMap listenerFdMap) { s.status = 1 } -// 平滑重启Web Server -func (s *Server) Reload() { - sendProcessMsg(gproc.Pid(), gMSG_RELOAD, nil) -} - -// 完整重启Web Server -func (s *Server) Restart() { - sendProcessMsg(gproc.Pid(), gMSG_RESTART, nil) -} - -// 关闭Web Server -func (s *Server) Shutdown() { - sendProcessMsg(gproc.PPid(), gMSG_SHUTDOWN, nil) -} - // 获取当前监听的文件描述符信息,构造成map返回 func (s *Server) getListenerFdMap() map[string]string { m := map[string]string { diff --git a/g/net/ghttp/ghttp_server_admin.go b/g/net/ghttp/ghttp_server_admin.go index 11c09ea9c..bc785c184 100644 --- a/g/net/ghttp/ghttp_server_admin.go +++ b/g/net/ghttp/ghttp_server_admin.go @@ -11,11 +11,27 @@ import ( "strings" "gitee.com/johng/gf/g/os/gview" "runtime" + "gitee.com/johng/gf/g/os/gproc" + "sync" + "gitee.com/johng/gf/g/os/gtime" + "errors" + "fmt" + "gitee.com/johng/gf/g/container/gtype" +) + +const ( + gADMIN_ACTION_INTERVAL_LIMIT = 0 // (毫秒)每一次执行管理操作的间隔限制 ) // 用于服务管理的对象 type utilAdmin struct {} +// (进程级别)用于Web Server管理操作的互斥锁,保证管理操作的原子性 +var serverActionLocker sync.Mutex + +// (进程级别)用于记录上一次操作的时间(毫秒) +var serverActionLastTime = gtype.NewInt64(gtime.Millisecond()) + // 服务管理首页 func (p *utilAdmin) Index(r *Request) { data := map[string]interface{}{ @@ -41,21 +57,31 @@ func (p *utilAdmin) Reload(r *Request) { if runtime.GOOS == "windows" { p.Restart(r) } else { - r.Response.Write("reload server") - r.Server.Reload() + if err := r.Server.Reload(); err == nil { + r.Response.Write("server reloaded") + } else { + r.Response.Write(err.Error()) + } } } // 服务完整重启 func (p *utilAdmin) Restart(r *Request) { - r.Response.Write("restart server") - r.Server.Restart() + if err := r.Server.Restart(); err == nil { + r.Response.Write("server restarted") + } else { + r.Response.Write(err.Error()) + } } // 服务关闭 func (p *utilAdmin) Shutdown(r *Request) { - r.Response.Write("shutdown server") r.Server.Shutdown() + if err := r.Server.Shutdown(); err == nil { + r.Response.Write("server shutdown") + } else { + r.Response.Write(err.Error()) + } } @@ -66,4 +92,47 @@ func (s *Server) EnableAdmin(pattern...string) { p = pattern[0] } s.BindObject(p, &utilAdmin{}) +} + +// 平滑重启Web Server +func (s *Server) Reload() error { + serverActionLocker.Lock() + defer serverActionLocker.Unlock() + if err := s.checkActionFrequence(); err != nil { + return err + } + sendProcessMsg(gproc.Pid(), gMSG_RELOAD, nil) + return nil +} + +// 完整重启Web Server +func (s *Server) Restart() error { + serverActionLocker.Lock() + defer serverActionLocker.Unlock() + if err := s.checkActionFrequence(); err != nil { + return err + } + sendProcessMsg(gproc.Pid(), gMSG_RESTART, nil) + return nil +} + +// 关闭Web Server +func (s *Server) Shutdown() error { + serverActionLocker.Lock() + defer serverActionLocker.Unlock() + if err := s.checkActionFrequence(); err != nil { + return err + } + sendProcessMsg(gproc.PPid(), gMSG_SHUTDOWN, nil) + return nil +} + +// 检测当前操作的频繁度 +func (s *Server) checkActionFrequence() error { + interval := gtime.Millisecond() - serverActionLastTime.Val() + if interval < gADMIN_ACTION_INTERVAL_LIMIT { + return errors.New(fmt.Sprintf("too frequent action, please retry in %d ms", gADMIN_ACTION_INTERVAL_LIMIT - interval)) + } + serverActionLastTime.Set(gtime.Millisecond()) + return nil } \ No newline at end of file diff --git a/g/net/ghttp/ghttp_server_comm_child.go b/g/net/ghttp/ghttp_server_comm_child.go index 5938c1c1d..d9362eddb 100644 --- a/g/net/ghttp/ghttp_server_comm_child.go +++ b/g/net/ghttp/ghttp_server_comm_child.go @@ -24,7 +24,7 @@ const ( gPROC_CHILD_MAX_IDLE_TIME = 3000 // 子进程闲置时间(未开启心跳机制的时间) ) -// 心跳消息 +// 心跳处理(方法为空,逻辑放到公共通信switch中进行处理) func onCommChildHeartbeat(pid int, data []byte) { } diff --git a/g/net/ghttp/ghttp_server_comm_main.go b/g/net/ghttp/ghttp_server_comm_main.go index 04fa6a8ed..3ce65e742 100644 --- a/g/net/ghttp/ghttp_server_comm_main.go +++ b/g/net/ghttp/ghttp_server_comm_main.go @@ -26,9 +26,9 @@ func onCommMainStart(pid int, data []byte) { sendProcessMsg(p.Pid(), gMSG_START, nil) } -// 心跳处理 +// 心跳处理(方法为空,逻辑放到公共通信switch中进行处理) func onCommMainHeartbeat(pid int, data []byte) { - updateProcessCommTime(pid) + } // 平滑重启服务