我正在创建一个 Mattermost 机器人。在 websocket 连接在随机时间段(1 分钟、8 分钟、2 小时等)后收到 ping 超时 (PingTimeoutChannel) 后,它会停止响应。Mattermost 服务器是 v.5.13,API v.4。
机器人通过创建新的 Client4 连接到 Mattermost API。接下来,它以用户身份登录,并在创建一个接收到授权令牌的 Websocket 客户端之后。它开始监听所有频道,当它收到一个事件,它是一条发给他的消息(@botname),它会自动响应(创建 model.post)。
我选择使用简单的用户名/密码身份验证进行登录,就像在 Mattermost 示例机器人中一样。但是,我尝试将其重写为个人访问令牌身份验证(如此处),因为我认为它可以解决超时问题。但是,此解决方案不再起作用,它在尝试以这种方式登录时给出“无效或过期的会话错误,请重新登录”。
所以我放弃了这个想法,开始寻找超时发生的地方。服务器 ping 正常,websocket 不正常。我尝试了很多方法,直到我重新连接(通过再次创建新的 Mattermost API 和 Websocket 客户端)。机器人仍然没有响应。我已经没有想法了。
Websocket 连接(跳过错误处理):
if config.BotCfg.Port == "443" {
protocol = "https"
secure = true
}
config.ConnectionCfg.Client = model.NewAPIv4Client(fmt.Sprintf("%s://%s:%s", protocol, config.BotCfg.Server, config.BotCfg.Port))
user,resp := config.ConnectionCfg.Client.Login(config.BotCfg.BotName, config.BotCfg.Password)
setBotTeam()
if limit.Users == nil {
limit.SetUsersList()
}
ws := "ws"
if secure {
ws = "wss"
}
if Websocket != nil {
Websocket.Close()
}
websocket, err := model.NewWebSocketClient4(fmt.Sprintf("%s://%s:%s", ws, config.BotCfg.Server, config.BotCfg.Port), config.ConnectionCfg.Client.AuthToken)
听力功能:
for {
select {
case <-connection.Websocket.PingTimeoutChannel:
logs.WriteToFile("Websocket ping timeout. Connecting again.")
log.Println("Websocket ping timeout. Connecting again.")
mux.Lock()
connection.Connect()
mux.Unlock()
case event := <-connection.Websocket.EventChannel:
mux.Lock()
if event != nil {
if event.IsValid() && isMessage(event.Event){
handleEvent(event)
}
}
mux.Unlock()
}
}
}()
// block to the go function
select {}
我希望机器人能够连续运行。如果您对如何解决此问题有任何建议,我将不胜感激!
编辑:正如Cerise建议的那样,我将 SIGQUIT 添加到退出函数并运行了一个竞赛检测器。通过从案例事件中删除一个 if 来修复数据竞争问题:= [...]。种族检测器不再报告任何问题,但是机器人在一段时间后仍然停止响应。
我发现第一次 PingTimeout 发生时,对等方停止响应,直到我重新启动应用程序。Websocket 的重新连接没有帮助。但是,我实际上不知道如何解决这个问题,或者解决方案是否存在。