一 典型应用场景
前置(Pre)
。限流
。鉴权
。参数校验/路由转发调整
后置(Post)
统计
日志
Zuul的高可用
。多个Zuul节点注册到Eureka Server上
。Nginx转发到多个Zuul “混搭”
二 Pre和Post过滤器
Zuul:放到权限校验,对请求做统一校验, 都有一个token ,内容不能为空
api-gateway->src->com.imooc.apigetway->建包filter0->TokenFilter.java
//package com.imooc.apigateway.filter;
//
//import com.netflix.zuul.ZuulFilter;
//import com.netflix.zuul.context.RequestContext;
//import org.springframework.http.HttpStatus;
//import org.springframework.stereotype.Component;
//import org.springframework.util.StringUtils;
//
//import javax.servlet.http.HttpServletRequest;
//
//import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
//import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
//
///**
// * Created by 廖师兄
// * 2018-02-15 15:34
// */
//@Component
//public class TokenFilter extends ZuulFilter {
// @Override
// public String filterType() {
// return PRE_TYPE;
// }
//
// @Override
// public int filterOrder() {
// return PRE_DECORATION_FILTER_ORDER - 1;
// }
//
// @Override
// public boolean shouldFilter() {
// return true;
// }
//
// @Override
// public Object run() {
// RequestContext requestContext = RequestContext.getCurrentContext();
// HttpServletRequest request = requestContext.getRequest();
//
// //这里从url参数里获取, 也可以从cookie, header里获取
// String token = request.getParameter("token");
// if (StringUtils.isEmpty(token)) {
// requestContext.setSendZuulResponse(false);
// requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
// }
// return null;
// }
//}
请求网址localhost:9000/myProduct/product/list?token=13121 可以
请求网址localhost:9000/myProduct/product/list 不可以,权限不通过
其它服务也会走这个逻辑
三 之后会对返回的数据进行处理加工
package com.imooc.apigateway.filter;
@Component
public class addResponseHeaderFilter extends ZuulFilter{
@Override
public String filterType() {
return POST_TYPE;
}
@Override
public int filterOrder() {
return SEND_RESPONSE_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletResponse response = requestContext.getResponse();
response.setHeader("X-Foo", UUID.randomUUID().toString());
return null;
}
}
四 限流
由于Zuul充当了API网关的角色,每个请求都会经过他,很适合做限流服务,放到前置过滤器中
时机:请求被转发之前调用,限流放最前面,早于鉴权
令牌桶限流
package com.imooc.apigateway.filter;
import com.google.common.util.concurrent.RateLimiter;
import com.imooc.apigateway.exception.RateLimitException;
import com.netflix.zuul.ZuulFilter;
import org.springframework.stereotype.Component;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVLET_DETECTION_FILTER_ORDER;
@Component
public class RateLimitFilter extends ZuulFilter{
//每秒钟放100个令牌
private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return SERVLET_DETECTION_FILTER_ORDER - 1; //-3-1=-4优先级最高,数值越低越高优先级
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {//具体实现
if (!RATE_LIMITER.tryAcquire()) {
throw new RateLimitException();
}
return null;
}
}
国外小伙写了一个限流
https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit
跨域问题 (1)在被调用的类或方法上增加@CreossOrigin注解 (2)在Zuul里增加CorsFilter过滤器 增加到网关上 @GetMapping("/list") @CrossOrigin(allowCredentials="true") public ResultVo<ProductVO> list(){ } api-gateway->src->main->com.immoc.apigateway->config->CorsConfig 应该是免费学习 跨域https://www.imooc.com/learn/947