spring-cloud-gateway icon indicating copy to clipboard operation
spring-cloud-gateway copied to clipboard

How can I use retry property of spring-cloud-loadbalancer with gateway?

Open dhsim86 opened this issue 2 years ago • 2 comments

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

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.

dhsim86 avatar Jul 14 '22 11:07 dhsim86

same situation,finally i use RetryGatewayFilterFactory instead, Waiting for others to answer ==!

yugj avatar Jul 28 '22 12:07 yugj

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

aakashkarira avatar Aug 04 '22 15:08 aakashkarira

The Retry filter is the right way to go and ribbon properties are not supported.

spencergibb avatar Jan 19 '23 19:01 spencergibb

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.

spring-cloud-issues avatar Jan 26 '23 19:01 spring-cloud-issues

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.

spring-cloud-issues avatar Feb 02 '23 19:02 spring-cloud-issues