Play Framework中WebSocket连接复用的处理及代码正确性疑问
WebSocket连接复用问题解答
1. 连接已存在时的处理方案
当chargingStationId对应的连接已经在ConcurrentHashMap里存在时,根据业务场景选以下策略:
- 拒绝新连接:给新请求的客户端返回WebSocket关闭帧(比如错误码
1008),明确告知已有活跃连接,避免多连接导致消息推送混乱。 - 替换旧连接:先主动关闭旧连接(发关闭帧,再从Map里移除),然后把新连接存进去。适合允许客户端重连、以最新连接为准的场景,注意要确保旧连接的资源被释放,别留内存泄漏。
- 忽略新请求:直接告知客户端已有连接,不创建新连接也不修改旧连接,适合客户端误触发重复连接的情况。
2. 关于actorRef的理解
没错,你理解的是对的:ActorFlow.actorRef里的actorRef就是out ActorRef。这个Ref是用来把服务器的消息推送给客户端的,OCPPActor拿到它之后,就能在需要的时候给客户端发消息。
3. 现有代码的问题及修正方向
你贴的两段代码都没法实现正确的连接复用,问题点如下:
第一段代码的问题
ActorFlow.actorRef { actorRef => val flow = Props(new OCPPActor(actorRef, chargingStationId, isPersistentConn)) WebSocketManager.addConnection(chargingStationId, flow) flow })
你存到Map里的是Props对象,这只是Actor的创建模板,每次用它都会生成新的Actor实例,根本没法复用已有的连接。正确的做法是存已经创建好的ActorRef(或者关联该WebSocket连接的out ActorRef),而不是Props。
第二段代码的问题
ActorFlow.actorRef { _ => WebSocketManager.getConnection(chargingStationId) })
ActorFlow.actorRef要求返回Props来创建新Actor,但你直接返回Map里的内容——如果之前存的是Props,那会生成新Actor,不是复用;如果存的是ActorRef,类型直接不匹配会报错。而且这种写法跳过了WebSocket握手和连接建立的逻辑,完全走不通。
正确的复用思路
- 连接建立阶段:客户端发起WebSocket连接,成功创建OCPPActor后,把该Actor的自身ActorRef(或者对应的out ActorRef)存入
ConcurrentHashMap,用chargingStationId当键。 - 消息推送阶段:服务器要给客户端发消息时,直接从Map里取出对应的ActorRef,通过它发送消息就行。不需要在
ActorFlow.actorRef里搞复用,因为ActorFlow是处理新连接请求的,如果已有连接,直接拒绝新请求或者告诉客户端用现有连接就好。
内容的提问来源于stack exchange,提问作者joesan
相关产品推荐
相关产品推荐

