1. 程式人生 > >Spring Cloud學習筆記(九)-閘道器Zuul使用熔斷器和過濾器

Spring Cloud學習筆記(九)-閘道器Zuul使用熔斷器和過濾器

說明:本文僅作為本人學習<<深入理解Spring Cloud與微服務構建>>一書的學習筆記,所有程式碼案例及文字描述均參考該書,不足之處,請留言指正,不勝感激.
一.在Zuul上配置熔斷器
  上一篇提到zuul的起步依賴集成了ribbon和hystrix,接下來我們來看看如何在閘道器上實現熔斷功能.
  首先我們需要了解在Zuul中實現熔斷功能需要實現ZuulFallbackProvider的介面.實現該介面有兩個方法,一個是getRoute()方法,用於指定熔斷功能應用於哪個路由服務;另一個方法fallbackResponse()為進入熔斷功能時執行的邏輯.具體實現可以參看如下程式碼:

/**
 * 閘道器熔斷配置
 *
 * @author zhyu
 * @version v1.0
 * @date 2018年07月03日 19:54:28
 */
@Component
public class MyZuulFallbackProvider implements ZuulFallbackProvider {
    @Override
    public String getRoute() {
        //實現對producer-server服務的熔斷
        return "producer-server";
        //return "*";  實現對所有的路由服務的熔斷
} @Override public ClientHttpResponse fallbackResponse() { 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("{\"status\":500,\"message\":\"sorry,the system goes to sleep,please try again later!\"}".getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } }; } }

接著我們啟動eureka-server,zuul-server服務,不啟動producer-server服務,然後通過閘道器訪問producer-server的介面,結果如下:
這裡寫圖片描述
可見,熔斷器配置起了作用,如果我們將getRoute()方法的返回改為”*”,那麼將對所有的路由服務都加熔斷功能.
二.在Zuul中使用過濾器
  在Zuul中自定義過濾器很簡單,只需要繼承ZuulFilter,並實現它的抽象方法就好,最後將其注入到IoC容器,如下:

package com.example.zuulserver.Filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;

/**
 * 自定義過濾器
 * 實現起來很簡單,只需要繼承ZuulFilter,並實現它的抽象方法
 * @author zhyu
 * @version v1.0
 * @date 2018年07月05日 19:11:49
 */
@Component
public class MyZuulFilter extends ZuulFilter {
    /**
     * 返回過濾器的型別
     * @return
     */
    @Override
    public String filterType() {
        /**
         * Zuul有一下四種過濾器
         * "pre":是在請求路由到具體的服務之前執行,這種型別的過濾器可以做安全校驗,例如身份校驗,引數校驗等
         * "routing":它用於將請求路由到具體的微服務例項,在預設情況下,它使用Http Client進行網路請求
         * "post":它是在請求已被路由到微服務後執行,一般情況下,用作收集統計資訊,指標,以及將響應傳輸到客戶端
         * "error":它是在其他過濾器發生錯誤時執行
         */
        return "pre";
    }

    /**
     * 過濾順序,值越小,越早執行該過濾器
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 表示該過濾器是否過濾邏輯,如果是ture,則執行run()方法;如果是false,則不執行run()方法.
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 具體的過濾邏輯
     * 本例中,檢查請求的引數中是否傳了token這個引數,如果沒傳,則請求不被路由到具體的服務例項,
     * 直接返回響應,狀態碼為401
     * @return
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String token = request.getParameter("token");
        if(token == null){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try{
                ctx.getResponse().getWriter().write("token is empty");
            }catch(Exception e){

            }
        }
        return null;
    }
}

然後我們啟動服務,當我們不帶token時,瀏覽器顯示如下:
這裡寫圖片描述
這次我們帶上token,再訪問:
這裡寫圖片描述