Spring Cloud Zuul回退服务

4

是否可以设置代理到主服务器/服务,但当主服务器/服务不可用时,将请求重定向到次要服务器/服务?

次要服务不是与主要服务相同类型的实例。它们的API兼容但不相同。当主服务器不可用时,次要服务器是一个性能较差的最后资源。

我们没有使用Eureka,只有固定IP地址。

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

我查看了ZuulFallbackProvider,但这个接口是在出现错误时提供固定响应的。当http://server1:8080/whatever没有响应时,我希望重定向到http://server2:8080/whateverApi2。谢谢。
3个回答

6
您可以使用ZuulFallbackProvider来实现此功能,但首先需要进行以下配置。
首先,在Zuul中直接指定zuul.routes.<service>.url的URL路由不会在HystrixCommand中执行。为了实现这一点,您需要像下面这样更改配置。
zuul:
  routes:
    whatever:
      path: /whatever/**
      sensitiveHeaders: Cookie,Set-Cookie
      serviceId: whatever
      stripPrefix: false

ribbon:
  eureka:
    enabled: false

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

上述配置是在不使用Eureka的情况下使用Ribbon。你可以在此处找到详细信息。(链接) 现在,你的请求将通过Ribbon执行HystrixCommand。因此,你可以提供自己的ZuulFallbackProvider。
在ZuulFallbackProvider中,你可以像以下示例代码一样,在fallbackResponse方法中向你的http://server2:8080/whateverApi2.发起回退请求。下面是一个非常简单的示例 :-) 你需要根据自己的目的完成以下示例。
@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();
            }
        };
    }
}

感谢您的回答。我暂时不会将其标记为解决方案,只是想看看是否有任何“仅配置”的替代方案。我将使用您的解决方案,甚至在使用完整的Spring Cloud基础设施时,可能会直接使用Netflix OSS组件之一而不是RestTemplate。 - Ricardo Piccoli
我终于回到了这个问题,并尝试了这种方法。但是ZuulFallbackProvider是一个静态的fallback。有没有Zuul、Ribbon或Hystrix可以实际重定向请求到我的fallback服务?我不想将其添加到Ribbon服务器列表中,因为我希望它作为最后的手段执行,仅在服务器宕机时才会使用。 - Ricardo Piccoli
1
如果您不想使用Hystrix回退,我认为另一个可能的方法是创建自己的完整路由或后置过滤器。在您的过滤器中,您可以检查原始请求的结果,然后使用适当的参数将请求转发到备用服务器。 - yongsung.yoon

4
如果有人想做类似的事情,实际上使用Hystrix而不是Zuul组件是有效的。在网关API中,我们创建一个门面控制器来响应我们想要设置回退解决方案的服务。
@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接口,每个接口都指向不同的服务端点。

就是这样!如果你关闭主服务,网关API会立即调用备用服务而不会返回任何一个服务不可用的错误,并且这个变化只需要几毫秒的时间。

同样地,如果你重新启动它,它也会在几毫秒后重新响应。


0

需要添加可重试

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

类似情况


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接