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

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

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

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

背景

websock报错:The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for caller_第1张图片

提供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 occurred
java.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 occurred
java.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连接呢?

代码参考:

    @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));
        }
    }

 

你可能感兴趣的:(websocket)