SpringCloud之網關服務(gateway)
阿新 • • 發佈:2018-11-25
quest cat jmeter 屏蔽 sign gin thead roc run 前言
網關服務在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 **/ @Component public 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 **/ @Component public 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接口進行壓力測試,這樣我們就可以很好的測試上面的內容。
SpringCloud之網關服務(gateway)