前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >zuul源码分析之Filter管理

zuul源码分析之Filter管理

作者头像
天涯泪小武
发布2021-12-09 19:36:26
4640
发布2021-12-09 19:36:26
举报

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

FilterFileManager

FilterFileManager用于管理Filter存放目录,并定期扫描目录的变化。

FilterFileManager的类图
FilterFileManager的类图

他的功能如下:

  • 开启一个线程,开始轮询
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();
    }
  • 每次轮询,处理目录内的所有*.groovy文件,即调用FilterLoader.getInstance().putFilter(file);
void processGroovyFiles(List<File> aFiles)  {
        for (File file : aFiles) {
            FilterLoader.getInstance().putFilter(file);
        }
    }

    void manageFiles() throws Exception, IllegalAccessException, InstantiationException {
        List<File> aFiles = getFiles();
        processGroovyFiles(aFiles);
    }

FilterLoader

编译、加载filter文件,并且检查源文件是否有变更,除此之外,它还按照filterType组织并维护List<ZuulFilter>

FilterLoader类图
FilterLoader类图

主要逻辑

 public boolean putFilter(File file) throws Exception {
    String sName = file.getAbsolutePath() + file.getName();
    // 如果文件在上次加载后发生了变化,重新编译加载
    if (filterClassLastModified.get(sName) != null && (file.lastModified() != filterClassLastModified.get(sName))) {
        filterRegistry.remove(sName);
    }
    ZuulFilter filter = filterRegistry.get(sName);
    if (filter == null) {
        // 编译、加载文件
        Class clazz = COMPILER.compile(file);
        if (!Modifier.isAbstract(clazz.getModifiers())) {
            filter = (ZuulFilter) FILTER_FACTORY.newInstance(clazz);
            // 为了下次Request使用filter,清空filter.filterType()类型的List<Filter>缓存,下次Request重新构建
            List<ZuulFilter> list = hashFiltersByType.get(filter.filterType());
            if (list != null) {
                hashFiltersByType.remove(filter.filterType()); //rebuild this list
            }
            // filterRegistry 管理所有的filter,
            filterRegistry.put(file.getAbsolutePath() + file.getName(), filter);
            // 记录filter文件更新时间。
            filterClassLastModified.put(sName, file.lastModified());
            return true;
            }
        }
        return false;
    }

这里主要的逻辑是把Groovy源码进行编译并加载进jvm里。

FilterRegistry

用于管理加载的filter,数据结构比较简单,使用 ConcurrentHashMap<String, ZuulFilter> filters,启动key为filter的name:file.getAbsolutePath() + file.getName();

DynamicCodeCompiler

是一个接口,定义两种加载编译源码的方法:

    /**
        方法最后返回的是Class,即源码编译成字节码后,还要加载。
        需要支持热加载,文件变化更新等。
     */
    Class compile(String sCode, String sName) throws Exception;

    Class compile(File file) throws Exception;

总结

zuul整体框架比较简单,如果要实现API-Gateway,或者client-api adapter code,可以参考下。框架背后的思想也许更值得我们参考。

参考

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-01-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • FilterFileManager
  • FilterLoader
  • FilterRegistry
  • DynamicCodeCompiler
  • 总结
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档