解决gateway转发websocket服务时遇到的问题:java.lang.ClassCastException: org.apache.catalina.connector.ResponseFacade cannot be cast to reacto

洛辰 1年前 ⋅ 1008 阅读

问题:通过网关连接websocket服务,网关后台报错如下:

2022-09-15 10:52:20,741 ERROR AbstractErrorWebExceptionHandler:122 - [15d2d70e]  500 Server Error for HTTP GET "/websocket/123"
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.upgrade(ReactorNettyRequestUpgradeStrategy.java:163) ~[spring-webflux-5.3.19.jar:5.3.19]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ HTTP GET "/websocket/123" [ExceptionHandlingWebHandler]
Original Stack Trace:
		at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.upgrade(ReactorNettyRequestUpgradeStrategy.java:163) ~[spring-webflux-5.3.19.jar:5.3.19]
		at org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService.lambda$handleRequest$1(HandshakeWebSocketService.java:243) ~[spring-webflux-5.3.19.jar:5.3.19]
		at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:152) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:240) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoNext$NextSubscriber.onComplete(MonoNext.java:102) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:83) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onNext(FluxDematerialize.java:98) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onNext(FluxDematerialize.java:44) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainAsync(FluxFlattenIterable.java:421) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:686) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onNext(FluxFlattenIterable.java:250) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:292) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:236) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onComplete(FluxDematerialize.java:121) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onNext(FluxDematerialize.java:91) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onNext(FluxDematerialize.java:44) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:340) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:227) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.request(FluxDematerialize.java:127) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxPeek$PeekSubscriber.request(FluxPeek.java:138) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onSubscribe(MonoIgnoreElements.java:72) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onSubscribe(FluxPeek.java:171) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxDematerialize$DematerializeSubscriber.onSubscribe(FluxDematerialize.java:77) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.Mono.subscribe(Mono.java:4400) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:128) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.DrainUtils.postCompleteDrain(DrainUtils.java:132) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.DrainUtils.postComplete(DrainUtils.java:187) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxMaterialize$MaterializeSubscriber.onComplete(FluxMaterialize.java:141) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxTake$TakeSubscriber.onComplete(FluxTake.java:153) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxTake$TakeSubscriber.onNext(FluxTake.java:133) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.onNext(FluxTimeout.java:180) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:128) ~[reactor-core-3.4.17.jar:3.4.17]
		at org.springframework.cloud.commons.publisher.FluxFirstNonEmptyEmitting$FirstNonEmptyEmittingSubscriber.onComplete(FluxFirstNonEmptyEmitting.java:325) ~[spring-cloud-commons-3.1.1.jar:3.1.1]
		at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onComplete(FluxSubscribeOn.java:166) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable$IterableSubscription.fastPath(FluxIterable.java:362) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:227) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:131) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:124) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.Flux.subscribe(Flux.java:8469) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:200) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoFlatMapMany.subscribeOrReturn(MonoFlatMapMany.java:49) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.Flux.subscribe(Flux.java:8455) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:200) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.MonoFlatMapMany.subscribeOrReturn(MonoFlatMapMany.java:49) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxFromMonoOperator.subscribe(FluxFromMonoOperator.java:76) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84) ~[reactor-core-3.4.17.jar:3.4.17]
		at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37) ~[reactor-core-3.4.17.jar:3.4.17]
		at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) ~[?:1.8.0_251]
		at java.util.concurrent.FutureTask.run(FutureTask.java) ~[?:1.8.0_251]
		at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_251]
		at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_251]
		at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_251]
		at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_251]
		at java.lang.Thread.run(Thread.java:748) ~[?:1.8.0_251]

 

分析原因:

Gateway The default usage is based on Netty Container of RequestUpgradeStrategy and WebSocketClient Result in an error , Statement Tomcat The container corresponds to Bean To cover it can solve this problem

意思是:网关默认基于netty做长连接,要使用websocket需要重写覆盖一下对应的Bean

解决方法:

package cnki.bdms;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.reactive.socket.client.TomcatWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
import org.springframework.web.reactive.socket.server.RequestUpgradeStrategy;
import org.springframework.web.reactive.socket.server.upgrade.TomcatRequestUpgradeStrategy;

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

    /**************解决网关转接websocket服务的问题*******************************/
    @Bean
    @Primary
    WebSocketClient tomcatWebSocketClient() {
        return new TomcatWebSocketClient();
    }
    @Bean
    @Primary
    public RequestUpgradeStrategy requestUpgradeStrategy() {
        return new TomcatRequestUpgradeStrategy();
    }
    /**************解决网关转接websocket服务的问题*******************************/
}

相关文章推荐

全部评论: 0

    我有话说: