Zuul作为微服务系统的网关组件,用于构建边界服务,致力于动态的路由、过滤、监控、弹性伸缩和安全。

其中Zuul、Ribbon以及Eureka的结合使用可以实现智能路由和负载均衡的功能,网关将所有的服务的API接口统一聚合,统一对外暴露,外界调用API的接口的时候,不需要知道微服务系统中各服务相关调用的复杂性,保护了内部微服务单元的API接口,网关可以做用户身份认证和权限认证,防止非法请求操作api接口,网关可以实现监控功能,实时日志输出,对请求进行记录,网关可以实现流量监控,在高流量监控的情况下,对服务降级,API接口从内部服务分离出来,方便做测试

Zuul通过Servlet来实现,通过自定义的ZuulServlet来对请求进行控制,核心的是一系列过滤器,可以在http请求的发起和相应返回期间执行一系列的过滤器,Zuul采取了动态处理、编译等这些过滤器,过滤器之间不能直接通信,而是通过RequestContext(静态类)对象来实现共享数据,每个请求都会创建一个RequetsContext对象,RequestContext中又ThreadLocal变量来记录每个Request所需要传递的数据,底层使用的是ThreadLocalMap来进行存储数据的。

Zuul大部分功能都是通过过滤器来实现的,Zuul中定义了四种标准过滤器类型,这些过滤器类型的对应于请求的的典型生命周期。

1,PRE:这种过滤器在请求到达路由之前被调用,我们可以利用这种过滤器实现身份验证,在集群中选择请求的微服务,记录调试信息等。

2,ROUTING:这种过滤器将请求通过路由到达微服务,这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfinx Ribbon请求到微服务。

3,POST:这种过滤器在请求被路由到微服务以后执行,这种过滤器可用来响应添加标准的HTTP Header、收集统计信息和指标,将响应从微服务发送给客户端等。

4,ERROE:在其他阶段发生错误时执行该过滤器。

内置的特殊过滤器:

  在zuul还提供了一类特殊的过滤器,分别为:StaticResponseFilter和SurgicaDebugFilter

   StaticResponseFilter:允许从Zuul本身生成响应,而不是将请求转发到资源

   SurgicaDebugFilter:允许将特定的请求路由到分隔的调试主机或者集群

自定义的过滤器:

   除了默认的过滤器,Zuul还允许我们创建自定义的过滤器类型,例如可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务

可是有没有注意到,如果我们不使用zuul,当我们在每个微服务增加了新的方法,都需要在网关层手动的增加相应的方法封装,而Spring cloud 中的zuul很好的解决了这一问题

 

spring boot 网关转发时间优化 springboot的网关_spring Cloue Zuul

zuul作为网关层,自身也是一个微服务,跟其他服务Service-1. Service-2 。。。一样,都需要注册在Eureka Server上,可以相互发现,zuul都干知道那些服务在线,同时通过配置路由规则,可以将请求转发到指定的后端的服务上,对于一些公用的预处理,(比如:权限认证。token合法校验,灰度验证时部分流量引导之类)可以放在所谓的过滤器(ZuulFilter -- 自定义的所谓的处理类)里处理,这样后端服务以后新增了,zuul层几乎可以保持不变。

Spring Cloud Zuul路由是微服务架构中不可缺少的一部分,提供动态路由,监控、弹性、安全等边缘服务,Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器

下面我们通过代码来了解Zuul是如何工作的:

   简单实用

  1,添加依赖

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.5.RELEASE</version>
</dependency>

  2,编写配置文件 application.yml

     

spring:
  application:
    name: gateway-service-zuul
server:
  port: 8888


#增加路由规则的配置
#通过zuul.routes.<route>.path和zuul.routes.<route>.url进行配置,<route>为路由的名字,可以任意指定,但是一组path和url的路由名要相同
zuul.routes.baidu.path: /baidu/**
zuul.routes.baidu.url: http://www.baidu.com

3,设置启动类

   

package com.example.springzuul;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class SpringzuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringzuulApplication.class, args);
    }
}

  启动类上添加@EnableZuulProxy的注解,用于启动网关路由,最简单的Zuul案例就配置完成了

简单的Zuul配置完成之后,可是上面咱们在总结的时候,发现四种标准的过滤器咱们还么有使用到,下面讲解一下四种过滤器的使用情况,在使用的时候需要自己定义一个类,继承ZuulFilter类,并且覆盖里面的方法。

 

package com.example.springzuul;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

import javax.servlet.http.HttpSession;

/**
 * 自定义过滤器,可以实现在不同的时候进行数据的拦截,分为四种状态
 * 当请求到达服务的时候,
 * 请求进入服务的时候,
 * 请求到达服务之后
 * 错误的时候
 */
public class MyFilter  extends ZuulFilter{
    /**
     * 表示返回的类型,就是确定要进行什么样的操作
     * @return
     */
    @Override
    public String filterType() {
        return null;
    }

    /**
     * 设置级别,数字越大级别越低
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 表示是否开启当前的拦截器 false 是不开启, true是开启
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return false;
    }
    /**
     * 表示执行的代码,比如说请求的时候,进行身份的认证等..
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
//        currentContext.set
        HttpSession session = currentContext.getRequest().getSession();
        return null;
    }
}

   自定义类之后,可以完成一些自己的配置

       filterType:表示返回的类型,也就是需要说明你当前的拦截器是在什么时候使用。

       filterOrder:设置优先级,因为会有很多的拦截器,并不是只有当前设置的一个拦截器,所以需要设置拦截的优先级,数字越大表示优先级越低

       shouldFilter:表示设置是否开启拦截器,true是开启拦截器,false是不开启拦截器

       run:就是拦截之后需要进行的操作,可以根据上面的filterType设置的类型,进行相应的操作,在使用的时候,使用到一个RequestContext的对象,该对象在上面也说过,因为拦截器之间是没有通讯的,所以使用RequestContet来进行数据的共享,当我在操作的时候,有一点像不明白,该对象里面的数据是在什么时候传递过来的呢,由于源码没有看懂也没有找打相似的代码,于是与网上寻找帮助,在看完资料之后,数据的传输是不是用过域来记性数据的保存和传输的呢,因为RequestContext对象可以获取到Request之后可以获取到Session对象,将数据保存到该对象中,可以完成在登录的时候获取用户的信息,也可以完成在拦截器中完成数据的共享,不知道想法是否正确,还希望大佬给出答案。

上面是是自定义的拦截器,但是如果需要时会用自己定义的拦截器,是否还需要将自己定义的拦截器放在spring的容器中呢,所以需要配置一个java配置。

  

package com.example.springzuul;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 用于将自己定义的拦截器,声明成bean注入到spring的容器中
 */
@Configuration
public class FilterConfig {
    @Bean
    public MyFilter myFilter() {
        MyFilter myFilter = new MyFilter();
        return myFilter;
    }
}