网关zuul——过滤器

网关——过滤器

从网关组件请求流程分析,可以看出网关的核心类为ZuulServlet,所有的请求都是走到这里来处理的!

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        try {
            this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
            RequestContext context = RequestContext.getCurrentContext();
            context.setZuulEngineRan();

            try {
                this.preRoute();
            } catch (ZuulException var12) {
                this.error(var12);
                this.postRoute();
                return;
            }

            try {
                this.route();
            } catch (ZuulException var13) {
                this.error(var13);
                this.postRoute();
                return;
            }

            try {
                this.postRoute();
            } catch (ZuulException var11) {
                this.error(var11);
            }
        } catch (Throwable var14) {
            this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName()));
        } finally {
            RequestContext.getCurrentContext().unset();
        }
    }

zuulServlet-service

从service方法中可以看出,preRoute()、route()、postRoute()、error()这4个方法为一套模板方法,定义了整个zuul组件的处理规则:

先执行preRoute()、再执行route(),然后是postRoute(),当任意环节出问题时,走到error()方法。

void postRoute() throws ZuulException {
        this.zuulRunner.postRoute();
    }

    void route() throws ZuulException {
        this.zuulRunner.route();
    }

    void preRoute() throws ZuulException {
        this.zuulRunner.preRoute();
    }
void error(ZuulException e) {
        RequestContext.getCurrentContext().setThrowable(e);
        this.zuulRunner.error();
    }

从上述代码可以看出,实际执行这套模板方法的时zuulRunner类

这次以preRoute()方法为例进行分析,最终preRoute()

在ZuulRunner中,调用的是FilterProcessor实例的preRoute();FilterProcessor类为单例模式,同时看其类名就可以知道该类是过滤器处理类;

public void preRoute() throws ZuulException {
        FilterProcessor.getInstance().preRoute();
    }

查看在FilterProcessor类中preRoute()的具体实现

public void preRoute() throws ZuulException {
        try {
            //这里是运行指定类型的过滤器
            //只有类型为pre的过滤器才会被调用
            this.runFilters("pre");
        } catch (ZuulException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new ZuulException(var3, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + var3.getClass().getName());
        }
    }

public Object runFilters(String sType) throws Throwable {
        if (RequestContext.getCurrentContext().debugRouting()) {
            Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
        }
        //根据类型获取过滤器
        boolean bResult = false;
        List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
        if (list != null) {
            for(int i = 0; i < list.size(); ++i) {
                //执行过滤器
                ZuulFilter zuulFilter = (ZuulFilter)list.get(i);
                Object result = this.processZuulFilter(zuulFilter);
                if (result != null && result instanceof Boolean) {
                    bResult |= ((Boolean)result).booleanValue();
                }
            }
        }

        return bResult;
    }

processZuulFilter(Zuulfilter filter)的具体内容

public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        boolean bDebug = ctx.debugRouting();
        String metricPrefix = "zuul.filter-";
        long execTime = 0L;
        String filterName = "";

        try {
            long ltime = System.currentTimeMillis();
            filterName = filter.getClass().getSimpleName();
            RequestContext copy = null;
            Object o = null;
            Throwable t = null;
            if (bDebug) {
                Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);
                copy = ctx.copy();
            }
         // 主要内容
            ZuulFilterResult result = filter.runFilter();
            ExecutionStatus s = result.getStatus();
            execTime = System.currentTimeMillis() - ltime;
            switch(s) {
            case FAILED:
                t = result.getException();
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
                break;
            case SUCCESS:
                o = result.getResult();
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);
                if (bDebug) {
                    Debug.addRoutingDebug("Filter {" + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + "ms");
                    Debug.compareContextState(filterName, copy);
                }
            }

            if (t != null) {
                throw t;
            } else {
                this.usageNotifier.notify(filter, s);
                return o;
            }
        } catch (Throwable var15) {
            if (bDebug) {
                Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + var15.getMessage());
            }

            this.usageNotifier.notify(filter, ExecutionStatus.FAILED);
            if (var15 instanceof ZuulException) {
                throw (ZuulException)var15;
            } else {
                ZuulException ex = new ZuulException(var15, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
                throw ex;
            }
        }

runFilter()中的内容

public ZuulFilterResult runFilter() {
        ZuulFilterResult zr = new ZuulFilterResult();
        if (!this.isFilterDisabled()) {
                //判断是否执行filter
            if (this.shouldFilter()) {
                Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());

                try {
                    //执行filter中的run方法
                    Object res = this.run();
                    zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
                } catch (Throwable var7) {
                    t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed");
                    zr = new ZuulFilterResult(ExecutionStatus.FAILED);
                    zr.setException(var7);
                } finally {
                    t.stopAndLog();
                }
            } else {
                zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
            }
        }

        return zr;
    }    

从上面代码可以看出,preRoute()方法为运行类型为”pre“的过滤器;从runFilter()方法可以看出,只有过滤器需要执行时才会执行过滤器中的run()方法;即过滤器中的run方法中包含了所有的过滤器要做的所有业务。

其他route(),postRoute(),error()中的代码也遵循这一规则,只有过滤器类型不同这一点

总结:

