mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 12:17:53 +08:00
comment update for package ghttp
This commit is contained in:
parent
c8d253eb56
commit
5f8e6ad9ed
@ -16,6 +16,9 @@ import (
|
||||
"github.com/gogf/gf/os/gview"
|
||||
)
|
||||
|
||||
// utilAdmin is the controller for administration.
|
||||
type utilAdmin struct{}
|
||||
|
||||
// Index shows the administration page.
|
||||
func (p *utilAdmin) Index(r *Request) {
|
||||
data := map[string]interface{}{
|
||||
|
@ -3,7 +3,6 @@
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
// pprof封装.
|
||||
|
||||
package ghttp
|
||||
|
||||
@ -27,7 +26,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
gADMIN_ACTION_INTERVAL_LIMIT = 2000 // (毫秒)服务开启后允许执行管理操作的间隔限制
|
||||
// Allow executing management command after server starts after this interval in milliseconds.
|
||||
gADMIN_ACTION_INTERVAL_LIMIT = 2000
|
||||
gADMIN_ACTION_NONE = 0
|
||||
gADMIN_ACTION_RESTARTING = 1
|
||||
gADMIN_ACTION_SHUTINGDOWN = 2
|
||||
@ -36,48 +36,44 @@ const (
|
||||
gADMIN_GPROC_COMM_GROUP = "GF_GPROC_HTTP_SERVER"
|
||||
)
|
||||
|
||||
// 用于服务管理的对象
|
||||
type utilAdmin struct{}
|
||||
|
||||
// (进程级别)用于Web Server管理操作的互斥锁,保证管理操作的原子性
|
||||
// serverActionLocker is the locker for server administration operations.
|
||||
var serverActionLocker sync.Mutex
|
||||
|
||||
// (进程级别)用于记录上一次操作的时间(毫秒)
|
||||
// serverActionLastTime is timestamp in milliseconds of last administration operation.
|
||||
var serverActionLastTime = gtype.NewInt64(gtime.TimestampMilli())
|
||||
|
||||
// 当前服务进程所处的互斥管理操作状态
|
||||
// serverProcessStatus is the server status for operation of current process.
|
||||
var serverProcessStatus = gtype.NewInt()
|
||||
|
||||
// 重启Web Server,参数支持自定义重启的可执行文件路径,不传递时默认和原有可执行文件路径一致。
|
||||
// 针对*niux系统: 平滑重启
|
||||
// 针对windows : 完整重启
|
||||
// RestartAllServer restarts all the servers of the process.
|
||||
// The optional parameter <newExeFilePath> specifies the new binary file for creating process.
|
||||
func RestartAllServer(newExeFilePath ...string) error {
|
||||
serverActionLocker.Lock()
|
||||
defer serverActionLocker.Unlock()
|
||||
if err := checkProcessStatus(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkActionFrequence(); err != nil {
|
||||
if err := checkActionFrequency(); err != nil {
|
||||
return err
|
||||
}
|
||||
return restartWebServers("", newExeFilePath...)
|
||||
}
|
||||
|
||||
// 关闭所有的WebServer
|
||||
// ShutdownAllServer shuts down all servers of current process.
|
||||
func ShutdownAllServer() error {
|
||||
serverActionLocker.Lock()
|
||||
defer serverActionLocker.Unlock()
|
||||
if err := checkProcessStatus(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkActionFrequence(); err != nil {
|
||||
if err := checkActionFrequency(); err != nil {
|
||||
return err
|
||||
}
|
||||
shutdownWebServers()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检查当前服务进程的状态
|
||||
// checkProcessStatus checks the server status of current process.
|
||||
func checkProcessStatus() error {
|
||||
status := serverProcessStatus.Val()
|
||||
if status > 0 {
|
||||
@ -91,8 +87,9 @@ func checkProcessStatus() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检测当前操作的频繁度
|
||||
func checkActionFrequence() error {
|
||||
// checkActionFrequency checks the operation frequency.
|
||||
// It returns error if it is too frequency.
|
||||
func checkActionFrequency() error {
|
||||
interval := gtime.TimestampMilli() - 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))
|
||||
@ -101,16 +98,16 @@ func checkActionFrequence() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 平滑重启:创建一个子进程,通过环境变量传参
|
||||
// forkReloadProcess creates a new child process and copies the fd to child process.
|
||||
func forkReloadProcess(newExeFilePath ...string) error {
|
||||
path := os.Args[0]
|
||||
if len(newExeFilePath) > 0 {
|
||||
path = newExeFilePath[0]
|
||||
}
|
||||
p := gproc.NewProcess(path, os.Args, os.Environ())
|
||||
// 创建新的服务进程,子进程自动从父进程复制文件描述来监听同样的端口
|
||||
sfm := getServerFdMap()
|
||||
// 将sfm中的fd按照子进程创建时的文件描述符顺序进行整理,以便子进程获取到正确的fd
|
||||
var (
|
||||
p = gproc.NewProcess(path, os.Args, os.Environ())
|
||||
sfm = getServerFdMap()
|
||||
)
|
||||
for name, m := range sfm {
|
||||
for fdk, fdv := range m {
|
||||
if len(fdv) > 0 {
|
||||
@ -138,13 +135,12 @@ func forkReloadProcess(newExeFilePath ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 完整重启:创建一个新的子进程
|
||||
// forkRestartProcess creates a new server process.
|
||||
func forkRestartProcess(newExeFilePath ...string) error {
|
||||
path := os.Args[0]
|
||||
if len(newExeFilePath) > 0 {
|
||||
path = newExeFilePath[0]
|
||||
}
|
||||
// 去掉平滑重启的环境变量参数
|
||||
os.Unsetenv(gADMIN_ACTION_RELOAD_ENVKEY)
|
||||
env := os.Environ()
|
||||
env = append(env, gADMIN_ACTION_RESTART_ENVKEY+"=1")
|
||||
@ -156,7 +152,7 @@ func forkRestartProcess(newExeFilePath ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取所有Web Server的文件描述符map
|
||||
// getServerFdMap returns all the servers name to file descriptor mapping as map.
|
||||
func getServerFdMap() map[string]listenerFdMap {
|
||||
sfm := make(map[string]listenerFdMap)
|
||||
serverMapping.RLockFunc(func(m map[string]interface{}) {
|
||||
@ -167,7 +163,7 @@ func getServerFdMap() map[string]listenerFdMap {
|
||||
return sfm
|
||||
}
|
||||
|
||||
// 二进制转换为FdMap
|
||||
// bufferToServerFdMap converts binary content to fd map.
|
||||
func bufferToServerFdMap(buffer []byte) map[string]listenerFdMap {
|
||||
sfm := make(map[string]listenerFdMap)
|
||||
if len(buffer) > 0 {
|
||||
@ -183,16 +179,17 @@ func bufferToServerFdMap(buffer []byte) map[string]listenerFdMap {
|
||||
return sfm
|
||||
}
|
||||
|
||||
// Web Server重启
|
||||
// restartWebServers restarts all servers.
|
||||
func restartWebServers(signal string, newExeFilePath ...string) error {
|
||||
serverProcessStatus.Set(gADMIN_ACTION_RESTARTING)
|
||||
if runtime.GOOS == "windows" {
|
||||
if len(signal) > 0 {
|
||||
// 在终端信号下,立即执行重启操作
|
||||
// Controlled by signal.
|
||||
forceCloseWebServers()
|
||||
forkRestartProcess(newExeFilePath...)
|
||||
} else {
|
||||
// 非终端信号下,异步1秒后再执行重启,目的是让接口能够正确返回结果,否则接口会报错(因为web server关闭了)
|
||||
// Controlled by web page.
|
||||
// It should ensure the response wrote to client and then close all servers gracefully.
|
||||
gtimer.SetTimeout(time.Second, func() {
|
||||
forceCloseWebServers()
|
||||
forkRestartProcess(newExeFilePath...)
|
||||
@ -215,18 +212,15 @@ func restartWebServers(signal string, newExeFilePath ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 关闭所有Web Server
|
||||
// shutdownWebServers shuts down all servers.
|
||||
func shutdownWebServers(signal ...string) {
|
||||
serverProcessStatus.Set(gADMIN_ACTION_SHUTINGDOWN)
|
||||
if len(signal) > 0 {
|
||||
glog.Printf("%d: server shutting down by signal: %s", gproc.Pid(), signal[0])
|
||||
// 在终端信号下,立即执行关闭操作
|
||||
forceCloseWebServers()
|
||||
allDoneChan <- struct{}{}
|
||||
} else {
|
||||
glog.Printf("%d: server shutting down by api", gproc.Pid())
|
||||
// 非终端信号下,异步1秒后再执行关闭,
|
||||
// 目的是让接口能够正确返回结果,否则接口会报错(因为web server关闭了)
|
||||
gtimer.SetTimeout(time.Second, func() {
|
||||
forceCloseWebServers()
|
||||
allDoneChan <- struct{}{}
|
||||
@ -234,8 +228,7 @@ func shutdownWebServers(signal ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// 关优雅闭进程所有端口的Web Server服务
|
||||
// 注意,只是关闭Web Server服务,并不是退出进程
|
||||
// gracefulShutdownWebServers gracefully shuts down all servers.
|
||||
func gracefulShutdownWebServers() {
|
||||
serverMapping.RLockFunc(func(m map[string]interface{}) {
|
||||
for _, v := range m {
|
||||
@ -246,8 +239,7 @@ func gracefulShutdownWebServers() {
|
||||
})
|
||||
}
|
||||
|
||||
// 强制关闭进程所有端口的Web Server服务
|
||||
// 注意,只是关闭Web Server服务,并不是退出进程
|
||||
// forceCloseWebServers forced shuts down all servers.
|
||||
func forceCloseWebServers() {
|
||||
serverMapping.RLockFunc(func(m map[string]interface{}) {
|
||||
for _, v := range m {
|
||||
@ -258,7 +250,7 @@ func forceCloseWebServers() {
|
||||
})
|
||||
}
|
||||
|
||||
// 异步监听进程间消息
|
||||
// handleProcessMessage listens the signal from system.
|
||||
func handleProcessMessage() {
|
||||
for {
|
||||
if msg := gproc.Receive(gADMIN_GPROC_COMM_GROUP); msg != nil {
|
||||
|
@ -15,10 +15,10 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// 进程信号量监听消息队列
|
||||
// procSignalChan is the channel for listening the signal.
|
||||
var procSignalChan = make(chan os.Signal)
|
||||
|
||||
// 信号量处理
|
||||
// handleProcessSignal handles all signal from system.
|
||||
func handleProcessSignal() {
|
||||
var sig os.Signal
|
||||
signal.Notify(
|
||||
@ -35,12 +35,12 @@ func handleProcessSignal() {
|
||||
sig = <-procSignalChan
|
||||
intlog.Printf(`signal received: %s`, sig.String())
|
||||
switch sig {
|
||||
// 进程终止,停止所有子进程运行
|
||||
// Stop the servers.
|
||||
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGABRT:
|
||||
shutdownWebServers(sig.String())
|
||||
return
|
||||
|
||||
// 用户信号,重启服务
|
||||
// Restart the servers.
|
||||
case syscall.SIGUSR1:
|
||||
restartWebServers(sig.String())
|
||||
return
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
package ghttp
|
||||
|
||||
// windows不处理信号量
|
||||
// handleProcessSignal does nothing on windows platform.
|
||||
func handleProcessSignal() {
|
||||
|
||||
}
|
||||
|
@ -10,26 +10,32 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// SetCookieMaxAge sets the CookieMaxAge for server.
|
||||
func (s *Server) SetCookieMaxAge(ttl time.Duration) {
|
||||
s.config.CookieMaxAge = ttl
|
||||
}
|
||||
|
||||
// SetCookiePath sets the CookiePath for server.
|
||||
func (s *Server) SetCookiePath(path string) {
|
||||
s.config.CookiePath = path
|
||||
}
|
||||
|
||||
// SetCookieDomain sets the CookieDomain for server.
|
||||
func (s *Server) SetCookieDomain(domain string) {
|
||||
s.config.CookieDomain = domain
|
||||
}
|
||||
|
||||
// GetCookieMaxAge returns the CookieMaxAge of server.
|
||||
func (s *Server) GetCookieMaxAge() time.Duration {
|
||||
return s.config.CookieMaxAge
|
||||
}
|
||||
|
||||
// GetCookiePath returns the CookiePath of server.
|
||||
func (s *Server) GetCookiePath() string {
|
||||
return s.config.CookiePath
|
||||
}
|
||||
|
||||
// GetCookieDomain returns CookieDomain of server.
|
||||
func (s *Server) GetCookieDomain() string {
|
||||
return s.config.CookieDomain
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ package ghttp
|
||||
|
||||
import "github.com/gogf/gf/internal/intlog"
|
||||
|
||||
// 设置日志目录,只有在设置了日志目录的情况下才会输出日志到日志文件中。
|
||||
// SetLogPath sets the log path for server.
|
||||
// It logs content to file only if the log path is set.
|
||||
func (s *Server) SetLogPath(path string) {
|
||||
if len(path) == 0 {
|
||||
return
|
||||
@ -19,38 +20,37 @@ func (s *Server) SetLogPath(path string) {
|
||||
s.config.AccessLogEnabled = true
|
||||
}
|
||||
|
||||
// 设置日志内容是否输出到终端,默认情况下只有错误日志才会自动输出到终端。
|
||||
// 如果需要输出请求日志到终端,默认情况下使用SetAccessLogEnabled方法开启请求日志特性即可。
|
||||
// SetLogStdout sets whether output the logging content to stdout.
|
||||
func (s *Server) SetLogStdout(enabled bool) {
|
||||
s.config.LogStdout = enabled
|
||||
}
|
||||
|
||||
// 设置是否开启access log日志功能
|
||||
// SetAccessLogEnabled enables/disables the access log.
|
||||
func (s *Server) SetAccessLogEnabled(enabled bool) {
|
||||
s.config.AccessLogEnabled = enabled
|
||||
}
|
||||
|
||||
// 设置是否开启error log日志功能
|
||||
// SetErrorLogEnabled enables/disables the error log.
|
||||
func (s *Server) SetErrorLogEnabled(enabled bool) {
|
||||
s.config.ErrorLogEnabled = enabled
|
||||
}
|
||||
|
||||
// 设置是否开启error stack打印功能
|
||||
// SetErrorStack enables/disables the error stack feature.
|
||||
func (s *Server) SetErrorStack(enabled bool) {
|
||||
s.config.ErrorStack = enabled
|
||||
}
|
||||
|
||||
// 获取日志目录
|
||||
// GetLogPath returns the log path.
|
||||
func (s *Server) GetLogPath() string {
|
||||
return s.config.LogPath
|
||||
}
|
||||
|
||||
// access log日志功能是否开启
|
||||
// IsAccessLogEnabled checks whether the access log enabled.
|
||||
func (s *Server) IsAccessLogEnabled() bool {
|
||||
return s.config.AccessLogEnabled
|
||||
}
|
||||
|
||||
// error log日志功能是否开启
|
||||
// IsErrorLogEnabled checks whether the error log enabled.
|
||||
func (s *Server) IsErrorLogEnabled() bool {
|
||||
return s.config.ErrorLogEnabled
|
||||
}
|
||||
|
@ -6,18 +6,23 @@
|
||||
|
||||
package ghttp
|
||||
|
||||
// SetNameToUriType sets the NameToUriType for server.
|
||||
func (s *Server) SetNameToUriType(t int) {
|
||||
s.config.NameToUriType = t
|
||||
}
|
||||
|
||||
// SetDumpRouterMap sets the DumpRouterMap for server.
|
||||
// If DumpRouterMap is enabled, it automatically dumps the route map when server starts.
|
||||
func (s *Server) SetDumpRouterMap(enabled bool) {
|
||||
s.config.DumpRouterMap = enabled
|
||||
}
|
||||
|
||||
// SetClientMaxBodySize sets the ClientMaxBodySize for server.
|
||||
func (s *Server) SetClientMaxBodySize(maxSize int64) {
|
||||
s.config.ClientMaxBodySize = maxSize
|
||||
}
|
||||
|
||||
// SetFormParsingMemory sets the FormParsingMemory for server.
|
||||
func (s *Server) SetFormParsingMemory(maxMemory int64) {
|
||||
s.config.FormParsingMemory = maxMemory
|
||||
}
|
||||
|
@ -6,16 +6,19 @@
|
||||
|
||||
package ghttp
|
||||
|
||||
// SetRewrite sets rewrites for static URI for server.
|
||||
func (s *Server) SetRewrite(uri string, rewrite string) {
|
||||
s.config.Rewrites[uri] = rewrite
|
||||
}
|
||||
|
||||
// SetRewriteMap sets the rewrite map for server.
|
||||
func (s *Server) SetRewriteMap(rewrites map[string]string) {
|
||||
for k, v := range rewrites {
|
||||
s.config.Rewrites[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetRouteOverWrite sets the RouteOverWrite for server.
|
||||
func (s *Server) SetRouteOverWrite(enabled bool) {
|
||||
s.config.RouteOverWrite = enabled
|
||||
}
|
||||
|
@ -12,22 +12,27 @@ import (
|
||||
"github.com/gogf/gf/os/gsession"
|
||||
)
|
||||
|
||||
// SetSessionMaxAge sets the SessionMaxAge for server.
|
||||
func (s *Server) SetSessionMaxAge(ttl time.Duration) {
|
||||
s.config.SessionMaxAge = ttl
|
||||
}
|
||||
|
||||
// SetSessionIdName sets the SessionIdName for server.
|
||||
func (s *Server) SetSessionIdName(name string) {
|
||||
s.config.SessionIdName = name
|
||||
}
|
||||
|
||||
// SetSessionStorage sets the SessionStorage for server.
|
||||
func (s *Server) SetSessionStorage(storage gsession.Storage) {
|
||||
s.config.SessionStorage = storage
|
||||
}
|
||||
|
||||
// GetSessionMaxAge returns the SessionMaxAge of server.
|
||||
func (s *Server) GetSessionMaxAge() time.Duration {
|
||||
return s.config.SessionMaxAge
|
||||
}
|
||||
|
||||
// GetSessionIdName returns the SessionIdName of server.
|
||||
func (s *Server) GetSessionIdName() string {
|
||||
return s.config.SessionIdName
|
||||
}
|
||||
|
@ -92,9 +92,8 @@ func (s *Server) AddStaticPath(prefix string, path string) {
|
||||
path: realPath,
|
||||
}
|
||||
if len(s.config.StaticPaths) > 0 {
|
||||
// 先添加item
|
||||
s.config.StaticPaths = append(s.config.StaticPaths, addItem)
|
||||
// 按照prefix从长到短进行排序
|
||||
// Sort the array by length of prefix from short to long.
|
||||
array := garray.NewSortedArray(func(v1, v2 interface{}) int {
|
||||
s1 := gconv.String(v1)
|
||||
s2 := gconv.String(v2)
|
||||
@ -107,7 +106,7 @@ func (s *Server) AddStaticPath(prefix string, path string) {
|
||||
for _, v := range s.config.StaticPaths {
|
||||
array.Add(v.prefix)
|
||||
}
|
||||
// 按照重新排序的顺序重新添加item
|
||||
// Add the items to paths by previous sorted slice.
|
||||
paths := make([]staticPathItem, 0)
|
||||
for _, v := range array.Slice() {
|
||||
for _, item := range s.config.StaticPaths {
|
||||
|
@ -3,9 +3,6 @@
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
//
|
||||
// HTTP Cookie管理对象,
|
||||
// 由于Cookie是和HTTP请求挂钩的,因此被包含到 ghttp 包中进行管理。
|
||||
|
||||
package ghttp
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user