服务网关:API Gateway,API网关
Spring Cloud Zuul:封装于Netflix Zuul
API网关的其他方案:Nginx + Lua、Kong、Tyk
功能:让外部请求经过统一的网关,在网关上过滤请求,加工响应
过滤请求:限流、权限校验、路由
Zuul 项目构建
1、借助IDEA,初始化项目
New Project -> Spring Initializr -> 选择依赖Cloud Routing.Zuul
2、给主类增加注解 @EnableZuulProxy
3、application.properties 更名为 application.yml
server.port: 8080
zuul:
routes.myService:
path: /myService/**
serviceId: service_1 # 路径与服务的映射,前提是 Zuul也得是 Eureka Client
sensitiveHeaders: # 把敏感头设为空,即可让Zuul把所有请求头都转发给服务
ignored-patterns: # 让一些路径不允许通过Zuul访问(但不影响直接访问原服务)
- /inner/**
- /**/inner
4、运行主类 main方法,访问 localhost:8080/myService/path 或 localhost:8080/service_1/path,即可访问到service_1的接口
前置过滤器
请求数据流:前置过滤器 -> 路由过滤器 -> 服务 -> 错误过滤器(可选) -> 后置过滤器
@Component
public class TokenFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE; // 前置过滤器
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1; // 过滤器顺序,让它在PRE_DECORATION_FILTER过滤器之前
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest hsr = rc.getRequest();
if(false){
rc.setSendZuulResponse(false); // 校验不通过,直接返回
rc.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}
后置过滤器
@Component
public class TokenFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1; // 过滤器顺序,让它在SEND_RESPONSE_FILTER过滤器之前
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext rc = RequestContext.getCurrentContext();
HttpServletResponse hsr = rc.getResponse();
hsr.setHeader("X-Hogen", "dd");
return null;
}
}
限流
令牌桶限流:每秒往令牌桶里放固定数目的令牌,应用从桶里取到令牌才处理请求,否则丢弃请求
@Component
public class TokenFilter extends ZuulFilter {
// RateLimiter 来源于 Google Guava组件
private static final RateLimiter RATE_LIMITER = RateLimiter.create(100); // 每秒往桶里放100个令牌
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SERVLET_DETECTION_FILTER_ORDER - 1; // 设置成比最高优先级还高
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest hsr = rc.getRequest();
if(!RATE_LIMITER.tryAcquire()){ // 尝试取令牌
rc.setSendZuulResponse(false);
}
return null;
}
}
Zuul 高可用
Zuul 同时得是 Eureka Client,部署多台即可
网友评论