springcloud(第九篇)netflix zuul

来源:互联网 发布:手机网络捕鱼作弊器 编辑:程序博客网 时间:2024/06/05 06:43

netflix zuul

introduction

zuul用来提供动态路由、监控、授权、安全、调度等等的边缘服务(edge service)

ZuulFilter

ZuulFilterZuul中核心组件,通过继承该抽象类,覆写几个关键方法达到自定义调度请求的作用,这里filter不是java web中的filter,不要混淆.

new ZuulFilter() {                @Override                public int filterOrder() {                    return 0;                }                @Override                public String filterType() {                    return null;                }                @Override                public boolean shouldFilter() {                    return false;                }                @Override                public Object run() {                    return null;                }            }

filterOrder:filter执行顺序,通过数字指定
shouldFilter:filter是否需要执行 true执行 false 不执行
run : filter具体逻辑
filterType :filter类型,分为以下几种

pre:请求执行之前filter
route: 处理请求,进行路由
post: 请求处理完成后执行的filter
error:出现错误时执行的filter

quick start

直接给出一个简单demo,通过demo代码再具体解析

package com.lkl.springcloud.zuul;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.ContextLifecycleFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.filters.FilterRegistry;import com.netflix.zuul.http.ZuulServlet;import com.netflix.zuul.monitoring.MonitoringHelper;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.builder.SpringApplicationBuilder;import org.springframework.boot.context.embedded.FilterRegistrationBean;import org.springframework.boot.context.embedded.ServletRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.stereotype.Component;import java.io.IOException;/** * Created by liaokailin on 16/5/24. */@SpringBootApplicationpublic class Application {    public static void main(String[] args) {        new SpringApplicationBuilder(Application.class).web(true).run(args);    }    @Component    public static class MyCommandLineRunner implements CommandLineRunner {        @Override        public void run(String... args) throws Exception {            MonitoringHelper.initMocks();            initJavaFilters();        }        private void initJavaFilters() {            final FilterRegistry r = FilterRegistry.instance();            r.put("javaPreFilter", new ZuulFilter() {                @Override                public int filterOrder() {                    return 50000;                }                @Override                public String filterType() {                    return "pre";                }                @Override                public boolean shouldFilter() {                    return true;                }                @Override                public Object run() {                    System.out.println("running javaPreFilter");                    RequestContext.getCurrentContext().set("name", "liaokailin");                    return null;                }            });            r.put("javaRoutingFilter", new ZuulFilter() {                @Override                public int filterOrder() {                    return 50000;                }                @Override                public String filterType() {                    return "route";                }                @Override                public boolean shouldFilter() {                    return true;                }                @Override                public Object run() {                    System.out.println("running javaRoutingFilter");                    try {                        RequestContext.getCurrentContext().getResponse().sendRedirect("http://blog.csdn.net/liaokailin/");                    } catch (IOException e) {                        e.printStackTrace();                    }                    return null;                }            });            r.put("javaPostFilter", new ZuulFilter() {                @Override                public int filterOrder() {                    return 50000;                }                @Override                public String filterType() {                    return "post";                }                @Override                public boolean shouldFilter() {                    return true;                }                @Override                public Object run() {                    System.out.println("running javaPostFilter");                    System.out.println(RequestContext.getCurrentContext().get("name").toString());                    return null;                }            });        }    }    @Bean    public ServletRegistrationBean zuulServlet() {        ServletRegistrationBean servlet = new ServletRegistrationBean(new ZuulServlet());        servlet.addUrlMappings("/test");        return servlet;    }    @Bean    public FilterRegistrationBean contextLifecycleFilter() {        FilterRegistrationBean filter = new FilterRegistrationBean(new ContextLifecycleFilter());        filter.addUrlPatterns("/*");        return filter;    }}

servlet注册

通过ServletRegistrationBean构造ZuulServlet,该Servlet用以进行filter执行调度以及监控等等操作
访问 http://localhost:8080/test 进入该servlet

filter注册

通过FilterRegistrationBean进行filter注册,ContextLifecycleFilter的核心功能是为了清除RequestContext
请求上下文通过ThreadLocal存储,因此需要在请求完成后删除该对象。

CommandLineRunner

CommandLineRunner接口很简单,知道spring boot的知道其功能,在工程启动后会执行对应run方法:

MonitoringHelper.initMocks(); 启动监控,这个再后续文章中具体再说
initJavaFilters()方法中注册三种类型filter

RequestContext

RequestContextzuul有很重作用,在不同组件传递数据都是通过它来实现的

启动工程后访问 http://localhost:8080/test 可以看到后台答应消息,页面也会定位到我的博客首页。

zuul执行流程

借用官网的一张图片

Lifecycle

通过图片可以清晰看出执行过程,在微服务中后端各种引用,利用zuul进行合理调用还是很有必要的,例如 负载、限流、监控、安全等等功能。

zuul with groovy

为了动态修改filter,zuul利用groovy,它是基于jvm的语言,语法简单而且和java很类似,可以简单的理解为在java语法上进行拓展,但groovy是可以动态加载的,应用发布到线上后可以在不重启情况下对业务逻辑进行修改。

为了简单起见,下面创建一个groovy filter

import com.netflix.zuul.ZuulFilterimport com.netflix.zuul.context.RequestContextimport javax.servlet.http.HttpServletRequestclass PreRequest extends ZuulFilter{    @Override    String filterType() {        return "pre"    }    @Override    int filterOrder() {        return 1000    }    @Override    boolean shouldFilter() {        return true    }    @Override    Object run() {        HttpServletRequest req = RequestContext.currentContext.request as HttpServletRequest        Iterator headerIt = req.getHeaderNames().iterator()        while (headerIt.hasNext()) {            String name = (String) headerIt.next()            String value = req.getHeader(name)            println("header: " + name + ":" + value)        }        return null    }}

创建一个pre类型的filter,在run方法中获取HttpServletRequest 然后答应header信息

在代码中加入groovy编译器,间隔10秒扫描一次groovy文件,其代码如下:

 <dependency>            <groupId>org.codehaus.groovy</groupId>            <artifactId>groovy-all</artifactId>            <version>2.4.4</version>        </dependency>
 FilterLoader.getInstance().setCompiler(new GroovyCompiler());            try {                FilterFileManager.setFilenameFilter(new GroovyFileFilter());                FilterFileManager.init(10,"/Users/liaokailin/code/ieda/springcloud/myzuul/src/main/java/com/lkl/springcloud/zuul/filters/groovy/pre");            } catch (Exception e) {                throw new RuntimeException(e);            }

这里groovy文件通过绝对路径指定,如果是实际开发中,可以通过db去存储groovy文件。

启动应用后再访问该工程,可以发现header信息全部答应出来。

ok ~ it’s work ! more about is here
转载请注明
http://blog.csdn.net/liaokailin/article/details/51525908

欢迎关注,您的肯定是对我最大的支持

这里写图片描述

3 0