Spring Cloud Zuul fallback service

时间:2017-06-19 14:05:15

标签: spring spring-cloud netflix-zuul

Is it possible to setup a proxy to a main server/servers/service but when this is not available, redirect requests to a secondary server/servers/service?

The secondary service is not an instance of the same type of the primary one. Their API is compatible but not the same. The secondary is a less-performant last resource when the primary is not available.

We are not using Eureka, only fixed IPs yet.

zuul:
  routes:
    whatever:
      path: /whatever/**
      sensitiveHeaders: Cookie,Set-Cookie
      url: http://server1:8080/whatever

I had a look on ZuulFallbackProvider, but this interface is to provided a fixed response on case of error. I want, when http://server1:8080/whatever is not responding, redirect to http://server2:8080/whateverApi2.

Thanks.

3 个答案:

答案 0 :(得分:4)

您可以使用ZuulFallbackProvider执行此操作,但您需要先配置以下内容。

首先,url-routing - 直接在zuul.routes.<service>.url中指定url - 在Zuul中不在HystrixCommand中执行。为此,您需要更改您的配置,如下所示。

zuul:
  routes:
    whatever:
      path: /whatever/**
      sensitiveHeaders: Cookie,Set-Cookie
      serviceId: whatever
      stripPrefix: false

ribbon:
  eureka:
    enabled: false

whatever:
  ribbon:
    listOfServers: http://server1:8080/

以上配置使用Ribbon而不使用eureka。你可以找到详细信息here

现在,您的请求将通过Ribbon在HystrixCommand中执行。所以你可以提供自己的ZuulFallbackProvider。

在ZuulFallbackProvider中,您可以通过以下http://server2:8080/whateverApi2.方法向fallbackResponse发送回复请求。以下是一个非常天真的例子。 :-)您需要为自己的目的完成以下示例。

@Component
public class TestZuulFallbackProvider implements ZuulFallbackProvider{
    @Override
    public String getRoute() {
        return "test";
    }

    @Override
    public ClientHttpResponse fallbackResponse() {

        ResponseEntity<String> response = new RestTemplate().exchange("http://server2:8080/whateverApi2", HttpMethod.GET, null, String.class);
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return response.getStatusCode();
            }
            @Override
            public int getRawStatusCode() throws IOException {
                return response.getStatusCodeValue();
            }
            @Override
            public String getStatusText() throws IOException {
                return response.getStatusCode().getReasonPhrase();
            }
            @Override
            public void close() {
            }
            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream(response.getBody().getBytes("UTF-8"));
            }
            @Override
            public HttpHeaders getHeaders() {
                return response.getHeaders();
            }
        };
    }
}

答案 1 :(得分:4)

如果有人试图做类似的事情,实际工作的不是使用任何Zuul组件,而是使用Hystrix。

在Gateway API中,我们创建一个façade控制器,响应我们想要设置回退解决方案的服务:

    @HystrixCommand(fallbackMethod = "fallbackWhatever")
@PostMapping
ResponseEntity<Object> whatever(final RequestEntity<?> request) {
    return defaultClient.searchSubmissions(request.getHeaders(), request.getBody());
}

ResponseEntity<Object> fallbackWhatever(final RequestEntity<?> request) {
    return fallbackClient.searchSubmissions(request.getHeaders(), request.getBody());
}

defaultClient和fallbackClient是两个不同的FeignClient接口,每个接口都指向每个服务端点。

就是这样!如果您关闭主服务,Gateway API将开始调用回退服务,而不会返回单个服务不可用,并且更改只需几毫秒。

此外,如果你再打开它,它在准备好后几毫秒就会回复。

答案 2 :(得分:0)

需要添加可重试

zuul:
  routes:
    whatever:
      path: /whatever/**
      sensitiveHeaders: Cookie,Set-Cookie
      url: http://server1:8080/whatever
      retryable=true

类似的situation