spring-cloud-gateway
spring-cloud-gateway copied to clipboard
How can I use retry property of spring-cloud-loadbalancer with gateway?
Hello, thanks to you, I am a developer who is using various modules provided by spring-cloud.
Recently, I am trying to use spring-cloud-loadbalancer retry while using spring-cloud-gateway, but I don't know if I'm using it incorrectly or if I didn't understand it, so I leave this issue.
spring-cloud-netflix-ribbon has been deprecated, so I'm going to use spring-cloud-loadbalancer, but I used to use ribbon's properties as follows.
ribbon:
MaxAutoRetriesNextServer: 1
MaxAutoRetries: 1
So I read the document of the spring-cloud-loadbalancer, and I thought that the spring-cloud-loadbalancer also supports the same functionality, so I tried spring.cloud.loadbalancer.retry.max-retries-on-next-service-instance
and spring.cloud.loadbalancer.retry.max-retries-on-same-service-instance
Test Environment
- source code
- spring.cloud version: 2021.0.2
server:
port: 80
spring:
application:
name: spring-cloud-gateway-demo
cloud:
loadbalancer:
retry:
enabled: true
max-retries-on-next-service-instance: 1
max-retries-on-same-service-instance: 1
avoid-previous-instance: false
retryable-status-codes: 500, 501, 502, 503
retry-on-all-operations: true
gateway:
httpclient:
response-timeout: 3s
connect-timeout: 2000
default-filters:
- StripPrefix=1
routes:
- id: spring-webflux-demo
uri: lb://webflux-demo
predicates:
- "Path=/webflux-demo/**"
discovery:
client:
simple:
instances:
webflux-demo:
- uri: http://localhost:8080
- uri: http://localhost:8081
I ran only one web application on 8080 port to respond to "hello-world" and tested gateway, but it doesn't seem to work as I intended. (There is no 8081 port application, so I thought the gateway would try it again with 8081 port and then request it with 8080 port.)
The log is printed as follows:
2022-07-14 21:44:27 | TRACE | HttpWebHandlerAdapter .traceDebug :116 | [reactor-http-nio-3] [292b2f3f-3] HTTP GET "/webflux-demo/hello", headers={masked}
2022-07-14 21:44:27 | TRACE | WeightCalculatorWebFilter .filter :252 | [reactor-http-nio-3] Weights attr: {}
2022-07-14 21:44:27 | TRACE | PathRoutePredicateFactory .traceMatch :61 | [reactor-http-nio-3] Pattern "/webflux-demo/**" matches against value "/webflux-demo/hello"
2022-07-14 21:44:27 | DEBUG | RoutePredicateHandlerMapping .lambda$lookupRoute$6 :142 | [reactor-http-nio-3] Route matched: spring-webflux-demo
2022-07-14 21:44:27 | DEBUG | RoutePredicateHandlerMapping .lambda$getHandlerInternal$0 :90 | [reactor-http-nio-3] Mapping [Exchange: GET http://localhost:80/webflux-demo/hello] to Route{id='spring-webflux-demo', uri=lb://webflux-demo, order=0, predicate=Paths: [/webflux-demo/**], match trailing slash: true, gatewayFilters=[[[StripPrefix parts = 1], order = 1]], metadata={}}
2022-07-14 21:44:27 | DEBUG | RoutePredicateHandlerMapping .lambda$getHandler$1 :189 | [reactor-http-nio-3] [292b2f3f-3] Mapped to org.springframework.cloud.gateway.handler.FilteringWebHandler@77920ce9
2022-07-14 21:44:27 | DEBUG | FilteringWebHandler .handle :85 | [reactor-http-nio-3] Sorted gatewayFilterFactories: [[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@b9d018b}, order = -2147483648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@45b32dfe}, order = -2147482648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@5438c17a}, order = -1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardPathFilter@6b4fc2d1}, order = 0], [[StripPrefix parts = 1], order = 1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@429aeac1}, order = 10000], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@3b7c80c6}, order = 10150], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.LoadBalancerServiceInstanceCookieFilter@3b2e5c0d}, order = 10151], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@8bd076a}, order = 2147483646], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyRoutingFilter@7499eac7}, order = 2147483647], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@79eeff87}, order = 2147483647]]
2022-07-14 21:44:27 | TRACE | RouteToRequestUrlFilter .filter :68 | [reactor-http-nio-3] RouteToRequestUrlFilter start
2022-07-14 21:44:27 | TRACE | ReactiveLoadBalancerClientFilter .filter :108 | [reactor-http-nio-3] ReactiveLoadBalancerClientFilter url before: lb://webflux-demo/hello
2022-07-14 21:44:27 | TRACE | DefaultListableBeanFactory .doGetBean :264 | [reactor-http-nio-3] Returning cached instance of singleton bean 'reactorServiceInstanceLoadBalancer'
2022-07-14 21:44:27 | TRACE | DefaultListableBeanFactory .doGetBean :264 | [reactor-http-nio-3] Returning cached instance of singleton bean 'discoveryClientServiceInstanceListSupplier'
2022-07-14 21:44:27 | TRACE | DefaultListableBeanFactory .doGetBean :264 | [reactor-http-nio-3] Returning cached instance of singleton bean 'retryAwareDiscoveryClientServiceInstanceListSupplier'
2022-07-14 21:44:27 | TRACE | ReactiveLoadBalancerClientFilter .lambda$filter$2 :144 | [reactor-http-nio-3] LoadBalancerClientFilter url chosen: http://localhost:8081/hello
2022-07-14 21:44:27 | TRACE | RouterFunctions .route :1080 | [reactor-http-nio-3] [292b2f3f-3] Matched org.springframework.web.reactive.function.server.RequestPredicates$$Lambda$962/0x0000000800624e90@2be765c0
2022-07-14 21:44:27 | DEBUG | AbstractErrorWebExceptionHandler .debug :147 | [reactor-http-nio-3] [292b2f3f-3] Resolved [AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8081] for HTTP GET /webflux-demo/hello
2022-07-14 21:44:27 | ERROR | AbstractErrorWebExceptionHandler .error :122 | [reactor-http-nio-3] [292b2f3f-3] 500 Server Error for HTTP GET "/webflux-demo/hello"
java.net.ConnectException: Connection refused
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337) [3 skipped]
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:710)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:995)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Wrapped by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8081
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 "/webflux-demo/hello" [ExceptionHandlingWebHandler]
Original Stack Trace:
2022-07-14 21:44:27 | TRACE | Jackson2JsonEncoder .trace :157 | [reactor-http-nio-3] [292b2f3f-3] Encoding [{timestamp=Thu Jul 14 21:44:27 KST 2022, path=/webflux-demo/hello, status=500, error=Internal Server Error, requestId=292b2f3f-3}]
2022-07-14 21:44:27 | TRACE | HttpWebHandlerAdapter .traceDebug :116 | [reactor-http-nio-3] [292b2f3f-3] Completed 500 INTERNAL_SERVER_ERROR, headers={masked}
2022-07-14 21:44:27 | TRACE | ReactorHttpHandlerAdapter .trace :157 | [reactor-http-nio-3] [292b2f3f-3, L:/[0:0:0:0:0:0:0:1]:80 - R:/[0:0:0:0:0:0:0:1]:55942] Handling completed
I also looked at the RetryGatewayFilterFactory provided by spring-cloud-gateway but it didn't seem to provide the above functionality.
I'd like to use the above properties (max-retries-on-next-service-instance
and max-retries-on-same-service-instance
) while using spring-cloud-gateway and spring-cloud-loadbalancer together, is there a way? Or I wonder if I read the manual incorrectly or if I didn't find a way.
same situation,finally i use RetryGatewayFilterFactory instead, Waiting for others to answer ==!
Same situation. Also, we were using ribbon for setting timeout for individual services registered on Eureka. That seems to be not possible in spring-cloud-loadbalancer. Reference : https://github.com/spring-cloud/spring-cloud-gateway/issues/2695
The Retry filter is the right way to go and ribbon properties are not supported.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.