#slack RTM api scala 中的“{}”消息后断开连接

#slack RTM api disconnection following "{}" message in scala

我目前正在尝试使用 RTM API 可用的 Scala 创建#slack 机器人。

我已经设法得到一个基本功能的机器人,它用 "pong" 响应 "ping"。

我目前遇到的问题是 websocket 连接在流打开后每隔几分钟系统关闭。

我目前正在为 websockets 使用以下库:https://github.com/jfarcand/WCS

在这一点上,我不完全确定是什么导致连接在从#slack RTM 流接收到空 JSON 消息 ({}) 后断开。

如有任何帮助,我们将不胜感激。

这里是相关的连接和监听代码:

def connect(): Unit ={

    if(rec_url == "")
      slack = ws.open(rtm_url)
    else {
      h.debug("Attempting to reconnect")
      slack = WebSocket().open(rec_url) // TODO: need to completely close the connection before trying to create a new one.
    }


    initRTM()
  }

  // Initialize Real Time Messaging
  def initRTM(): Unit = {

    h.debug("\nOpening Real Time Messaging socket")

    slack.listener(new TextListener {

        override def onOpen: Unit = {
          h.debug("Websocket connection open")
          status = 1
        }

        override def onClose: Unit = {
          h.debug("Websocket connection closed, reconnecting...")
          slack.shutDown

          status = 0
        }

        override def onError(t: Throwable): Unit ={
          h.debug("Websocket Error encountered")
          t.printStackTrace()
          h.debug(t.getMessage)
        }

        override def onMessage(message: String) {
          h.debug("Message received: "+message)
          val body: JsValue = Json.parse(message)

          try {

            if(body.as[JsObject].keys.contains("type")){
              val m_type = (body \ "type").as[String]

              m_type match {

                case "hello" => ;
                case "reconnect_url" => setReconnectUrl((body \ "url").as[String])
                case "message" => processMessage(body)
                case _ => h.debug("Unprocessed message type: " + m_type)

              }
            }
          } catch {
            case e: Exception=> e.printStackTrace()
          }
        }

      })

    while(slack.isOpen){

    }

    h.debug("connection is closed")

    connect()


  }

这是控制台的输出:

Opening Real Time Messaging socket
INFO - Websocket connection open
INFO - Message received: {"type":"hello"}
INFO - Message received: {"reply_to":0,"type":"message","channel":"D1NCSAU12","user":"U1NCSAU0L","text":"pong","ts":"1467558776.000079"}
INFO - Message received: {"type":"reconnect_url","url":"wss://mpmulti-c6k1.slack-msgs.com/websocket/x4UkvMwZeNqFuyZ_YsxjLNi_OIOzqHisL6sHC3DB0QRnKoG-VH8Qr361SlSprlWb6WjzDhw6j5Pj0FiFFYTjoiCLwM-i863os0xWkjUGJJbUoKUmtlG22e3lTTAFuuIFg2TTI7W-0XfU4HJB2nvbjy_hKCwVQ7uIIlrr6fYi_ms="}
INFO - Reconnect URL Set to: wss://mpmulti-c6k1.slack-msgs.com/websocket/x4UkvMwZeNqFuyZ_YsxjLNi_OIOzqHisL6sHC3DB0QRnKoG-VH8Qr361SlSprlWb6WjzDhw6j5Pj0FiFFYTjoiCLwM-i863os0xWkjUGJJbUoKUmtlG22e3lTTAFuuIFg2TTI7W-0XfU4HJB2nvbjy_hKCwVQ7uIIlrr6fYi_ms=
INFO - Message received: {"type":"presence_change","presence":"active","user":"U1NCSAU0L"}
INFO - Unprocessed message type: presence_change
11:23:18.790 [Hashed wheel timer #1] DEBUG com.ning.http.client.providers.netty.channel.pool.DefaultChannelPool - Closed 0 connections out of 0 in 0ms
INFO - Message received: {"type":"user_typing","channel":"D1NCSAU12","user":"U1MP4A19R"}
INFO - Unprocessed message type: user_typing
INFO - Message received: {"type":"message","channel":"D1NCSAU12","user":"U1MP4A19R","text":"ping","ts":"1467559430.000080","team":"T1MQWNFR8"}
INFO - User typed 'ping'
INFO - Answer: {"id":0,"type":"message","channel":"D1NCSAU12","text":"pong"}
INFO - Message received: {"ok":true,"reply_to":0,"ts":"1467559430.000081","text":"pong"}
INFO - Message received: {"type":"user_typing","channel":"D1NCSAU12","user":"U1MP4A19R"}
INFO - Unprocessed message type: user_typing
INFO - Message received: {"type":"message","channel":"D1NCSAU12","user":"U1MP4A19R","text":"ping","ts":"1467559432.000082","team":"T1MQWNFR8"}
INFO - User typed 'ping'
INFO - Answer: {"id":1,"type":"message","channel":"D1NCSAU12","text":"pong"}
INFO - Message received: {"ok":true,"reply_to":1,"ts":"1467559432.000083","text":"pong"}
INFO - Message received: {"type":"user_typing","channel":"D1NCSAU12","user":"U1MP4A19R"}
INFO - Unprocessed message type: user_typing
INFO - Message received: {"type":"message","channel":"D1NCSAU12","user":"U1MP4A19R","text":"ping","ts":"1467559434.000084","team":"T1MQWNFR8"}
INFO - User typed 'ping'
INFO - Answer: {"id":2,"type":"message","channel":"D1NCSAU12","text":"pong"}
INFO - Message received: {"ok":true,"reply_to":2,"ts":"1467559434.000085","text":"pong"}
INFO - Message received: {"type":"user_typing","channel":"D1NCSAU12","user":"U1MP4A19R"}
INFO - Unprocessed message type: user_typing
INFO - Message received: {"type":"message","channel":"D1NCSAU12","user":"U1MP4A19R","text":"ping","ts":"1467559448.000086","team":"T1MQWNFR8"}
INFO - User typed 'ping'
INFO - Answer: {"id":3,"type":"message","channel":"D1NCSAU12","text":"pong"}
INFO - Message received: {"ok":true,"reply_to":3,"ts":"1467559448.000087","text":"pong"}
INFO - Message received: {"type":"user_typing","channel":"D1NCSAU12","user":"U1MP4A19R"}
INFO - Unprocessed message type: user_typing
INFO - Message received: {"type":"message","channel":"D1NCSAU12","user":"U1MP4A19R","text":"ping ping","ts":"1467559452.000088","team":"T1MQWNFR8"}
11:24:18.889 [Hashed wheel timer #1] DEBUG com.ning.http.client.providers.netty.channel.pool.DefaultChannelPool - Closed 0 connections out of 0 in 0ms
INFO - Message received: {"type":"reconnect_url","url":"wss://mpmulti-lbww.slack-msgs.com/websocket/u61Fem7nt3c1DP35C1So6S-Q3QnP0wcY4BeKMG6GZBpjo32E_rGM0YhwH-M_i6uGdezSgzr8R6BmM4eC7ZcwGaAR38GRi2VFyEM7REgtCO0Hd6FAsguHS63TwCI65UwBCkcS_gEFdpoI5tD0az4cBWtdfj1yXbn1iOwpiH_BALg="}
INFO - Reconnect URL Set to: wss://mpmulti-lbww.slack-msgs.com/websocket/u61Fem7nt3c1DP35C1So6S-Q3QnP0wcY4BeKMG6GZBpjo32E_rGM0YhwH-M_i6uGdezSgzr8R6BmM4eC7ZcwGaAR38GRi2VFyEM7REgtCO0Hd6FAsguHS63TwCI65UwBCkcS_gEFdpoI5tD0az4cBWtdfj1yXbn1iOwpiH_BALg=
11:25:18.989 [Hashed wheel timer #1] DEBUG com.ning.http.client.providers.netty.channel.pool.DefaultChannelPool - Closed 0 connections out of 0 in 0ms
INFO - Message received: {}
11:26:13.918 [New I/O worker #1] DEBUG com.ning.http.client.providers.netty.handler.Processor - Channel Closed: [id: 0x0e0d06c0, /192.168.99.102:46345 :> mpmulti-6wbl.slack-msgs.com/54.172.207.190:443] with attribute NettyResponseFuture{currentRetry=5,
    isDone=true,
    isCancelled=false,
    asyncHandler=com.ning.http.client.ws.WebSocketUpgradeHandler@e9cba57,
    nettyRequest=com.ning.http.client.providers.netty.request.NettyRequest@b3f8453,
    content=NettyWebSocket{channel=[id: 0x0e0d06c0, /192.168.99.102:46345 :> mpmulti-6wbl.slack-msgs.com/54.172.207.190:443]},
    uri=wss://mpmulti-6wbl.slack-msgs.com/websocket/0WNxIQsK_mzw561vkxWrN4B3tSPO-oBBR6fPtGnD2GLP_47Cms8s8GzyNl8ujheXVnNIw0RygTwglxlZYdfChlNf_0MfCwihOeQMUI-hjgCcwxXuMZFUSYrZphQpu1w7VYP5j3dc0nOVnL0YZX_oi62cgeoaWgwn5GjUiif-0AM=,
    keepAlive=true,
    httpHeaders=org.jboss.netty.handler.codec.http.DefaultHttpHeaders@790add3d,
    exEx=null,
    redirectCount=0,
    timeoutsHolder=null,
    inAuth=false,
    statusReceived=false,
    touch=530188604}
INFO - Websocket connection closed, reconnecting...
11:26:13.920 [New I/O worker #1] DEBUG com.ning.http.client.providers.netty.channel.ChannelManager - Closing Channel [id: 0x0e0d06c0, /192.168.99.102:46345 :> mpmulti-6wbl.slack-msgs.com/54.172.207.190:443] 

在对这个问题做了一些额外的研究并尝试了各种方法之后,据我所知,我已经设法解决了这个问题。

似乎#slack API 需要定期发送 ping 消息以防止连接断开。

在执行每 30 秒发送一次 ping 消息的计时器代码后,到目前为止我再也没有遇到过这个问题。

这里是我为了解决问题添加的部分添加代码:

def initRTM(): Unit = {

    h.debug("\nOpening Real Time Messaging socket")

    h.debug("Pinging at 30s intervals")
    val ex = new ScheduledThreadPoolExecutor(1)
    val task = new Runnable {
      def run() = sendPing()
    }
    val f = ex.scheduleAtFixedRate(task, 1, 30, TimeUnit.SECONDS)

    if(!slack.isOpen){
      f.cancel(false)
    }
    [...]
}

RTM API (https://api.slack.com/rtm) 没有具体说明必须发送 ping 消息才能保持连接有效,但强烈建议这样做:

Clients should try to quickly detect disconnections, even in idle periods, so that users can easily tell the difference between being disconnected and everyone being quiet. Not all web browsers support the WebSocket ping spec, so the RTM protocol also supports ping/pong messages. When there is no other activity clients should send a ping every few seconds

这实际上似乎是维持连接的必要条件。

我希望这可以帮助其他在使用#slack RTM 时遇到类似问题的用户API。