Zuul(二)過濾

過濾器

Zuul作爲網關的其中一個重要功能, 就是實現請求的鑑權。而這個動作我們往往是通過Zuul提供的過濾器來實現的

ZuulFilter

ZuulFilter是過濾器的頂級父類。在這裏我們看一- 下其中定義的4個最重要的方法:

public abstract class ZuulFilter implements IZuulFilter {
    public abstract String filterType();//過濾器類型

    public abstract int filterOrder();//過濾器順序

    public abstract boolean shouldFilter();//要不要過濾,來自IZuulFilter

    public abstract Object run() throws ZuulException;//過濾邏輯,來自IZuulFilter
}
shouldFilter:返回一個boolean值,判斷該過濾器是否需要執行,返回true執行,返回false不執行。
run:過濾器的具體業務邏輯
filterType:返回字符串,代表過濾器的類型,包含以下4種:
    pre:請求在被路由之前執行
    routing:在路由請求時調用
    post:在routing和error過濾器之後調用
    error:處理請求時發生錯誤調用
filterOrder:通過返回的int值來定義過濾器的執行順序,數字越小優先級越高

過濾器執行生命週期

這張是Zuul官網提供的請求生命週期圖,清晰的表現了一次請求在各個過濾器的執行順序。

在這裏插入圖片描述
●“custom” filter是自定義filter可以任意指定其類型,
●“error” filter是當"pre” filter 、“routing” filter、 “post” filter任何一個出現問題時,會跳到這個“error” filter,它執行完畢後後返回給“post” filter最終返回給客戶端瀏覽器。
●流程細說:
一次http請求首先會到達 "pre” filter (內置過濾器) :主要是對請求進行處理解析,如:請求參數、頭的處理解析等。執行完畢後,說明request請求處理完成,請求已經準備就緒,就應該轉發給具體的微服務(Origin server 遠程服務)了。“routing” filter會根據路由規則,把請求轉發給具體的微服務,微服務處理完成後,把結果返回給“routing” filter,“routing” filter 會對結果有一個處理或者不處理。“routing” filter 放行後到“post” filter (後置過濾器) , 如果沒有問題就返回給客戶端了,所以這裏的前置、後置是針對 “routing” filter的。
●正常流程:
請求到達首先會經過pre類型過濾器,而後到達routing類型, 進行路由,請求就到達真正的服務提供者,執行請求,返回結果後,會到達post過濾器。而後返回響應。
●異常流程:
1.整介過程中,pre或者routing過濾器出現異常, 都會直接進入error過濾器,再error處理完畢後,會將請求交給POST過濾器,最後返回給用戶。
2. 如果是error過濾器自己出現異常,最終也會進入POST過濾器,而後返回。
3. 如果是POST過濾器出現異常,會跳轉到error過濾器, 但是與pre和routing不同的時,請求不會再到達POST過濾器了。

使用場景

場景非常多:
●請求鑑權:一般放在pre類型,如果發現沒有訪問權限,直接就攔截了
●異常處理:一般會在error類型和post類型過濾器中結合來處理。
●服務調用時長統計: pre和post結合使用。

自定義過濾器

package com.baidu.filter;

import com.netflix.zuul.IZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public  class LoginFilters implements IZuulFilter {
    public  String filterType(){
        //設置過濾器類型
        return FilterConstants.PRE_TYPE;
    }

    //過濾器執行順序,當一個請求在同一個階段存在多個過濾器的時候,多個過濾器執行順序。
    public  int filterOrder(){
        //設置過濾器順序
        return  FilterConstants.PRE_DECORATION_FILTER_ORDER-1;
    }

    public  boolean shouldFilter(){
        return true;
    }

    //過濾邏輯
    public  Object run() throws ZuulException{
        //獲取請求上下文RequestContext:是一個域,作用範圍:從請求到達zuul一直到路由結束返回客戶端。
        RequestContext context = RequestContext.getCurrentContext();
        //獲取request
        HttpServletRequest request = context.getRequest();
        //獲取請求參數
        String token = request.getParameter("access-token");

        //判斷是否存在
        if(StringUtils.isBlank(token)){
            //不存在,未登錄,就攔截,參數是false就攔截
            context.setSendZuulResponse(false);
            //返回403
            context.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
        }
        return null;
    }
}

這樣訪問路徑要加參數,例如:http://localhost:10010/user/user/findById/2?access-token=huijie,否則會被攔下,出現403

負載均衡

Zuul中默認就已經集成了Ribbon負載均衡和Hystix熔斷機制。但是所有的超時策略都是走的默認值,比如熔斷超時時間只有1S,很容易就觸發了。因此建議我們手動進行配置:

Zuul的高可用

啓動多個Zuul服務,自動註冊到Eureka,形成集羣。如果是服務內部訪問,你訪問Zuul,自動負載均衡,沒問題。但是,Zuul更多是外部訪問,PC端、 移動端等。他們無法通過Eureka進行負載均衡,那麼該怎麼辦?此時,我們會使用其它的服務網關,來對Zuu進行代理。比如: Nginx、Eureka、Ribbon、Hystix、 Feign、 Zuul

spring-cloud-config:統一配置中心,自動去Git拉取最新的配置,緩存。使用Git的Webhook鉤子, 去通知配置中心,說配置發生了變化,配置中心會通過消息總線去通知所有的微服務,更新配置。
spring-cloud-bus:消息總線
Spring-cloud-stream:消息通信
spring -cloud-hystrix dashboard:容錯統計,形成圖形化界面
spring-cloud-sleuth:鏈路追蹤結合Zipkin

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章