SpringCloud(六):Zuul的Fallback回退机制

Zuul回退机制

默认情况下,经过Zuul的请求都会使用Hystrix进行包裹,所以Zuul本身就具有断路器的功能。

未指定路由配置回退

  • 代码示例如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    package com.mmzs.cloud.fallback;

    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;

    import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.client.ClientHttpResponse;
    import org.springframework.stereotype.Component;

    import com.netflix.hystrix.exception.HystrixTimeoutException;

    /**
    * @author: mmzsit
    * @date: 2018年11月14日
    * @Description: 用于定制FallBack返回的body、状态码、消息头Header
    * 博客地址:https://blog.csdn.net/MobiusStrip
    * @version V1.0
    */
    @Component
    public class MyFallbackProvider implements FallbackProvider {

    @Override
    public String getRoute() {
    return "microservice-provider-user";
    //微服务配了路由的话,就用配置的名称
    //return "customers";
    //如果要为所有路由提供默认回退,可以创建FallbackProvider类型的bean并使getRoute方法返回*或null
    //return "*";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, final Throwable cause) {
    if (cause instanceof HystrixTimeoutException) {
    return response(HttpStatus.GATEWAY_TIMEOUT);
    } else {
    return response(HttpStatus.INTERNAL_SERVER_ERROR);
    }
    }

    private ClientHttpResponse response(final HttpStatus status) {
    return new ClientHttpResponse() {
    @Override
    public HttpStatus getStatusCode() throws IOException {
    //return status;
    return HttpStatus.BAD_REQUEST;
    }

    @Override
    public int getRawStatusCode() throws IOException {
    //return status.value();
    return HttpStatus.BAD_REQUEST.value();
    }

    @Override
    public String getStatusText() throws IOException {
    //return status.getReasonPhrase();
    //return HttpStatus.BAD_REQUEST.name();
    return HttpStatus.BAD_REQUEST.getReasonPhrase();
    }

    @Override
    public void close() {
    }

    @Override
    public InputStream getBody() throws IOException {
    return new ByteArrayInputStream(("fallback:"+MyFallbackProvider.this.getRoute()).getBytes());
    }

    @Override
    public HttpHeaders getHeaders() {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    return headers;
    }
    };
    }
    }

==[注]== 其中代理的路由如果在 application.yml中配置过,也可以有如下示例:

1
2
3
zuul:
routes:
customers: /myuser/**

为所有路由提供默认回退 

如果要为所有路由提供默认回退,可以创建FallbackProvider类型的bean并使getRoute方法返回*或null

  • 代码示例如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    class MyFallbackProvider implements FallbackProvider {
    @Override
    public String getRoute() {
    return "*";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable throwable) {
    return new ClientHttpResponse() {
    @Override
    public HttpStatus getStatusCode() throws IOException {
    return HttpStatus.OK;
    }

    @Override
    public int getRawStatusCode() throws IOException {
    return 200;
    }

    @Override
    public String getStatusText() throws IOException {
    return "OK";
    }

    @Override
    public void close() {

    }

    @Override
    public InputStream getBody() throws IOException {
    return new ByteArrayInputStream("fallback".getBytes());
    }

    @Override
    public HttpHeaders getHeaders() {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    return headers;
    }
    };
    }
    }