gpt4 book ai didi

go - 有什么办法可以防止默认的 golang 程序完成

转载 作者:数据小太阳 更新时间:2023-10-29 03:36:00 25 4
gpt4 key购买 nike

我有一个使用 websocket 连接和数据库的服务器。有些用户可以通过套接字连接,所以我需要在数据库中增加他们的“在线”;在他们断开连接的那一刻,我也减少了他们在数据库中的“在线”字段。但如果服务器出现故障,我会使用在线用户的局部变量 replica map[string]int。所以我需要推迟服务器关闭,直到它完成一个数据库请求,该请求根据我的变量副本减少所有用户“在线”,因为在这种情况下套接字连接不会发送默认的“关闭”事件。

我找到了一个包 github.com/xlab/closer 来处理一些系统调用并且可以在程序完成之前做一些 Action ,但是我的数据库请求不能以这种方式工作(下面的代码)

func main() {
...
// trying to handle program finish event
closer.Bind(cleanupSocketConnections(&pageHandler))
...
}

// function that handles program finish event
func cleanupSocketConnections(p *controllers.PageHandler) func() {
return func() {
p.PageService.ResetOnlineUsers()
}
}

// this map[string]int contains key=userId, value=count of socket connections
type PageService struct {
Users map[string]int
}

func (p *PageService) ResetOnlineUsers() {
for userId, count := range p.Users {
// decrease online of every user in program variable
InfoService{}.DecreaseInfoOnline(userId, count)
}
}

也许我使用不当,或者有更好的方法来防止默认程序完成?

最佳答案

首先,当您所说的服务器“崩溃”时执行任务非常复杂,因为崩溃可能意味着很多事情,当您的服务器出现严重问题时,没有任何东西可以保证清理功能的执行。

从工程的角度来看(如果设置用户在故障时离线是如此重要),最好是在另一台服务器上有一个辅助服务,它接收用户连接和断开事件以及 ping 事件,如果它没有收到在设置的超时更新服务认为您的服务器已关闭并继续将每个用户设置为离线。

回到你的问题,使用 defer 和等待终止信号应该可以覆盖 99% 的情况。我注释了代码以解释逻辑。

// AllUsersOffline is called when the program is terminated, it takes a *sync.Once to make sure this function is performed only
// one time, since it might be called from different goroutines.
func AllUsersOffline(once *sync.Once) {
once.Do(func() {
fmt.Print("setting all users offline...")
// logic to set all users offline
})
}

// CatchSigs catches termination signals and executes f function at the end
func CatchSigs(f func()) {
cSig := make(chan os.Signal, 1)
// watch for these signals
signal.Notify(cSig, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGHUP) // these are the termination signals in GNU => https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
// wait for them
sig := <- cSig
fmt.Printf("received signal: %s", sig)
// execute f
f()
}
func main() {
/* code */
// the once is used to make sure AllUsersOffline is performed ONE TIME.
usersOfflineOnce := &sync.Once{}
// catch termination signals
go CatchSigs(func() {
// when a termination signal is caught execute AllUsersOffline function
AllUsersOffline(usersOfflineOnce)
})
// deferred functions are called even in case of panic events, although execution is not to take for granted (OOM errors etc)
defer AllUsersOffline(usersOfflineOnce)
/* code */
// run server
err := server.Run()
if err != nil {
// error logic here
}
// bla bla bla
}

关于go - 有什么办法可以防止默认的 golang 程序完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57934981/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com