簡體   English   中英

Play 框架持久 WebSocket 連接

[英]Play Framework Persistent WebSocket Connection

在當前版本的 Play Framework 中,無法使 WebSocket 連接持久化。

https://www.playframework.com/documentation/2.8.x/ScalaWebSockets#Keeping-a-WebSocket-Alive

我有下面的一段代碼,需要這個 WebSocket 連接是持久的。

class ProvisioningActor(sink: ActorRef) extends Actor {

    private[this] val source = Observable.interval(appConfig.pingInterval).map(elem => elem.toInt)
    private[this] val ping = Consumer.foreach[Int](x => self ! x)
    private[this] val task = source.consumeWith(ping).runToFuture

    override def receive: Receive = {
      case jsValue: JsValue =>
        logger.debug(s"Received OCPPCallRequest: \n ${Json.prettyPrint(jsValue)}")
        jsValue.validate[OCPPCallRequest].asEither match {
          case Right(ocppCall) => handleOCPPCallRequest(ocppCall).materialize.map {
            case Failure(fail) => sink ! JsError(s"${fail.getMessage}")
            case Success(succ) => sink ! Json.toJson(succ)
          }
          case Left(errors) =>
            logger.error(s"Errors occurred when validating OCPPCallRequest: \n $errors")
            sink ! Json.toJson(s"error -> ${errors.head._2}") // TODO: Work on this issue here on how we want to propagate errors
        }
      case x: Int =>
        logger.debug(s"Elem: $x")
        handleHeartBeatRequest(2, "HeartbeatRequest").materialize.map {
          case Failure(fail) => sink ! JsError(s"${fail.getMessage}")
          case Success(succ) => sink ! Json.toJson(succ)
        }
      case msg: Any =>
        logger.warn(s"Received unknown message ${msg.getClass.getTypeName} that cannot be handled, " +
          s"eagerly closing websocket connection")
        task.cancel()
        self ! PoisonPill
    }
  }

它有點像將心跳消息發送回客戶端。 我的問題是:

  1. 這對實施來說是否足夠好?
  2. 默認情況下,所有 WebSocket 連接都是持久的,這可能不是我們想要的。 所以這必須基於每個連接。 正確的?

還有其他建議嗎?

我們將 PlayFramework websockets 用於長時間運行的會話,繁忙的服務器支持超過 1000 個並發 Websocket 連接,並且缺少乒乓數據包會導致空閑的 websocket 連接被中間防火牆、代理等以及播放框架 idleTimeout 本身終止 - play.server.https.idleTimeout.

從 PlayFramework v2.1(現在使用 v2.8)開始,我們一直在使用 Sockjs 協議,Play Sockjs - https://github.com/fdimuccio/play2-sockjs ,它使用應用層心跳https://github.com/fdimuccio /play2-sockjs/wiki/API-reference-for-0.5.x#configuring-sockjs-handler

package controllers

import scala.concurrent.duration._

import play.api.mvc._
import play.sockjs.api._

// mixin SockJSRouter trait with your controller
class SockJSController extends Controller with SockJSRouter {

  // override this method to specify custom SockJSSettings
  override protected val settings = SockJSSettings(websocket = false, heartbeat = 55 seconds)

  // here goes the request handler
  def sockjs = SockJS.accept[String, String] { request =>
    ...
  }

}

我們在生產中使用 20s 心跳,這已被證明非常安全,每個連接都有相同的心跳設置,這對我們的用例很有效。

本主題可能有幫助: Play2.5 Java WebSockets

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM