首页 > 解决方案 > 如果断路器打开,则回退到 Spring Cloud Gateway 中的另一条路由

问题描述

我有这种路线。它们工作正常,但由于某种原因,日志中出现错误(日志的最后一行)。这是由于响应尝试第二次通过过滤器 modifyResponseBody 的事实。为什么会这样?一般来说,将请求重定向到不同的路由是否被认为是可以接受的?

   @Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
    RouteLocator build = builder.routes()
            .route("normal", p -> p
                    .path("/read/searchByResource").and().predicate(pr -> !pr.getRequest().getHeaders().containsKey("hello-header"))
                    .filters(f -> f.modifyResponseBody(GenericResponse.class, SpecificResponse.class,
                            (serverWebExchange, genericResponse) -> Mono.just(new SpecificResponse(genericResponse)))
                            .circuitBreaker(c -> c.setName("myCircuitBreaker")
                            .setFallbackUri("forward:/fallback")
                            .setStatusCodes(Set.of("500"))))
                    .uri("http://localhost:8081"))

            .route("not normal", p -> p
                    .path("/fallback")
                    .filters(f -> f.rewritePath("/fallback", "/read/searchByResource")
                    )
                    .uri("http://localhost:8082"))
            .build();

    return build;
}
2021-04-21 18:37:30.599 TRACE 8108 --- [ctor-http-nio-1] o.s.c.g.f.WeightCalculatorWebFilter      : Weights attr: {}
2021-04-21 18:37:30.600 TRACE 8108 --- [ctor-http-nio-1] o.s.c.g.h.p.PathRoutePredicateFactory    : Pattern "/read/searchByResource" matches against value "/read/searchByResource"
2021-04-21 18:37:30.600 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.h.RoutePredicateHandlerMapping   : Route matched: normal
2021-04-21 18:37:30.600 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.h.RoutePredicateHandlerMapping   : Mapping [Exchange: GET http://localhost:8080/read/searchByResource] to Route{id='normal', uri=http://localhost:8081, order=0, predicate=(Paths: [/read/searchByResource], match trailing slash: true && CiruitBreakerApplication$$Lambda$514/0x0000000800474840), gatewayFilters=[[ModifyResponseBody New content type = [null], In class = GenericResponse, Out class = SpecificResponse], [[SpringCloudCircuitBreakerResilience4JFilterFactory name = 'myCircuitBreaker', fallback = forward:/fallback], order = 0]], metadata={}}
2021-04-21 18:37:30.600 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.h.RoutePredicateHandlerMapping   : [28e0df6f-2] Mapped to org.springframework.cloud.gateway.handler.FilteringWebHandler@2198c0b4
2021-04-21 18:37:30.600 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.handler.FilteringWebHandler      : Sorted gatewayFilterFactories: [[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@6f825516}, order = -2147483648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@33188612}, order = -2147482648], [ModifyResponseBody New content type = [null], In class = GenericResponse, Out class = SpecificResponse], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@6d229b1c}, order = -1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardPathFilter@1b482cbf}, order = 0], [[SpringCloudCircuitBreakerResilience4JFilterFactory name = 'myCircuitBreaker', fallback = forward:/fallback], order = 0], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@2da99821}, order = 10000], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.config.GatewayNoLoadBalancerClientAutoConfiguration$NoLoadBalancerClientFilter@7161457}, order = 10150], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@661fe025}, order = 2147483646], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyRoutingFilter@66a53104}, order = 2147483647], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@62cba181}, order = 2147483647]]
2021-04-21 18:37:30.600 TRACE 8108 --- [ctor-http-nio-1] o.s.c.g.filter.RouteToRequestUrlFilter   : RouteToRequestUrlFilter start
2021-04-21 18:37:30.603 TRACE 8108 --- [ctor-http-nio-1] o.s.c.gateway.filter.NettyRoutingFilter  : outbound route: 45905ca4, inbound: [28e0df6f-2] 
2021-04-21 18:37:30.607 DEBUG 8108 --- [ctor-http-nio-1] i.g.r.c.i.CircuitBreakerStateMachine     : CircuitBreaker 'myCircuitBreaker' recorded an exception as failure:

