Zuul 属于Netflix旗下一款产品,而Spring很好对其做了整合
Zuul是一个边缘服务,提供动态路由、监控、弹性、安全性等等。相关的用法、信息、操作方式等 请查看WIKI https://github.com/Netflix/zuul/wiki
Spring Cloud Netflix的文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.1.0.M3/single/spring-cloud-netflix.html
一、Getting Start最简单的配置
java文件
@EnableZuulProxy
public class ZuulConfig {
}
yml文件
zuul:
routes:
pltf-client:
path: /pltf/client/**
service-id: pltf-client
二、对于yml的改进
1、最传统的路由
zuul.routes.client.path=/client/**
zuul.routes.client.url=http://localhost:1166/
2、面向服务的路由
如果每次都要写一串url的话感觉很繁琐,所以用service-id来代替,这里的service-id就是注册服务当中的 service-id
zuul.routes.client.path=/client/**
zuul.routes.client.service-id=client
3、通配符路由
有这样一个场景,由于业务的扩展,版本的升级,服务存在不同的版本。比如我们有这样的命名:client-v1、client-v2,默认情况下,Zuul自动为服务创建的路由表达式会采用服务名做前缀,针对client就会产生/client-v1,/client-v2两个路径来做映射,但这样生成的表达式规则较为单一,不利于路径规则的管理。通常,对于上面这种情况,我们希望是生成的路径为/v1/client,/v2/client。我们可以通过自定义路由规则来实现,具体代码如下:
@Bean
public PatternServiceRouteMapper serviceRouteMapper(){
return new PatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}");
}
4、Zuul的过滤器
四种过滤器:
- PRE:该类型的filters在Request routing到源web-service之前执行。可以进行一些权限认证,日志记录,或者额外给Request增加一些属性供后续的filter使用
- ROUTING: 该类型的filters用于把Request routing到源web-service,源web-service是实现业务逻辑的服务。这里使用HttpClient请求web-service
- POST: 该类型的filters在ROUTING返回Response后执行。用来实现对Response结果进行修改,收集统计数据以及把Response传输会客户端;
- ERROR: 上面三个过程中任何一个出现错误都交由ERROR类型的filters进行处理。
Zuul过滤器具有以下关键特性:
- Type(类型):Zuul过滤器的类型,这个类型决定过滤器在哪个阶段执行,例如:pre,post等阶段;
- Execution Order(执行顺序):规定了过滤器的执行顺序,Order的值越小,越先执行;
- Criteria(标准):Filters执行所需条件
- Action(行动):如果符合执行条件,则执行Action(具体逻辑代码)
@Sl4j
public class MyPreFilter extends ZuulFilter {
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info("{} AccessUserNameFilter request to {}", request.getMethod(), request.getRequestURL().toString());
// 获取请求的参数
String username = request.getParameter("username");
// 如果请求的参数不为空,且值为demo时,则通过
if(null != username && username.equals("demo")) {
// 对该请求进行路由
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
// 设值,让下一个Filter看到上一个Filter的状态
ctx.set("isSuccess", true);
return null;
}else{
// 过滤该请求,不对其进行路由
ctx.setSendZuulResponse(false);
// 返回错误码
ctx.setResponseStatusCode(401);
// 返回错误内容
ctx.setResponseBody("{\"result\":\"username is not correct!\"}");
ctx.set("isSuccess", false);
return null;
}
}
@Override
public boolean shouldFilter() {
// 是否执行该过滤器,此处为true,说明需要过滤
return true;
}
/**
* 指定该Filter执行的顺序(Filter从小到大执行)
* DEBUG_FILTER_ORDER = 1;
* FORM_BODY_WRAPPER_FILTER_ORDER = -1;
* PRE_DECORATION_FILTER_ORDER = 5;
* RIBBON_ROUTING_FILTER_ORDER = 10;
* SEND_ERROR_FILTER_ORDER = 0;
* SEND_FORWARD_FILTER_ORDER = 500;
* SEND_RESPONSE_FILTER_ORDER = 1000;
* SIMPLE_HOST_ROUTING_FILTER_ORDER = 100;
* SERVLET_30_WRAPPER_FILTER_ORDER = -2;
* SERVLET_DETECTION_FILTER_ORDER = -3;
*/
@Override
public int filterOrder() {
// 优先级为0,数字越大,优先级越低
return org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public String filterType() {
// 前置过滤器
return org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
}
}
网友评论