我有一个使用websocket连接的服务器和一个数据库。有些用户可以通过套接字连接,因此我需要在db中增加其“联机”;在断开连接的同时,我还减小了db中的“在线”字段。但是如果服务器发生故障,我会在线使用用户的本地变量副本map [string] int。因此,我需要推迟服务器关闭,直到它完成根据我的变量副本使所有用户“联机”的数据库请求递减的数据库请求为止,因为这样,套接字连接不会发送默认的“关闭”事件。
我找到了一个包github.com/xlab/closer,它可以处理一些系统调用,并且可以在程序完成之前执行一些操作,但是我的数据库请求无法以这种方式工作(下面的代码)
import random
stats = []
def make_rand_score():
score = [random.randint(1, 6) for n in range(4)]
score.remove(min(score))
return score
stats = [make_rand_score() for i in range(5)]
print(stats)
也许我使用不正确,或者有更好的方法防止默认程序完成?
答案 0 :(得分:0)
我认为您需要查看 go例程 和 频道 。
(也许)有用的东西:
https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/
答案 1 :(得分:0)
首先,当您所说的服务器“崩溃”时,执行任务非常复杂,因为崩溃可能意味着很多事情,而当服务器出现严重问题时,没有什么可以保证清理功能。
>从工程角度来看(如果使用户处于崩溃状态非常重要),最好是在另一台服务器上拥有一个辅助服务,以接收用户连接和断开事件以及ping事件(如果未接收到)会在设置的超时时间内更新,该服务会将您的服务器视为停机,然后继续将每个用户设置为离线。
回到您的问题,使用延迟并等待终止信号应该可以覆盖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
}