首頁>技術>

前言

閘道器服務在SpringCloud中有很重要的作用。

可以將服務跟外網進行隔離起到一定的保護作用,同時服務間區域網通訊更加快捷。而且在閘道器中可以做限流、許可權校驗,使得服務更加專注自身業務。比如說下訂單需要登入許可權,限流,我們在本篇將介紹如何使用。

搭建閘道器專案

注意:需要新增Eureka Discovery,Zuul路由元件。

1.入口新增@EnableZuulProxy註解

2.配置檔案

server:  port: 9000#指定註冊中心地址eureka:  client:    serviceUrl:      defaultZone: http://localhost:8761/eureka/#服務的名稱spring:  application:    name: api-gateway#自定義路由對映zuul:  routes:    order-service: /apigateway/order/**    product-service: /apigateway/product/**  #統一入口為上面的配置,其他入口忽略  ignored-patterns: /*-service/**  #處理http請求頭為空的問題  sensitive-headers:

我們啟動EurekaServer、productService、OrderService、apigateway,透過訪問:

統一對外只允許apigateway/product/,apigateway/order/形式訪問介面,這樣就對外做了一次遮蔽,隱藏了真實的服務api。

閘道器上做許可權校驗

許可權校驗需要透過實現ZuulFilter進行攔截。

package com.ckmike.api_gateway.filter;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;import org.apache.commons.lang.StringUtils;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;/** * LoginFilter 簡要描述 * <p> TODO:描述該類職責 </p> * * @author ckmike * @version 1.0 * @date 18-11-24 下午3:53 * @copyright ckmike **/@Componentpublic class LoginFilter extends ZuulFilter {    public static final String PRE_TYPE = "pre";    // 前置過濾器    @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();        System.out.println("address:" + request.getRemoteAddr());        System.out.println("uri:" + request.getRequestURI());        System.out.println("url:" + request.getRequestURL());        // 這裡可以結合ACL進行本地化或者放入到redis        if ("/apigateway/order/api/v1/order/saveforribbon".equalsIgnoreCase(request.getRequestURI())) {            return true;        }        return false;    }    @Override    public Object run() throws ZuulException {        RequestContext requestContext = RequestContext.getCurrentContext();        HttpServletRequest request = requestContext.getRequest();        String token = request.getHeader("token");        if (StringUtils.isBlank(token)) {            token = request.getParameter("token");        }        if (StringUtils.isBlank(token)) {            requestContext.setSendZuulResponse(false);            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());        }        return null;    }}

啟動之後訪問對應的介面

到此說明我們以及做好閘道器的許可權校驗,通常我們都會結合redis+ACL方式進行,但這裡因為簡單我直接透過字串進行校驗,有興趣可自行擴充套件redis+ACl做。

閘道器限流

通常系統都有一個承受極限,我們通常可以nginx做一限流,我們也可以透過閘道器進行限流,閘道器限流是透過每秒生成令牌作為訪問通行標識,這裡使用了guava做令牌生成。程式碼如下:

package com.ckmike.api_gateway.filter;import com.google.common.util.concurrent.RateLimiter;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;/** * OrderRateLimiteFilter 簡要描述 * <p> TODO:描述該類職責 </p> * * @author ckmike * @version 1.0 * @date 18-11-24 下午5:33 * @copyright ckmike **/@Componentpublic class OrderRateLimiteFilter extends ZuulFilter {    public static final String PRE_TYPE = "pre";    //每秒鐘產生1000個令牌,guava    private static final RateLimiter rateLimiter = 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/saveforribbon".equalsIgnoreCase(request.getRequestURI())) {            return true;        }        return false;    }    @Override    public Object run() throws ZuulException {        RequestContext requestContext = RequestContext.getCurrentContext();        if (!rateLimiter.tryAcquire()) {            requestContext.setSendZuulResponse(false);            requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());        }        return null;    }}

我們可以透過jmeter進行壓力測試,對/apigateway/order/api/v1/order/saveforribbon介面進行壓力測試,這樣我們就可以很好的測試上面的內容。

18
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • maven設定HTTP代理