從零搭建一個SpringCloud項目之Zuul(四)

整合Zuul

為什麼要使用Zuul?

  • 易於監控
  • 易於認證
  • 減少客戶端與各個微服務之間的交互次數
  1. 引入依賴
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
  1. 配置文件
  2. 開啟註解

啟動類上加@EnableZuulProxy

備註:不配置任何配置文件時,啟動zuul服務,zuul可以通過服務名去訪問到其他服務。

例://localhost:8000/study-trade/trade/testTrade/2

二、配置詳解

  1. 路徑映射
#關閉通過微服務名稱訪問
zuul.ignored-services=*

#指定微服務名稱和路徑的映射
#zuul.routes.study-trade=/strade/**

#指定微服務名稱和路徑的映射,是否剝離前綴
zuul.routes.study-trade.service-id=study-trade
zuul.routes.study-trade.path=/orderservice/**
zuul.routes.study-trade.strip-prefix=true

#指定ip映射,而不用負載均衡
#zuul.routes.study-trade.url=//localhost:8005/
#zuul.routes.study-trade.path=/st/**

#為我們目標下游服務器設置統一的請求前綴
# 本來是//localhost:8000/strade/trade/testTrade/2 的配置了就需要//localhost:8000/study-springcloud/strade/trade/testTrade/2才能訪問
#zuul.prefix=/study-springcloud
#是否剝離請求前綴
#zuul.strip-prefix=true

#屏蔽敏感的路徑
zuul.ignored-patterns=/**/admin/**

#過濾敏感頭信息,不加這行,cookie,setcookie,authrotion三個同步信息不能傳遞的,等號後不用寫值
zuul.routes.study-trade.sensitive-headers=

#禁用Zuul的過濾器  simpleClassname代表類名
#zuul.simpleClassname.pre|router|post|error=true
  1. 降級回退
  • 宕機回退
  • 超時回退(ribbon.ConnectionTimeout=4000
    ribbon.ReadTimeout=4000)

代碼實現:

/**
 * @description: Zull的降級回退
 * @author: mmc
 * @create: 2020-04-12 22:39
 **/
@Component
public class ZuulFallBack implements FallbackProvider {

    @Override
    public String getRoute() {
        //可以填微服務實例名稱或*
        return "*";
    }

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

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

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("後端服務異常".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders=new HttpHeaders();
                httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
                return httpHeaders;
            }
        };
    }
}
  1. 過濾器
@Component
public class ThrowExeceptionFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
       return null;
    }
}

  1. 統一異常處理
  • 4.1 禁用系統異常

    zuul.SendErrorFilter.error.disable=true

  • 4.2 自定義異常處理類

@Component
public class ErrorFilter extends SendErrorFilter {

    @Override
    public Object run() {
       try{
           RequestContext ctx = RequestContext.getCurrentContext();
           HttpServletRequest request = ctx.getRequest();
           HttpServletResponse response = ctx.getResponse();
           ExceptionHolder exception = findZuulException(ctx.getThrowable());
           response.setContentType("application/json;charset=utf-8");
           response.setCharacterEncoding("UTF-8");

           Map<String,Object> errorMap=new HashMap<>();
           errorMap.put("code","-1");
           errorMap.put("errMsg",exception.getThrowable().getCause().getMessage());
           response.getWriter().write(JSON.toJSONString(errorMap));
       }catch (Exception e){
           try {
               ReflectionUtils.rethrowException(e);
           } catch (Exception e1) {
               e1.printStackTrace();
           }
       }
       return null;
    }
}