websock报错:The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for caller-CSDN博客

网上看到了一些关于这个错误的产生场景

参考:场景:使用websocket遇到的一个小问题 The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid stat

我这里产生错误的场景是不同的,记录一下

背景

提供websocket服务的公司,其内部的系统已经与websocket server建立了长连接,图中的nginx是一个出口网关,其运维要求是出口网关与上游服务是不能建立长连接的。

而我们作为外部公司,希望使用其长连接服务,显然长连接是建立不起来了

方案

我们使用java开发websocket client,由于其不支持长连接,我们就采用了轮询的方式,每隔30s通过http upgrade来拉取一次数据

使用了@ClientEndpoint注解

伪代码

// 提供启动的时候 与nginx建立长连接 // 在onMessage方法中 每次发送http请求 获取的结果落库

这样做,在于nginx的长连接中不断发送http请求,是OK的

问题

问题是:在某些情况下会报错

[ ERROR] [2020-07-06 01:45:34] [WebSocketClient-AsyncIO-1] org.apache.tomcat.websocket.pojo.PojoEndpointBase [175] - No error handling configured for [xxx] and the following error occurredjava.io.IOException: java.util.concurrent.ExecutionException: java.io.IOException: 断开的管道

之后30秒报错

[ ERROR] [2020-07-04 15:41:42] [WebSocketClient-AsyncIO-1] org.apache.tomcat.websocket.pojo.PojoEndpointBase [175] - No error handling configured for [xxx] and the following error occurredjava.lang.IllegalStateException: The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method

通过这个错误,可能得出两个结论

1. 当websocket server与client之间的socket断开(broken pipe)之后,在长连接上根据session继续发送http请求会报错

java.lang.IllegalStateException: The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method

2. No error handling configured for 的原因是:没有配置@onError注解来处理

解决方案

是不是可以在onError这里重新建立一个新的socket连接呢?经过测试,这种方式是不行的,因为这样会导致前一个连接没有关闭,后面又建立了一个连接,导致多个端口对同一个remote endpoint建立连接

代码参考:

    @OnError    public void onError(Session session, Throwable t) {        logger.error(CommonUtil.exceptionToString(t));        /**         * 解决websocket服务器断开socket 导致@ClientEndPoint生成的WebScoket-AsyncIO线程退出的问题         * 这里再次建立socket连接         */        WebSocketContainer container;        try {            container = ContainerProvider.getWebSocketContainer();            URI r = URI.create(Const.SMK_WEBSOCKET_ADDRESS_PREFIX + Const.SMK_CENTER_MODULE);            session = container.connectToServer(this.getClass(), r);        } catch (DeploymentException | IOException ex) {            logger.error(CommonUtil.exceptionToString(ex));        }    }

应该在onClose方法中建立一个新的socket连接

    @OnClose    public void onClose(Session session, CloseReason reason) {        logger.warn("closing session => {} - {}", session, reason);        /**         * 解决websocket服务器断开socket 导致@ClientEndPoint生成的WebScoket-AsyncIO线程退出的问题         * 这里再次建立socket连接         */        try {            new Thread(new SmkCenterRunnable(), "smk-center-java-websocket-client").start();        } catch (Exception e) {            logger.error(CommonUtil.exceptionToString(e));        }    }

经过测试,大部分场景下其会重新建立其websocket连接。但是也存在失败的情况,后续可以加入retry策略,采用一个定时器,每隔1分钟,2分钟,4分钟...以及重试次数来尝试重新建立连接


原网址: 访问
创建于: 2023-11-06 10:58:44
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论