0

Trying out Spring Cloud Gateway with Spring Boot microservices registered/discovered via Eureka server. The setup is working fine and clients can call the discovered services via the gateway without problem which is great.

Now, I am trying to test a scenario where a client calls a service (via the gateway) for which currently there are no instances available to service the call (i.e. service is down). When we test this scenario, the default behaviour is that the client gets a 500 Internal Server Error response. What would be the simplest way to change this default behaviour to return a 503 Service Unavilable response instead?

Current Stack:

Java 8
Spring Boot 2.0.0.M6 
Spring Cloud 2.0.0.M3
Spring Cloud Starter Eureka 2.0.0.M2 (in Gateway JVM)
Spring Cloud Starter Netflix Ribbon 2.0.0.M3 (in Gateway JVM)
Spring Cloud Starter Netflix Eureka Server 2.0.0.M3 (in Eureka Server JVM)
Going Bananas
  • 2,265
  • 3
  • 43
  • 83

3 Answers3

1

In the end we have decided to leave the error response as it is. i.e. HTTP 500 - Unable to find instance for test-service-name. We have however added functionality to the Gateway's Routing mechanism to include an enabled: true|false flag to each Route which now allows us to temporarily enable/disable access to those microservices as desired. We are doing this by re-building Routes which are marked with enabled: false to include a GatewayFilter in them which returns:

Mono.error(new WebRequestException(HttpStatus.SERVICE_UNAVAILABLE, "SERVICE_UNAVAILABLE",
            "Service is down for maintenance"));

whenever a call to that enabled: false Route is called.

The WebRequestException is our own Throwable class which we then intercept in our own WebExceptionHandler which handles the ServerWebExchange's ServerHttpResponse as needed.

Note 1: The Gateway is using spring-boot-starter-webflux within.

Note 2: Whenever we change the state of a Route's enabled flag we: 1) Re-build the Route, 2) Call CachingRouteLocator Bean's .refresh() method in order for the Route to be re-cached with|without the GatewayFilter in place.

Going Bananas
  • 2,265
  • 3
  • 43
  • 83
0

The question is quite similar to:

https://stackoverflow.com/a/69257852/12952273

but is asked in different way.

There is a pattern known as Circuit Breaker and it helps avoid cascade failures (cascade failure can happen if the being called service is not responding)

https://martinfowler.com/bliki/CircuitBreaker.html

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/29881432) – isopach Sep 21 '21 at 14:30
-1

This might be a little hacky, but why not add a controller advice? Something like this should get you there.

@ControllerAdvice
public class ServiceNotFoundHandler {
    @ExceptionHandler(NotFoundException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    public String handleUnavailableService(NotFoundException e) {
        return "service unavailable";
    }
}
iLikeBreakfast
  • 1,545
  • 23
  • 46