前言

在整合过程中,很容易就犯下一下错误,导致转发webSocket请求的时候,老是出现一些小问题。
记录一下

思路

1、nginx配置支持webSocket转发
2、Spring cloud gateway转发webSocket请求
3、webSocket服务器接收并处理webSocket请求

配置nginx

http模块内,配置3块内容

  • 支持协议升级
  • 网关服务路由
  • location识别转发

我这里转发到2个gateway服务,配置了一下upstream

map $http_upgrade $connection_upgrade {
      default upgrade;
      '' close;
    }

    upstream gateway{
      server 192.168.55.8:8080;
      server 192.168.55.9:8080;
    }

location /ws/{
            proxy_pass http://gateway/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            proxy_connect_timeout 60s;
            proxy_read_timeout 7200s;
            proxy_send_timeout 60s;
        }

配置Spring cloud gateway

 # Websocket路由
        - id: websocket_route
          uri: lb:ws://test-service
          predicates:
            - Path=/websocket/**

test-service 是webSocket请求最终处理的服务,test-service是服务名。
根据1级路径是websocket的请求进行转发

配置webSocket服务(test-service)

1、tomcat方式实现
2、spring封装实现
3、netty方式实现
此处简单介绍使用方式2, 配置,握手拦截,请求端点处理。

@Configuration
@EnableWebSocket
public class WebsocketSpringConfig implements WebSocketConfigurer {



    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new WebsocketSpringController(),"/websocket/user").addInterceptors(new WebsocketInterceptor()).setAllowedOrigins("*");
    }
}

public class WebsocketInterceptor implements HandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        map.put("token","");
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
    }
}


public class WebsocketSpringController extends TextWebSocketHandler {

    private final String charset = "UTF-8";
    private WebSocketSession session;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        this.session = session;
        System.out.println(session);
        session.sendMessage(new TextMessage("connected..."));

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        System.out.println(payload);
        session.sendMessage(new TextMessage("received:" + payload));

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
    }
}

问题

遇到一些小问题
1、nginx配置问题
upstream 问题
一开始配置的是 upstream test_gateway ,后面改成 upstream gateway

upstream name的不能有特殊字符,各种结合等

2、服务网络问题
test-service 的ip地址不可达,注册中心显示的test-service的ip地址是一个内网地址,gateway无法访问到,gateway转发请求失败。

Invalid handshake response getStatus: 404

将test-service的ip地址修改,重新进行服务注册后一切正常。

3、webSocket服务配置错误
一开始配置的时候开启了SockJS
registry.addHandler(new WebsocketSpringController(),“/websocket/user”).addInterceptors(new WebsocketInterceptor()).setAllowedOrigins(“*”).withSockJS();

导致ws请求无法接收处理。
开启SockJS所处理的URL是“http://”或“https://”模式,而不是“ws://”和“wss://”

withSockJS配置去掉。

遇到的报错信息如下

报错信息1
An exception has been observed post termination, use DEBUG level to see the full stack: io.netty.handler.codec.http.websocketx.WebSocketClientHandshakeException: Connection prematurely closed BEFORE opening handshake is complete.

报错信息2
java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value “*” since that cannot be set on the “Access-Control-Allow-Origin” response header. To allow credentials to a set of origins, list them explicitly or consider using “allowedOriginPatterns” instead.

报错信息3
“Invalid SockJS path ‘/123’ - required to have 3 path segments”

如果一开始没有用nginx做转发测试。
存在跟我一样的情况
不加nginx的时候转发ws是正常。加上nginx配置之后,就无法转发了,关键的是gateway不转发也不报错,nginx请求日志一切正常

不要怀疑,就是nginx配错了。请参考我的这套配置

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