spring cloud ----Zuul网关
什么是网关?
网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能。它将"1对N"问题转换成了"1对1”问题。
通过服务路由的功能,可以在对外提供服务时,只暴露 网关中配置的调用地址,而调用方就不需要了解后端具体的微服务主机。
网关 = 路由+ 过滤

网关其实主要是 通过 路由和过滤两个功能实现的。
当用户访问网关,首先会利用网关的过滤功能通过用户请求中的一些参数来判断这个用户是否有权限访问这个服务
在确定用户的权限问题后,在路由时
根据请求的路径,在配置文件中的路由规则中找到对应的转发地址
然后转发到对应的服务
网关的快速入门
我们是使用spring-cloud 的组件zuul来实现网关其实很方便
首先在pom文件中加入zuul需要的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
然后再application.yaml文件中配置
主要是配置路由映射规则
eureka:
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/
#自定义路由映射
zuul:
routes:
#单实例配置
consumer-server: /consume/**
#path: /consume/**
#serviceId: consumer-server
product-server: /product/**
# path: /product/**
# serviceId: product-server
# 过滤器禁用配置
AccessFilter:
pre:
disable: true
然后再运行的主类中添加注解,一个简单的网关就搭建成功
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class, args);
}
}
需要注意的是 再Zuul中 有两个注解
@EnableZuulProxy 和 @EnableZuulServer 都可以表示这是一个网关的主类,都可以使用内部的一些内置过滤器
但是 @EnableZuulServer 是 @EnableZuulProxy 的子集,@EnableZuulProxy注解 可以实现 @EnableZuulServer
注解的所有功能,也可以实现一些@EnableZuulServer 注解没有的功能。
自定义过滤器的实现:
Zuul 通过在接收到请求时对该请求完成校验和过滤,而不是在转发后进行过滤。
zuul是通过在网关上定义过滤器来实现对请求的拦截和过滤
怎么定义过滤器呢? 很简单只需要继承ZuulFilter抽象类并且实现它定义的抽象函数就可以了。
@Component
public class AccessFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
@Override
//过滤器类型
public String filterType() {
return "pre";
}
@Override
//过滤器执行顺序
public int filterOrder() {
return -4;
}
@Override
//判断过滤器是否需要执行
public boolean shouldFilter() {
return true;
}
@Override
//过滤器具体逻辑
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info("send {} request to {}",request.getMethod(),request.getRequestURL().toString());
String accessToken = request.getParameter("accessToken");
if (accessToken == null){
log.warn("access token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
return null;
}
log.info("acces token ok");
return null;
}
}
这个自定义的过滤器的逻辑是,校验前端请求中是否带有token参数,如果没有就会报401参数。
我们再写完自定义过滤器后并不会立即生效,需要再过滤器上加@Component注解或者再主类中
定义一个过滤器的bean对象
@Bean
public AccessFilter errorFilter(){
return new AccessFilter();
}
启动主类后过滤器就自动生效了。
public String filterType() 过滤器类型
1.pre: 被路由之前
2.Routing 在路由时
3.Post 在路由后
4.Error 处理请求发生错误时
public int filterOrder() 通过定义int类型值来确定过滤器的执行顺序,最高优先级值为 -3 public boolean shouldFilter() 通过boolean类型来判断该过滤器是否需要执行,可以通过此方法来确定过滤器的执行范围 public Object run() 执行具体的过滤逻辑
过滤器的执行顺序:

当外部的HTTP请求到达API网关服务的时候,首先
会进入第一阶段 pre: 前置过滤器的主要作用是在路由前对请求进行加工 比如权限校验
在第一阶段完成之后
会进入第二阶段routing: 在路由请求转发时,请求会被routing 类型的过滤器处理
第三阶段 post 阶段: 在这个阶段我们不仅可以获取到请求的信息,还可以获取到服务实例的返回信息,所以在post阶段我们可以对返回的结果进行加工
Error阶段,error只有在我们进行上述三个阶段过滤时出现异常时才会触发,但是error过滤器最后还是会流向 post filter 向客户端返回结果
一些内置过滤器介绍:
pre:
1.ServletDetectFilter
执行顺序 -3
2.Servlet30WrapperFilter
执行顺序 -2
3.DebugFilter:
执行顺序为 1
routing:
1.RibbonRoutingFilter
执行顺序10
2.SimpleHostRoutingFilter
执行顺序100
3.SendForwardFilter
执行顺序 500
post:
1.SendErrorFilter
执行顺序0
2.SendResponseFilter
执行顺序1000

浙公网安备 33010602011771号