作为网关至少要有三大功能:
1.路由功能,能够将内外网分离。
2.过滤功能,包括登录鉴权等
3.限流的功能

为了能够满足网关的上述的三大功能这里选择了Zuul+RateLimiter 来实现。
1.application.yml
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8081/eureka/
server:
port: 8087
spring:
application:
name: api_gateway
redis:
host: localhost
port: 6379
zuul:
routes:
order_service: /api_gateway/**
ignored-services: "*_service/**"
2.pom.xml 主要的包:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0-jre</version>
</dependency>
3.路由功能
zuul:
routes:
order_service: /api_gateway/**
ignored-services: "*_service/**"
原来直接请求/order_service订单服务,通过zuul的路由配置统一通过/api_gateway/来请求,隐藏了真实的内网服务路径。当然这里需要结合物理网络进行内外网隔离。
4.登录鉴权
登录鉴权是通过ZuulFilter 来进行过滤的。
@Component
public class LoginFilter extends ZuulFilter {
/**
* 过滤器类型,前置过滤器
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器顺序,越小越先执行
* @return
*/
@Override
public int filterOrder() {
return 1;
}
/**
* 过滤器是否生效
* @return
*/
@Override
public boolean shouldFilter() {
System.out.println("ZuulExceptionZuulException");
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
System.out.println("request.getRequestURI():"+request.getRequestURI());
//ACL
if ("/api_gateway/order/getOrderDetailById.do".equalsIgnoreCase(request.getRequestURI())){
return true;
}
return false;
}
/**
* 业务逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
System.out.println("ZuulExceptionZuulException");
//JWT
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//token对象
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;
}
}
5. 网关限流
限流是通过Guava限流工具RateLimiter来实现的。
@Component
public class RateLimitFilter extends ZuulFilter {
private static final RateLimiter rateLimiter= RateLimiter.create(2);
/**
* 过滤器类型,前置过滤器
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器顺序,越小越先执行
* @return
*/
@Override
public int filterOrder() {
return -1;
}
/**
* 过滤器是否生效
* @return
*/
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if ("/api_gateway/order/getOrderDetailById.do".equalsIgnoreCase(request.getRequestURI())){
System.out.println("request.getRequestURI():"+request.getRequestURI());
return true;
}
return false;
}
/**
* 业务逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletResponse response= requestContext.getResponse();
if (!rateLimiter.tryAcquire()) {
try {
requestContext.setSendZuulResponse(false);
String data = "请求频繁,暂时限流";
OutputStream outputStream = response.getOutputStream();
response.setHeader("content-type", "text/html;charset=UTF-8");
byte[] dataByteArr = data.getBytes("UTF-8");
outputStream.write(dataByteArr);
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
其中 private static final RateLimiter rateLimiter= RateLimiter.create(2); 是每秒产生两个令牌。rateLimiter.tryAcquire() 无法获取令牌则请求太过于频繁给出提示。
效果如下图:

版权声明:本文为qq_40263927原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。