参考文章
史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)
Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能
zuul有以下功能:
Authentication
Insights
Stress Testing
Canary Testing
Dynamic Routing
Service Migration
Load Shedding
Security
Static Response handling
Active/Active traffic management
- 身份认证和安全(Authentication): 识别每一个资源的验证要求,并拒绝那些不符的请求
- 审查与监控:
- 动态路由:动态将请求路由到不同后端集群
- 压力测试:逐渐增加指向集群的流量,以了解性能
- 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
- 静态响应处理:边缘位置进行响应,避免转发到内部集群
- 多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB(ElasticLoad Balancing)使用多样化
身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求 # 审查与监控: # 动态路由:动态将请求路由到不同后端集群 # 压力测试:逐渐增加指向集群的流量,以了解性能 # 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求 # 静态响应处理:边缘位置进行响应,避免转发到内部集群 # 多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB(ElasticLoad Balancing)使用多样化
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
启动类加上注解@EnableZuulProxy,开启zuul的功能
zuul配置
zuul:
routes:
api-a:
path: /api-a/**
serviceId: service-ribbon
api-b:
path: /api-b/**
serviceId: service-feign
以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务;
如“/ myusers / ”只匹配一个级别,但“/ myusers / *”分层次匹配。
这些简单的url路由不会作为HystrixCommand执行,也不能使用功能区负载平衡多个URL。 为此,请指定服务路由并为serviceId配置功能区客户端目前需要在功能区中禁用Eureka支持,
为了同时指定path 和 url,但是不破坏Zuul的Hystrix和Ribbon特性:
zuul:
routes:
users:
path: /myusers/**
serviceId: users
ribbon:
eureka:
enabled: false
users:
ribbon:
listOfServers: example.com,google.com
zuul的服务过滤
@Component
public class MyFilter extends ZuulFilter{
private static Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
Object accessToken = request.getParameter("token");
if(accessToken == null) {
log.warn("token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("token is empty");
}catch (Exception e){}
return null;
}
log.info("ok");
return null;
}
}
在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
pre:路由之前
routing:路由之时
post: 路由之后
error:发送错误调用
方法:
filterType:返回一个字符串代表过滤器的类型
filterOrder:过滤的顺序
shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
如果在Zuul过滤器生命周期的任何部分期间抛出异常,则会执行错误过滤器。 SendErrorFilter仅在RequestContext.getThrowable()不为null时运行。 然后它在请求中设置特定的javax.servlet.error。*属性,并将请求转发到Spring Boot错误页面。