微服务网关-zuul

zuul之动态过滤器Filter类文件管理加载

2018-11-21  本文已影响157人  Mr_1214

目录

概述

zuul 支持过滤器动态修改动态加载功能,目前支持动态Filter由Groovy编写。动态管理Groovy编写的Filter类文件变更以及动态编译等功能。

实现原理

实现原理是监控存放Filter文件的目录,定期扫描这些目录,如果发现有新Filter源码文件或者Filter源码文件有改动,则对文件进行编译加载

Filter类文件动态管理

通过原理知道zuul通过定期扫描Filter文件存放的目录来校验是否有新的文件或有改动的文件,对这些文件进行加载,源码是通过FilterFileManager实现此功能的。FilterFileManager管理目录轮询的变化和新的Groovy过滤器。轮询间隔和目录在类的初始化中指定,并且轮询器将检查,更改和添加。


FilterFileManager 功能如下:

  • 开启一个线程,开始轮询(startPoller)
  • 每次轮询,处理目录内的所有*.groovy文件,即调用FilterLoader.getInstance().putFilter(file)
   //开启轮询线程
    void startPoller() {
       //创建轮询线程
        poller = new Thread("GroovyFilterFileManagerPoller") {
            public void run() {
                while (bRunning) {
                    try {
                       //定时休眠 sleep(pollingIntervalSeconds * 1000);
                       //扫描目录监听目录变化
                        manageFiles();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        poller.setDaemon(true);
        //开启轮询线程
        poller.start();
    }
  • startPoller 开启轮询线程定时调用manageFiles方法执行扫描目录,监听目录变化
  • startPoller方法在FilterFileManager初始化时(init)调用一次
    //目录扫描检测主入口方法
    void manageFiles() throws Exception, IllegalAccessException, InstantiationException {
       // 1. 通过getFiles方法获取到目录的所有Filter文件
        List<File> aFiles = getFiles();
        //2. 通过processGroovyFiles方法处理所有Filter文件
        processGroovyFiles(aFiles);
    }
    
    //加载所有动态Filter文件
    List<File> getFiles() {
        List<File> list = new ArrayList<File>();
        //遍历配置的动态Filter文件存放目录,加载目录文件
        for (String sDirectory : aDirectories) {
            if (sDirectory != null) {
                File directory = getDirectory(sDirectory);
                File[] aFiles = directory.listFiles(FILENAME_FILTER);
                if (aFiles != null) {
                    list.addAll(Arrays.asList(aFiles));
                }
            }
        }
        return list;
    }
    
    //处理所有动态Filter文件
    void processGroovyFiles(List<File> aFiles) throws Exception, InstantiationException, IllegalAccessException {
        //遍历动态Filter列表
        for (File file : aFiles) {
            //通过FilterLoader类来加载处理Filter
            FilterLoader.getInstance().putFilter(file);
        }
    }

manageFiles方法完成两件事

  1. 调用getFiles方法加载所有预制目录中的动态Filter文件
  2. 调用processGroovyFiles方法遍历filter列表通过FilterLoader类处理加载Filter

Filter类文件动态编译

zuul 动态加载filter文件,并通过编译器将文件编译成class
目前zuul通过定义DynamicCodeCompiler接口以及Groovy编译的实现类GroovyCompiler来完成Groovy编写的filter的动态编译

public interface DynamicCodeCompiler {
    /**
     * 通过源码字符串以及filter 名称编译class
     *
     */
    Class compile(String sCode, String sName) throws Exception;
    /**
     *
     * 通过源码文件编译class
     */
    Class compile(File file) throws Exception;
}

DynamicCodeCompiler 动态代码编译器接口
定义两个方法根据不同的参数返回编译好的class

public class GroovyCompiler implements DynamicCodeCompiler {

    private static final Logger LOG = LoggerFactory.getLogger(GroovyCompiler.class);

    /**
     * Compiles Groovy code and returns the Class of the compiles code.
     *
     * @param sCode
     * @param sName
     * @return
     */
    @Override
    public Class compile(String sCode, String sName) {
        GroovyClassLoader loader = getGroovyClassLoader();
        LOG.warn("Compiling filter: " + sName);
        Class groovyClass = loader.parseClass(sCode, sName);
        return groovyClass;
    }

    /**
     * 获取GroovyClassLoader
     * @return a new GroovyClassLoader
     */
    GroovyClassLoader getGroovyClassLoader() {
        return new GroovyClassLoader();
    }

    /**
     * 编译groovy class从文件中
     * Compiles groovy class from a file
     *
     * @param file
     * @return
     * @throws java.io.IOException
     */
    @Override
    public Class compile(File file) throws IOException {
        GroovyClassLoader loader = getGroovyClassLoader();
        Class groovyClass = loader.parseClass(file);
        return groovyClass;
    }
}

GroovyCompiler 为groovy编写的Filter的动态编译实现类。


zuul 默认支持groovy编写的Filter,这给在不停服的情况下动态变更业务规则提供了可靠的保障

上一篇下一篇

猜你喜欢

热点阅读