使用Spring Cloud Gateway调用内部服务失败时,如何重试外部服务?

时间:2018-07-05 16:22:47

标签: spring-boot spring-cloud-gateway

我正在实现一种服务,该服务模拟网络上可用的另一种服务。 我正在尝试配置Spring Cloud网关,以在对我的实现的调用失败时将请求重新路由到公共服务。

我尝试通过以下方式使用Hystrix过滤器:

spring:
  cloud:
    gateway:
      routes:
      - id: foo
        uri: http://my-internal-service/
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: https://the.public.service/

不幸的是,就像documentation所说:

  

当前,仅支持转发:计划的URI。如果调用后备,则请求将被转发到与URI相匹配的控制器。

因此,我不能使用fallbackUri: https://...

是否有计划支持此功能? 否则,对于该特定用例,我有哪些选择?

2 个答案:

答案 0 :(得分:0)

我最终得到了一种hacky解决方法,该解决方法似乎适用于我的特定用例(即GET请求):

  1. 在网关应用程序中创建我自己的后备控制器
  2. 配置hystrix后备指向该控制器
  3. 使用WebClient拨打我的公共服务

最终结果如下:

application.yml

spring:
  cloud:
    gateway:
      default-filters:
      - name: AddResponseHeader
        args:
          name: X-Data-Origin
          value: My internal service
      routes:
      - id: foo
        uri: http://my-internal-service/
        filters:
        - name: Hystrix
          args:
            name: local-service-fallback
            fallbackUri: forward:/fallback/foo

FallbackController.java

@RestController
@RequestMapping(path = "/fallback")
public class FallbackController {

    private static final String fallbackUri = "https://the.public.service";

    WebClient webClient;

    public FallbackController() {
        webClient = WebClient.create(fallbackUri);
    }

    @GetMapping("/foo")
    Mono<MyResponse> foo(ServerWebExchange failedExchange) {
        failedExchange.getResponse().getHeaders().remove("X-Data-Origin");
        failedExchange.getResponse().getHeaders().add("X-Data-Origin", "The public service");

        // Now call the public service using the same GET request
        UriComponents uriComponents = UriComponentsBuilder.newInstance()
            .uri(URI.create(fallbackUri))
            .path("/path/to/service")
            .queryParams(failedExchange.getRequest().getQueryParams())
            .build();

        return WebClient.create(uriComponents.toUriString())
                .get()
                .accept(MediaType.TEXT_XML)
                .exchange()
                .doOnSuccess(clientResponse -> {
                // Copy the headers from the public service's response back to our exchange's response
                    failedExchange.getResponse().getHeaders()
                         .addAll(clientResponse.headers().asHttpHeaders());
                })
                .flatMap(clientResponse -> {
                    log.info("Data origin: {}", 
                             failedExchange.getResponse().getHeaders().get("X-Data-Origin"));
                    return clientResponse.bodyToMono(MyResponse.class);
                });
     }
}

答案 1 :(得分:0)

我有类似的问题要解决。

我添加了新的备用路线,并且有效。

.route(p -> p .path("/fallback/foo").uri("https://example.com"))