了解网关
服务网关(Zuul)是微服务架构中不可或缺的部分,通过网关统一向外界系统提供REST API的过程中,除了有服务路由、负载均衡(默认轮询)的功能之外,还有权限控制等功能。
网关的作用:
(1)统一入口:为全部微服务提供统一入口,将系统与外部隔离,保障了后台服务的安全
(2)鉴权校验:识别请求的权限,过滤不符合要求的请求
(3)动态路由:动态的将请求路由到集群的不同节点上
(4)减少客户与服务的耦合
项目搭建
在springcloud-eureka-application的基础上,添加一个consumer,和之前的consumer做个集群,然后再添加一个module,名称:springcloud-zuul,也注册到eureka中去,代码不再详细贴出来了,和之前的一样的。
添加zuul的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
主类添加注解开启zuul功能
@EnableZuulProxy // 开启Zuul的网关功能
编写路由规则
zuul:
routes:
user-client: # 这里是路由id,随意写
path: /user-info/** # 这里是映射路径
url: consumer # 映射到的服务名
接下来就可以通过zuul来进行访问了:http://localhost:8084/user-info/list
完整代码如下:
https://gitee.com/superbutton/spring-cloud-study/tree/develop/springcloud-zuul-application
接下来看看zuul filter(过滤器),用来实现对外部服务的控制。Filter有四个生命周期:“PRE”、“ROUTING”、“POST”、“ERROR”,如下图所示:
详细解释如下:
PRE:请求被路由之前调用,该过滤器可以实现身份认证,微服务可以记录调试信息等
ROUTING:该过滤器将请求路由到微服务,这种过滤器用于构建发送给微服务的请求
POST:该过滤器用来将响应信息发送给客户端
ERROR:在发生错误的时候执行该过滤器
Zuul除了默认的这几个过滤器之外,还允许我们创建自定义的过滤器。
正常的执行流程:请求到达首先由PRE过滤器处理。之后到达ROUTING过滤器,该过滤器会将请求路由到指定服务,由真正的服务提供者执行,执行完成后返回结果,而后会到达POST过滤器,之后返回响应
异常的执行流程:PRE和ROUTING过滤器出现异常之后,都会进入ERROR过滤器,ERROR过滤器处理完成之后,会将请求交给POST过滤器,之后返回客户端。如果ERROR出现异常,也会进入POST之后返回。
看一下底层一些关键的方法:ZuulFilter实现接口IZuulFilter,主要看看ZuulFilter中几个关键的方法:
顶层接口IZuulFilter
实现类ZuulFilter:
几个重要的方法:
boolean shouldFilter(); //判断该过滤器时候需要执行,true则执行,false不执行
abstract public String filterType(); //返回字符串,表示过滤器类型,有:pre、routing、post、error
abstract public int filterOrder(); //通过int值定义过滤器的执行优先级,数字越小优先级越高
Object run() throws ZuulException; //过滤器的具体执行逻辑
Zuul中默认实现的Filter
类型 | 顺序 | 过滤器 | 功能 |
---|---|---|---|
pre | -3 | ServletDetectionFilter | 标记处理Servlet的类型 |
pre | -2 | Servlet30WrapperFilter | 包装HttpServletRequest请求 |
pre | -1 | FormBodyWrapperFilter | 包装请求体 |
route | 1 | DebugFilter | 标记调试标志 |
route | 5 | PreDecorationFilter | 处理请求上下文供后续使用 |
route | 10 | RibbonRoutingFilter | serviceId请求转发 |
route | 100 | SimpleHostRoutingFilter | url请求转发 |
route | 500 | SendForwardFilter | forward请求转发 |
post | 0 | SendErrorFilter | 处理有错误的请求响应 |
post | 1000 | SendResponseFilter | 处理正常的请求响应 |
如何禁用指定的Filter:
在application.yml中进行指定:
zuul.<SimpleClassName>.<filterType>.disable=true
例如:
zuul:
SendResponseFilter:
post:
disable: true
接下来我们自己实现模拟一个验证请求是否合法的过滤器:
@Component
public class MyFilter extends ZuulFilter {
/**
* 过滤器类型,"pre"表示在请求被路由之前执行
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* filter的执行优先级,数字越小优先级越高
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 表示是否需要执行该filter,true表示执行,false表示不执行
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤器的具体逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("token");
if(StringUtils.isEmpty(token)) {
ctx.setSendZuulResponse(false); // 没有token,进行拦截
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
ctx.setResponseBody("token is empty");
}
return null; //放行
}
}
验证结果如下:
被拦截的请求:
成功的请求:
完整代码:
https://gitee.com/superbutton/spring-cloud-study/tree/develop/springcloud-zuul-filter