comment update for package ghttp

This commit is contained in:
John 2020-05-01 03:31:04 +08:00
parent c8d253eb56
commit 5f8e6ad9ed
11 changed files with 68 additions and 58 deletions

View File

@ -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{}{

View File

@ -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 {

View File

@ -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

View File

@ -8,7 +8,7 @@
package ghttp
// windows不处理信号量
// handleProcessSignal does nothing on windows platform.
func handleProcessSignal() {
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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