websoket相关问题

App经过网关转发websocket请求,app发送连接请求是正常的,app应用手动发送断开连接是正常的,app应用切换到后台时自动关闭websocket连接请求时网关报错,但也走了websocket服务端onclose方法连接正常关闭了,就是网关老报错。

个人感觉应该跟网关配置那块有问题

spring:
  application:
    name: sc-gateway
  main:
    allow-bean-definition-overriding: true
  cloud:
    gateway:
      discovery:
        locator:
          enabled: false                     ###参考网上资料是不是不应该配置
          lower-case-service-id: true
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "docs.spring.io"
            allowedMethods:
              - GET
                POST
                DELETE
                PUT
                OPTION
      routes:
   #mini-mes基础服务
      - id: mini-mes
        order: 3
        uri: lb://mini-mes
        predicates:
          - Path=/api-i/**
        filters:
          - StripPrefix=1
          
     #mini-mes的webscoket接口
      - id: mini-mes-socket
        order: 2
        uri: lb:ws://mini-mes
        predicates:
          - Path=/api-i/webScoket/**
        filters:
          - StripPrefix=1
          - RemoveRequestHeader= SESSION

线上错误

```java
2023-04-21 14:19:38.273 ERROR 1 --- [-server-epoll-5] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET http://www.ccc.com:8766/api-i/webScoket/82-SA0003-appSendData]

io.netty.channel.unix.Errors$NativeIoException: syscall:read(..) failed: Connection reset by peer
    at io.netty.channel.unix.FileDescriptor.readAddress(..)(Unknown Source)

2023-04-21 14:19:38.274 ERROR 1 --- [-server-epoll-5] o.s.w.s.adapter.HttpWebHandlerAdapter    : Failed to handle request [GET http://www.ccc.com:8766/api-i/webScoket/82-SA0003-appSendData]

java.lang.IllegalStateException: Status and headers already sent
    at reactor.ipc.netty.http.server.HttpServerOperations.status(HttpServerOperations.java:346)
    at org.springframework.http.server.reactive.ReactorServerHttpResponse.applyStatusCode(ReactorServerHttpResponse.java:67)
    at org.springframework.http.server.reactive.AbstractServerHttpResponse.lambda$null$4(AbstractServerHttpResponse.java:214)
    at reactor.core.publisher.MonoRunnable.subscribe(MonoRunnable.java:42)
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080)
    at reactor.core.publisher.FluxConcatIterable$ConcatIterableSubscriber.onComplete(FluxConcatIterable.java:147)
    at reactor.core.publisher.FluxConcatIterable.subscribe(FluxConcatIterable.java:61)
    at reactor.core.publisher.MonoIgnoreElements.subscribe(MonoIgnoreElements.java:37)
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080)
    at org.springframework.http.server.reactive.ChannelSendOperator$WriteBarrier.onNext(ChannelSendOperator.java:181)
    at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:198)
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115)
    at reactor.core.publisher.FluxJust$WeakScalarSubscription.request(FluxJust.java:99)
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156)
    at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:138)
    at org.springframework.http.server.reactive.ChannelSendOperator$WriteBarrier.onSubscribe(ChannelSendOperator.java:163)

线下错误

2023-04-21 14:30:05.170 ERROR 7904 --- [ctor-http-nio-7] r.i.n.channel.CloseableContextHandler    : Handler failure while no child channelOperation was present

java.io.IOException: 远程主机强迫关闭了一个现有的连接。
    at sun.nio.ch.SocketDispatcher.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:192)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1108)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:345)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:647)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:582)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:499)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:461)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
    at java.lang.Thread.run(Thread.java:748)

2023-04-21 14:30:05.187 ERROR 7904 --- [ctor-http-nio-7] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET http://192.168.3.5:8766/api-i/webScoket/20-SA0003-appSendData]

java.io.IOException: 远程主机强迫关闭了一个现有的连接。
    at sun.nio.ch.SocketDispatcher.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:192)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1108)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:345)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:647)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:582)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:499)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:461)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
    at java.lang.Thread.run(Thread.java:748)

2023-04-21 14:30:05.206 ERROR 7904 --- [ctor-http-nio-7] o.s.w.s.adapter.HttpWebHandlerAdapter    : Failed to handle request [GET http://192.168.3.5:8766/api-i/webScoket/20-SA0003-appSendData]

java.lang.IllegalStateException: Status and headers already sent
    at reactor.ipc.netty.http.server.HttpServerOperations.status(HttpServerOperations.java:346)
    at org.springframework.http.server.reactive.ReactorServerHttpResponse.applyStatusCode(ReactorServerHttpResponse.java:67)
    at org.springframework.http.server.reactive.AbstractServerHttpResponse.lambda$null$4(AbstractServerHttpResponse.java:214)
    at reactor.core.publisher.MonoRunnable.subscribe(MonoRunnable.java:42)
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080)
    at reactor.core.publisher.FluxConcatIterable$ConcatIterableSubscriber.onComplete(FluxConcatIterable.java:147)
    at reactor.core.publisher.FluxConcatIterable.subscribe(FluxConcatIterable.java:61)
    at reactor.core.publisher.MonoIgnoreElements.subscribe(MonoIgnoreElements.java:37)

```

  • 这篇博客: webSocket部署到远程服务器遇到的坑中的 webSoket连接部分源码 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 前台

      var websocket = null;
        var Ip = window.location.host;
      if ('WebSocket' in window) {
             websocket = new WebSocket("ws://"+Ip+"/ws/dkuserSocket?userId="+"admin");
        }
        else
        {
            alert('当前浏览器 Not support websocket');
         }
    
        // 连接发生错误的回调方法
        websocket.onerror = function () {
            console.log("webSocke连接错误");
        };
    
        // 连接成功建立的回调方法
        websocket.onopen = function () {
    
            var param={
                "billId":billId,
                "billType":billType
            };
            
                // 接收到消息的回调方法
        websocket.onmessage = function (event) {
        }
        
        
        // 连接关闭的回调方法
        websocket.onclose = function () {
    
            }
    
        // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onunload = function () {
                closeWebSocket();
            }
    
        // 关闭WebSocket连接
        function closeWebSocket() {
                websocket.close();
            }
            
    

websocket的问题
WebSocket是一种在单个TCP连接上进行全双工通信的协议。它能够在客户端和服务器之间建立实时通信,同时还能保证数据的高效率和安全性。然而,在使用WebSocket过程中也会遇到一些问题,包括以下几点:
跨域访问问题:由于浏览器的同源策略,WebSocket只能与同源的服务器进行通信。如果需要与不同源的服务器进行通信,需要进行特殊的处理。
代理问题:一些网络环境下,客户端和服务器之间可能会存在代理,这会导致WebSocket连接失败。解决这个问题的方法是将代理服务器的配置进行调整。
加密问题:在保证通信安全的前提下,WebSocket需要进行加密操作。如果缺少加密操作,将会存在数据泄露的风险。
大规模连接问题:在WebSocket连接较多的情况下,服务器的性能可能会受到影响。因此,需要对服务器进行优化,以提高服务器的性能和稳定性。
综上所述,虽然WebSocket在实时通信方面有着非常明显的优势,但也需要注意以上几个问题,以保证其正常运行和安全性。