springcloud gateway整合websocket踩坑记录

gateway整合websocket踩坑

在gateway整合websocket时,总共遇到的问题有两个,一个是jar冲突,另外一个是网关设置跨域后websocket连接上马上断开

jar包冲突

jar包冲突主要是:org.apache.catalina.connector.ResponseFacade cannot be cast to reactor.netty.http.server.HttpServerResponse,提示get请求报错500

15:30:38.092 [http-nio-9999-exec-1] ERROR c.m.g.e.GlobalErrorWebExceptionHandler - [handle,38] - org.apache.catalina.connector.ResponseFacade cannot be cast to reactor.netty.http.server.HttpServerResponse
java.lang.ClassCastException: org.apache.catalina.connector.ResponseFacade cannot be cast to reactor.netty.http.server.HttpServerResponse
	at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.getNativeResponse(ReactorNettyRequestUpgradeStrategy.java:182)
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ HTTP GET "/sys/websocket/1" [ExceptionHandlingWebHandler]
Stack trace:
		at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.getNativeResponse(ReactorNettyRequestUpgradeStrategy.java:182)
		at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.upgrade(ReactorNettyRequestUpgradeStrategy.java:162)
		at org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService.lambda$handleRequest$1(HandshakeWebSocketService.java:235)
		at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:151)
		at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.Mono.subscribe(Mono.java:4252)
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172)
		at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at com.alibaba.csp.sentinel.adapter.reactor.MonoSentinelOperator.subscribe(MonoSentinelOperator.java:40)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)

我出现这种情况主要是调用feign接口,引用的包里面有如下冲突

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
</dependency>
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.tomcat.embed</groupId>
	<artifactId>tomcat-embed-jasper</artifactId>
</dependency>

解决办法:我是使用的idea,可以利用idea自带的jar包依赖来查看当前项目引用情况,具体ctrl+shift+alt+u来查看依赖情况,找到上面的jar包,去除依赖

连上websocket后立马断开问题

报错java.lang.UnsupportedOperationException,就是在请求头那块报错不支持

2022-08-26 16:12:11.334 ERROR 20032 --- [ctor-http-nio-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [7e7b8a68-1] Error [java.lang.UnsupportedOperationException] for HTTP GET "/plat/approveabc/websocket/1123213", but ServerHttpResponse already committed (200 OK)
2022-08-26 16:12:11.338 ERROR 20032 --- [ctor-http-nio-2] r.n.http.server.HttpServerOperations     : [id: 0x7e7b8a68, L:/127.0.0.1:8081 - R:/127.0.0.1:56941] Error finishing response. Closing connection

java.lang.UnsupportedOperationException: null
	at org.springframework.http.ReadOnlyHttpHeaders.set(ReadOnlyHttpHeaders.java:106) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ HTTP GET "/plat/approveabc/websocket/1123213" [ExceptionHandlingWebHandler]

查看代码,发现是gateway处理跨域时使用的

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        // 允许cookies跨域
        config.setAllowCredentials(true);
        // #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
        config.addAllowedOrigin("*");
        // #允许访问的头信息,*表示全部
        config.addAllowedHeader("*");

后来换成

  return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            if (!CorsUtils.isCorsRequest(request)) {
                return chain.filter(exchange);
            }
            ServerHttpResponse response = exchange.getResponse();
            HttpHeaders headers = response.getHeaders();
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "*");
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
            headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3628800");
            return chain.filter(exchange);
        };

就可以解决问题,后面那种解决跨域是reactive,在网关最好使用这种响应式编程,不然问题可能会很多

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
当然,我可以为您提供关于Spring Cloud Gateway整合WebSocket的教程。下面是一个简单的示例教程: 步骤1:添加依赖 首先,您需要在您的项目中添加Spring Cloud GatewaySpring WebSocket的依赖。在您的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 步骤2:配置WebSocket路由 在您的应用程序配置文件(例如application.yml)中添加WebSocket路由的配置。下面是一个示例配置: ```yaml spring: cloud: gateway: routes: - id: websocket_route uri: lb://websocket-service predicates: - Path=/ws/** filters: - WebSocket=ws://{uri}/ws/** ``` 在上面的示例中,我们定义了一个名为`websocket_route`的路由,将所有以`/ws`开头的请求转发到名为`websocket-service`的后端服务。过滤器`WebSocket`用于将HTTP请求升级为WebSocket协议。 步骤3:创建WebSocket处理器 创建一个WebSocket处理器来处理来自客户端的WebSocket连接和消息。下面是一个简单的示例: ```java @Component public class WebSocketHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理收到的消息 String payload = message.getPayload(); // 进行业务逻辑处理 session.sendMessage(new TextMessage("Hello, " + payload)); } } ``` 在上面的示例中,我们通过继承`TextWebSocketHandler`类来创建一个WebSocket处理器。在`handleTextMessage`方法中,我们可以处理收到的文本消息,并发送回复消息。 步骤4:配置WebSocket端点 配置WebSocket端点,使其与Spring Cloud Gateway一起工作。在您的应用程序主类上添加以下配置: ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Autowired private WebSocketHandler webSocketHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketHandler, "/ws").setAllowedOrigins("*"); } } ``` 在上面的示例中,我们使用`@EnableWebSocket`注解启用WebSocket支持,并通过`registerWebSocketHandlers`方法注册WebSocket处理器。我们指定了一个名为`/ws`的端点,并使用`setAllowedOrigins("*")`允许来自任何来源的连接。 步骤5:启动应用程序 现在,您可以启动您的应用程序并测试WebSocket连接了。使用WebSocket客户端连接到`ws://localhost:8080/ws`(假设您的应用程序运行在本地8080端口)。您可以发送消息并查看应用程序的响应。 这就是整合Spring Cloud GatewayWebSocket的简单教程。您可以根据自己的需求进行进一步的定制和扩展。希望对您有所帮助!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值