Spring Cloud Edgware对Hystrix回退的逻辑进行了一些改进。本文将信息探讨新旧版本的回退操作,并分析的原因及改进后的优势。

Dalston及更低版本

对于Dalston及更低版本,要想为Zuul提供回退,只需编写代码如下:

  1. @Component

  2. public class MyFallbackProvider implements ZuulFallbackProvider {

  3.  @Override

  4.  public String getRoute() {

  5.    // 表明是为哪个微服务提供回退,*表示为所有微服务提供回退

  6.    return "*";

  7.  }

  8.  @Override

  9.  public ClientHttpResponse fallbackResponse() {

  10.    return new ClientHttpResponse() {

  11.      @Override

  12.      public HttpStatus getStatusCode() throws IOException {

  13.        // fallback时的状态码

  14.        return HttpStatus.OK;

  15.      }

  16.      @Override

  17.      public int getRawStatusCode() throws IOException {

  18.        // 数字类型的状态码,本例返回的其实就是200,详见HttpStatus

  19.        return this.getStatusCode().value();

  20.      }

  21.      @Override

  22.      public String getStatusText() throws IOException {

  23.        // 状态文本,本例返回的其实就是OK,详见HttpStatus

  24.        return this.getStatusCode().getReasonPhrase();

  25.      }

  26.      @Override

  27.      public void close() {

  28.      }

  29.      @Override

  30.      public InputStream getBody() throws IOException {

  31.        // 响应体

  32.        return new ByteArrayInputStream("用户微服务不可用,请稍后再试。".getBytes());

  33.      }

  34.      @Override

  35.      public HttpHeaders getHeaders() {

  36.        // headers设定

  37.        HttpHeaders headers = new HttpHeaders();

  38.        MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));

  39.        headers.setContentType(mt);

  40.        return headers;

  41.      }

  42.    };

  43.  }

  44. }

Edgware及更高版本

  1. @Component

  2. public class MyFallbackProvider implements FallbackProvider {

  3.  @Override

  4.  public String getRoute() {

  5.    // 表明是为哪个微服务提供回退,*表示为所有微服务提供回退

  6.    return "*";

  7.  }

  8.  @Override

  9.  public ClientHttpResponse fallbackResponse(Throwable cause) {

  10.    if (cause instanceof HystrixTimeoutException) {

  11.      return response(HttpStatus.GATEWAY_TIMEOUT);

  12.    } else {

  13.      return this.fallbackResponse();

  14.    }

  15.  }

  16.  @Override

  17.  public ClientHttpResponse fallbackResponse() {

  18.    return this.response(HttpStatus.INTERNAL_SERVER_ERROR);

  19.  }

  20.  private ClientHttpResponse response(final HttpStatus status) {

  21.    return new ClientHttpResponse() {

  22.      @Override

  23.      public HttpStatus getStatusCode() throws IOException {

  24.        return status;

  25.      }

  26.      @Override

  27.      public int getRawStatusCode() throws IOException {

  28.        return status.value();

  29.      }

  30.      @Override

  31.      public String getStatusText() throws IOException {

  32.        return status.getReasonPhrase();

  33.      }

  34.      @Override

  35.      public void close() {

  36.      }

  37.      @Override

  38.      public InputStream getBody() throws IOException {

  39.        return new ByteArrayInputStream("服务不可用,请稍后再试。".getBytes());

  40.      }

  41.      @Override

  42.      public HttpHeaders getHeaders() {

  43.        // headers设定

  44.        HttpHeaders headers = new HttpHeaders();

  45.        MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));

  46.        headers.setContentType(mt);

  47.        return headers;

  48.      }

  49.    };

  50.  }

  51. }

分析

由代码可知:

  • Dalston及更低版本通过实现 ZuulFallbackProvider 接口,从而实现回退;

  • Edgware及更高版本通过实现 FallbackProvider 接口,从而实现回退。

  • 在Edgware中:

  • FallbackProvider是ZuulFallbackProvider的子接口。

  • ZuulFallbackProvider已经被标注 Deprecated ,很可能在未来的版本中被删除。

  • FallbackProvider接口比ZuulFallbackProvider多了一个 ClientHttpResponsefallbackResponse(Throwablecause); 方法,使用该方法,可获得造成回退的原因。

  • 笔者将在下一篇文章详细总结在Spring Cloud中如何获得造成回退原因的各种姿势。