我有一个websocket解决方案,用于移动应用程序和Java后端系统之间的双向通信。我正在使用带有STOMP的Spring WebSockets。我实现了一个乒乓解决方案,以使Websocket打开的时间超过30秒,因为我需要的会话时间更长。有时我会在日志中得到这些错误,这些错误似乎来自checkSession() in Spring's SubProtocolWebSocketHandler。
server.log:07:38:41,090错误[org.springframework.web.socket.messaging.SubProtocolWebSocketHandler](ajp-http-executor-threads-14526905)60205毫秒后未收到任何消息。关闭StandardWebSocketSession [id = 214a10,uri = / base / api / websocket]。
它们不是很频繁,但每天都会发生,并且60秒的时间似乎是适当的,因为它已硬编码到上述的Spring类中。但是,在运行应用程序一段时间之后,我开始收到大量这些真正长期存在的“超时”:
server.log:00:09:25,961错误[org.springframework.web.socket.messaging.SubProtocolWebSocketHandler](ajp-http-executor-threads-14199679)在208049286毫秒后未收到任何消息。关闭StandardWebSocketSession [id = 11a9d9,uri = / base / api / websocket]。
大约在这个时候,应用程序开始遇到问题。
我一直在尝试搜索此行为,但在网络上的任何地方都找不到它。有没有人以前见过这个问题,知道解决方法,或者可以向我解释一下?
最佳答案
我们发现了一些东西:
我们在STOMP级别上添加了自己的ping / pong功能,该功能每30秒运行一次。
移动客户端存在一个错误,即使在进入屏幕保护模式时,该错误也导致他们继续对ping进行回复。这意味着websocket从未关闭或超时。
在服务器收到Spring检查的每一个Pong消息中,发现很长时间没有收到“真实”消息,并触发了日志的写入。然后,它尝试使用以下代码关闭websocket:
session.close(CloseStatus.SESSION_NOT_RELIABLE);
但我怀疑这无法正确关闭会话。即使这样做,移动客户端也会尝试重新连接。因此,如果又过了30秒,则会向服务器发送另一条Pong消息,导致又写入了其中一个日志。以此类推...
解决方案是编写一些服务器端代码以基于this project关闭旧的Websocket,并修复移动客户端中的错误,即使它们处于屏幕保护程序模式,该错误也使它们能够响应ping / pong。
噢,让其他人知道的一件事是,永远不要信任客户端,我们看到他们有时可以在一毫秒内发送多个Websocket请求,因此请确保以某种方式处理这些“重复请求”!