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

时间:2019-09-14 11:20:14

标签: go websocket

我有一个使用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)

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

2 个答案:

答案 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
}