【问题标题】:How to handle websocket @OnError如何处理 websocket @OnError
【发布时间】:2015-02-28 03:43:27
【问题描述】:

除了记录它之外,处理 websocket 错误的正确方法是什么?

关于onError(),端点documentation 声明:

开发者可以在 web socket session 时实现这个方法 创建某种未在 Web 套接字中建模的错误 协议。例如,这可能是一个通知,一个传入的 消息太大而无法处理,或者传入的消息无法处理 被编码。

此方法存在多种异常类别 (当前)定义为处理:

  • 连接问题,例如,在 Web 套接字连接可以正式关闭之前发生的套接字故障。这些被建模为 SessionExceptions

  • 由开发人员创建的消息处理程序调用引发的运行时错误。

  • 在调用任何消息处理程序之前编码传入消息的转换错误。这些被建模为 DecodeExceptions

所有这些类型的异常都是致命的,导致 websocket 关闭吗?

如果出现错误,onError()方法是否应该关闭websocket(调用Session.close())?

到目前为止,我认为我有责任彻底关闭会话,并告知客户关闭原因。这就是为什么我的onError() 尝试调用session.close() 如果session.isOpen() 返回true,但这导致tomcat(8.0.15)抛出NullPointerException

...
Caused by: java.lang.NullPointerException
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:96)
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:444)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:335)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:264)
    at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:536)
    at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:464)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:441)
    at my.package.MyEndpoint.onWebSocketError(MyEndpoint.java:229)
    ... 18 more

这是一个 tomcat 错误,还是我的误解,还是两者兼而有之?

编辑: 似乎 Java EE websocket 示例dukeeetf2 假定错误是致命的;并且没有必要关闭会话。记录错误,并删除会话:

@OnError
public void error(Session session, Throwable t) {
    /* Remove this connection from the queue */
    queue.remove(session);
    logger.log(Level.INFO, t.toString());
    logger.log(Level.INFO, "Connection error.");
}

【问题讨论】:

    标签: java tomcat websocket onerror


    【解决方案1】:

    @OnError方法调用不代表Session会关闭;你可以做任何你想做的事,这取决于你的应用程序指定的合同。

    来自 tomcat 实现的堆栈跟踪似乎是一个错误。

    ad dukeeetf2 示例 - 似乎此代码包含其他假设 - 端点不会引发异常,因此此处捕获的所有内容都来自底层 WebSocket 框架实现。这并不意味着存在“连接错误”;我可能会立即关闭(如果这是我不希望我的应用程序处理错误的方式);此实现可能会导致打开的连接没有任何消息。

    【讨论】:

    • 谢谢。您确定会话保持打开状态吗?这是在某个地方记录的吗?
    • 好问题 - 不幸的是,此信息在任何地方都没有明确说明,但它是有道理的;会话关闭时需要调用@OnClose(或 Endpoint.onClose),因此在此之前没有必要清理任何与端点相关的资源。另一方面,@OnError(或 Endpoint.onError)在端点(+Decode/EncodeExeption,..)抛出未处理的异常时随时触发,可以通过端点实现来解决,因此没有必要关闭基础会话。
    • 这对我来说也很有意义,但我发现缺少文档很可疑。这是有道理的,但这并不意味着这就是它的实际工作方式。
    • 嗯 ;) 我记得与 JSR 356 规范负责人谈论过这个,当时他确认这是预期的行为。无论如何,规范明确提到 @OnClose 必须在会话关闭时调用,因此执行清理不会出错。 (您可能需要在@OnError 中进行额外检查,因为它可以在@OnClose 之后调用——例如当@OnClose 抛出异常时)。
    • 我自己阅读了 Undertow(Websockets 的 JBoss impl)的代码,发现是这样的。 onError 不会隐式调用 onClose。每当其他on* 方法抛出未处理的异常时,就会调用onError
    【解决方案2】:

    我看到这有点过时了,但今天在寻找此信息时结束了。 根据您对 websocket 状态的依赖方式,您需要手动关闭会话,至少对于 javax.websocket 实现而言是这样。

    在我的例子中,发生的错误导致 websession 客户端管理实现出现问题,所以我按照上面的示例关闭了会话。 我认为这取决于您需要什么,但它肯定不会在此实现中进行关闭会话。

    【讨论】:

      猜你喜欢
      • 2015-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-19
      • 1970-01-01
      • 2013-06-16
      • 1970-01-01
      • 2011-01-03
      相关资源
      最近更新 更多