0

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

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

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

不幸的是,就像文档说的那样:

目前,仅支持 forward: 计划的 URI。如果调用了fallback,请求将被转发到URI匹配的控制器。

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

是否有计划尽快支持此功能?否则,我对这个特定用例有什么选择?

4

2 回答 2

0

我有类似的问题要解决。

我添加了新的后备路线,它奏效了。

.route(p -> p .path("/fallback/foo").uri("https://example.com"))
于 2020-04-30T17:00:53.753 回答
0

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

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

这是最终结果的样子:

应用程序.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);
                });
     }
}
于 2018-07-06T16:43:22.940 回答