springcloud之微服務zuul組件實現

springcloud常用組件
1、服務註冊與發現:Eureka
2、服務網關: Zuul
3、服務負載均衡:Ribbon
4、服務之間調用:Feign
5、服務熔斷:Hystrix   ---因官網不繼續維護,可以使用阿里提供的Alibaba Sentinel 輕量級的流量控制、熔斷降級 Java 庫
6、配置中心:config     ---如果不想自己維護,可以使用阿里雲nacos作爲配置中心


2、zuul路由網管
主要權限驗證和限流,
(1)、權限驗證:這裏具體用ZuulFilter實現

方法說明
filterType : filter類型,分爲pre、error、post、 route
filterOrder: filter執行順序,通過數字指定,數字越小,執行順序越先
shouldFilter: filter是否需要執行 true執行 false 不執行
run : filter具體邏輯(上面爲true那麼這裏就是具體執行邏輯)

filter類型說明
pre: 請求執行之前filter
route: 處理請求,進行路由
post: 請求處理完成後執行的filter
error: 出現錯誤時執行的filter


 

/**
 * 登錄過濾器
 *記得類上加Component註解
 */
@Component
public class LoginFilter extends ZuulFilter {

    /**
     * 過濾器類型,前置過濾器
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 過濾器順序,越小越先執行
     */
    @Override
    public int filterOrder() {
        return 4;
    }

    /**
     * 過濾器是否生效
     * 返回true代表需要權限校驗,false代表不需要用戶校驗即可訪問
     */
    @Override
    public boolean shouldFilter() {

        //共享RequestContext,上下文對象
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        System.out.println(request.getRequestURI());
        //需要權限校驗URL
        if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        } else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        } else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }
        return false;
    }

    /**
     * 業務邏輯
     * 只有上面返回true的時候,纔會進入到該方法
     */
    @Override
    public Object run() throws ZuulException {

        //JWT
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //token對象,有可能在請求頭傳遞過來,也有可能是通過參數傳過來,實際開發一般都是請求頭方式
        String token = request.getHeader("token");

        if (StringUtils.isBlank((token))) {
            token = request.getParameter("token");
        }
        System.out.println("頁面傳來的token值爲:" + token);
        //登錄校驗邏輯  如果token爲null,則直接返回客戶端,而不進行下一步接口調用
        if (StringUtils.isBlank(token)) {
            // 過濾該請求,不對其進行路由
            requestContext.setSendZuulResponse(false);
            //返回錯誤代碼
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }
}


具體操作用如下代碼
原文章地址:https://www.cnblogs.com/qdhxhz/p/9601170.html

(2)、限流:這裏採用ZuulFilter + RateLimiter(基於guava框架來做網關限流),RateLimiter是令牌桶算法

 

/**
 * 訂單限流
 *其它和上面都一樣,只是run()中邏輯不一樣
 */
@Component
public class OrderRateLimiterFilter extends ZuulFilter {


    //每秒產生1000個令牌
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return -4;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //只對訂單接口限流
        if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();

        //就相當於每調用一次tryAcquire()方法,令牌數量減1,當1000個用完後,那麼後面進來的用戶無法訪問上面接口
        //當然這裏只寫類上面一個接口,可以這麼寫,實際可以在這裏要加一層接口判斷。
        if (!RATE_LIMITER.tryAcquire()) {
            requestContext.setSendZuulResponse(false);
            //HttpStatus.TOO_MANY_REQUESTS.value()裏面有靜態代碼常量
            requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
        }
        return null;
    }
}

文章來源:https://www.cnblogs.com/qdhxhz/p/9601170.html

下一篇文章介紹漏桶算法和令牌桶算法區別

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