org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory$CircuitBreakerStatusCodeException: 500 INTERNAL_SERVER_ERROR
    at org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory$1.lambda$filter$0(SpringCloudCircuitBreakerFilterFactory.java:103) ~[spring-cloud-gateway-server-3.0.2.jar:3.0.2]
    at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:289) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.Operators.complete(Operators.java:136) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoEmpty.subscribe(MonoEmpty.java:45) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:236) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2399) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:189) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:173) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:160) ~[reactor-core-3.4.5.jar:3.4.5]
    at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:388) ~[reactor-netty-http-1.0.6.jar:1.0.6]
    at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:654) ~[reactor-netty-core-1.0.6.jar:1.0.6]
    at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onStateChange(DefaultPooledConnectionProvider.java:196) ~[reactor-netty-core-1.0.6.jar:1.0.6]
    at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onStateChange(DefaultPooledConnectionProvider.java:452) ~[reactor-netty-core-1.0.6.jar:1.0.6]
    at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:629) ~[reactor-netty-http-1.0.6.jar:1.0.6]
    at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) ~[reactor-netty-core-1.0.6.jar:1.0.6]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

2021-04-21 18:37:30.608 DEBUG 8108 --- [ctor-http-nio-1] i.g.r.c.i.CircuitBreakerStateMachine     : No Consumers: Event ERROR not published
2021-04-21 18:37:30.608 TRACE 8108 --- [ctor-http-nio-1] o.s.c.g.h.p.PathRoutePredicateFactory    : Pattern "[/read/searchByResource]" does not match against value "/fallback"
2021-04-21 18:37:30.609 TRACE 8108 --- [ctor-http-nio-1] o.s.c.g.h.p.PathRoutePredicateFactory    : Pattern "/fallback" matches against value "/fallback"
2021-04-21 18:37:30.609 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.h.RoutePredicateHandlerMapping   : Route matched: not normal
2021-04-21 18:37:30.609 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.h.RoutePredicateHandlerMapping   : Mapping [Exchange: GET /fallback] to Route{id='not normal', uri=http://localhost:8082, order=0, predicate=Paths: [/fallback], match trailing slash: true, gatewayFilters=[[[RewritePath /fallback = '/read/searchByResource'], order = 0]], metadata={}}
2021-04-21 18:37:30.609 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.h.RoutePredicateHandlerMapping   : [28e0df6f-2] Mapped to org.springframework.cloud.gateway.handler.FilteringWebHandler@2198c0b4
2021-04-21 18:37:30.609 DEBUG 8108 --- [ctor-http-nio-1] o.s.c.g.handler.FilteringWebHandler      : Sorted gatewayFilterFactories: [[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@6f825516}, order = -2147483648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@33188612}, order = -2147482648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@6d229b1c}, order = -1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardPathFilter@1b482cbf}, order = 0], [[RewritePath /fallback = '/read/searchByResource'], order = 0], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@2da99821}, order = 10000], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.config.GatewayNoLoadBalancerClientAutoConfiguration$NoLoadBalancerClientFilter@7161457}, order = 10150], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@661fe025}, order = 2147483646], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyRoutingFilter@66a53104}, order = 2147483647], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@62cba181}, order = 2147483647]]
2021-04-21 18:37:30.609 TRACE 8108 --- [ctor-http-nio-1] o.s.c.g.filter.RouteToRequestUrlFilter   : RouteToRequestUrlFilter start
2021-04-21 18:37:30.610 TRACE 8108 --- [ctor-http-nio-3] o.s.c.gateway.filter.NettyRoutingFilter  : outbound route: 31272575, inbound: [28e0df6f-2] 
2021-04-21 18:37:30.615 TRACE 8108 --- [ctor-http-nio-3] o.s.c.g.filter.NettyWriteResponseFilter  : NettyWriteResponseFilter start inbound: 31272575, outbound: [28e0df6f-2] 
2021-04-21 18:37:30.617 TRACE 8108 --- [ctor-http-nio-1] o.s.c.g.filter.NettyWriteResponseFilter  : NettyWriteResponseFilter start inbound: 31272575, outbound: [28e0df6f-2] 
2021-04-21 18:37:30.618 ERROR 8108 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter    : [28e0df6f-2] Error [java.lang.NullPointerException] for HTTP GET "/read/searchByResource", but ServerHttpResponse already committed (202 ACCEPTED)

标签: javaspring-cloud-gatewayresilience4j

解决方案


推荐阅读