spring boot 集成Zuul
git地址
https://github.com/a18792721831/studySpringCloud.git
1. 为什么需要Zuul
Zuul 作为路由网关组件,在微服务架构中有着非常重要的作用,主要体现在以下6个方面。
- Zuul、Ribbon 以及Eureka 相结合,可以实现智能路由和负载均衡的功能,Zuul能够将请求流量按某种策略分发到集群状态的多个服务实例。
- 网关将所有服务的API接口统一聚合,并统一对外暴露。外界系统调用API接口时,都是由网关对外暴露的 API 接口,外界系统不需要知道微服务系统中各服务相互调用的复杂性。微服务系统也保护了其内部微服务单元的 API 接口,防止其被外界直接调用,导致服务的敏感信息对外暴露。
- 网关服务可以做用户身份认证和权限认证,防止非法请求操作API接口,对服务器起到保护作用。
- 网关可以实现监控功能,实时日志输出,对请求进行记录。
- 网关可以用来实现流量监控,在高流量的情况下,对服务进行降级。
- API接口从内部服务分离出来,方便做测试。
2. Zuul的工作原理
Zuul 是通过 Servlet 来实现的,Zuul 通过自定义的 ZuulServlet(类似于 Spring MVC 的DispatchServlet)米对请求进行控制。Zaul的核心是一系列过遗器,可以在Http请求的发起和响应返回期间执行一系列的过滤器。Zuu包括以下4种过滤器。
- PRE 过滤器:它是在请求路由到具体的服务之前执行的,这种类型的过滤器可以做安全验证,例如身份验证、参数验证等。
- ROUTING过滤器:它用于将请求路由到具体的微服务实例。在默认情况下,它使用Http Client 进行网络请求。
- POST过滤器:它是在请求已被路由到微服务后执行的。一般情况下,用作收集统计信息、指标,以及将响应传输到客户端。
- ERROR过滤器:它是在其他过滤器发生错误时执行的。
Zuul采取了动态读取、编译和运行这些过滤器。过滤器之间不能直接相互通信,而是通过RequestContext 对象来共享数据,每个请求都会创建一个RequestContext对象。Zuul过滤器具有以下关键特性。 - Type(类型):Zuul过滤器的类型,这个类型决定了过滤器在请求的哪个阶段起作用,例如Pre、Post阶段等。
- Execution Order(执行顺序):规定了过滤器的执行顺序,Order的值越小,越先执行。
- Criteria(标准):Filter执行所需的条件。
- Action(行动):如果符合执行条件,则执行Action(即逻辑代码)。
当一个客户端 Request请求进入Zuul网关服务时,网关先进入“prefilter”,进行一系列的验证、操作或者判断。然后交给“routing filter”进行路由转发,转发到具体的服务实例进行逻辑处理、返回数据。当具体的服务处理完后,最后由“post filter”进行处理,该类型的处理器处理完之后,将Response信息返回给客户端。
ZuulServlet 是 Zuul 的核心 Servlet。ZuulServlet 的作用是初始化 ZuulFiher,并编排这些ZmulFiher的执行顺序。该类中有一个service(方法,执行了过滤器执行的逻辑。
首先执行preRoute()方法,这个方法执行的是PRE类型的过滤器的逻辑。如果执行这个方法时出错了,那么会执行 error(e)和 postRoute()。然后执行route()方法,该方法是执行ROUTING类型过滤器的逻辑。最后执行 postRoute(),该方法执行了 POST类型过滤器的逻辑。
3. spring boot集成
3.1 创建
3.2 配置
3.3 注解
3.4 启动
启动eureka-server、eureka-client多个、ribbon、feign、zuul。
访问直连
再次请求
说明zuul路由转发也做了负载均衡。
访问ribbon
访问feign
3.5 指定url转发
增加配置
验证
多次访问依然是同一个
3.6 自定义转发列表
增加配置
启动验证
多次访问依然是指定的列表。
4. Zuul配置API接口版本号
配置
启动验证
不加版本号是无法访问的。
5. 在Zuul上配置熔断器
在Zuul中实现熔断功能需要实现FallbackProvider的接口。该接口主要有两个方法:一个是匹配的url的getRounte()方法,用于指定熔断功能应用于哪些路由的服务;另一个是fallbackResponse()方法,是当目标方法不可用时的处理方法。
启动验证
这里有一个坑,配置了url的路由无法进行熔断,会直接异常,截止文章发表,未找到直接证据,但是根据步骤可以复现。
具体见
https://blog.csdn.net/a18792721831/article/details/104655867
https://github.com/Netflix/zuul/issues/737
首先两个服务都能访问
接着关闭eureka-client、ribbon、feign。
然后访问
6. 在Zuul中使用过滤器
如何实现自定义过滤,以及在自定义过滤中加入业务逻辑。
实现过滤器很简单,只需要继承ZuulFilter,并实现ZuulFilter中的抽象方法,包括filterType()和filterOrder(),以及IZuulFilter的 shouldFilter()和Object run()的两个方法。其中,filterType()即过滤器的类型,它有4种类型,分别是“pre”“post”“routing”和“error”。filterOrder是过滤顺序,它为一个Int类型的值,值越小,越早执行该过滤器。
shouldFilter()表示该过滤器是否过滤逻辑,如果为true,则执行run()方法;如果为false,则不执行run()方法。run()方法写具体的过滤的逻辑。
首先创建自定义的过滤器
PRE过滤器
post
ps:Routing和error未验证触发(error直接转发到/error了,routing直接进入eureka-client中了)
注意:使用getOutputStream,如果使用getWriter会有异常getWriter() has already been called for this response
启动验证
日志