网关组件Zuul中的过滤器:

  在ZuulServlet中的service方法中定义过滤器的执行顺序,按preRoute()、route()、postRoute()顺序执行,error()时在出现异常时的处理规则。

  追踪preRoute()方法的执行可以得知,preRoute()经过了这3个类:ZuulServlet——>ZuulRunner——>FilterProcessor;

  最终preRoute的具体实现规则是在FilterProcessor中定义的

  在runFilters中定义了过滤器的类型:pre、route、post、error

  在ZuulFilter抽象类中的runFilter定义了过滤器是否被执行以及执行的方法体为run()方法

综上,要想添加一个能在网关中使用的自定义的过滤器;必须继承ZuulFilter抽象类,同时在filterType方法中定义好过滤器类型:pre、route、post、error;shouldFilter方法必须返回true才能执行,过滤器的具体实现逻辑要定义在run()方法中。

原文地址:https://www.cnblogs.com/AWSL/p/10624709.html

时间: 2024-08-30 14:01:18

网关zuul——过滤器的相关文章

Spring Cloud(七):服务网关zuul过滤器

上文介绍了Zuul的基本使用与路由功能,本文接着介绍Zuul的核心概念 -- Zuul过滤器(filter). Zuul的功能基本通过Zuul过滤器来实现(类比于Struts的拦截器,只是Struts拦截器用到责任链模式,Zuul则是通过FilterProcessor来控制执行),在不同的阶段,通过不同类型的过滤器来实现相应的功能. Zuul过滤器 过滤器类型 zuul的过滤器根据对HTTP请求的不同处理阶段包括如下四种类型 pre :在请求转发到后端目标服务之前执行,一般用于请求认证.确定路由

使用网关zuul过滤器登录鉴权

????1.新建一个filter包 ????????filte有很多种 pre.post. ????2.新建一个类LoginFilter,实现ZuulFilter,重写里面的四个方法(可以根据业务建很多个过滤器filter) ????????filterType/filterOrder/shouldFilter/run ????????1).filterType返回过滤器类型,前置类型为return PRE_TYPe,引入类FilterConstants,在类中可以看到各类filter定义 ??

Spring Cloud(十一):服务网关 Zuul(过滤器)【Finchley 版】

Spring Cloud(十一):服务网关 Zuul(过滤器)[Finchley 版] 发表于 2018-04-23 |  更新于 2018-05-07 | 在上篇文章中我们了解了 Spring Cloud Zuul 作为网关所具备的最基本功能:路由(Router).本文我们将关注 Spring Cloud Zuul 的另一核心功能:过滤器(Filter). Filter 的作用 我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的 API 网关入口被客户端访问到了.但

SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理

前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由网关的过滤器Filter以及异常处理的教程. SpringCloud Zuul Filter 介绍 过滤器概述 Zuul的中心是一系列过滤器,能够在HTTP请求和响应的路由过程中执行一系列操作. 以下是Zuul过滤器的主要特征: 类型:通常在应用过滤器时在路由流程中定义阶段(尽管它可以是任何自定义字

服务网关zuul之一:入门介绍

通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: 我们使用Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现:而服务间通过Ribbon或Feign实现服务的消费以及均衡负载:通过Spring Cloud Config实现了应用多环境的外部化配置以及版本管理.为了使得服务集群更为健壮,使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延. 在该架构中,我

11 微服务集群网关Zuul介绍

在实际环境中,我们的应用程序会有多个服务调用者,如何将其组织起来统一对外提供服务呢?我们可以使用Netflix的Zuul框架构建微服务集群网关来解决这个问题. 1. Zuul框架介绍 1.1 关于Zuul Spring Cloud提供了多个组件用于集群内部的通信,例如服务管理组件Eureka,负载均衡组件Ribbon,REST客户端组件Feign等等.如果集群提供可一个API或者Web服务,需要与外部进行通信,最好的方式就是添加一个网关,将集群的服务都隐藏到网关后面,这种做法对于外部客户端来说,

白话SpringCloud | 第十一章:路由网关(Zuul):利用swagger2聚合API文档

前言 通过之前的两篇文章,可以简单的搭建一个路由网关了.而我们知道,现在都奉行前后端分离开发,前后端开发的沟通成本就增加了,所以一般上我们都是通过swagger进行api文档生成的.现在由于使用了统一路由网关了,都希望各微服务的api文档统一的聚合在网关服务中,也方便前端用户查阅,不需要每个服务单独查看.当然了,也是可以做一个文档索引网页进行各微服务的api文档链接的.今天,我们就来讲下使用swagger实现自动化聚合微服务文档功能. 注:关于Swagger的介绍和使用,由于在之前的Spring

使用Zuul过滤器实现登录验证

Zuul网关同时管理各服务的api的访问权限,没登陆则不能调用某些接口: 使用Zuul过滤器实现: 步骤: 1.新建一个filter包 2.新建一个类,继承ZuulFilter类,在类顶部加注解@Component, 让Spring扫描 3.重写里面的4个方法,参考如下: package net.xdclass.apigataway.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.Reques

网关zuul——请求流转路径

网关Zuul——url请求流转路径 在springcloud的网关组件zuul中,网关本身能够接收url请求,那么请求在网关zuul组件中是怎么流转的呢? 从前面的文章可以看出,当外部请求传递到网关(Zuul)时,请求会传递到ZuulController类中 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndV