如何使用 Apache Camel 来监控文件更改?

Posted

技术标签:

【中文标题】如何使用 Apache Camel 来监控文件更改?【英文标题】:How can Apache Camel be used to monitor file changes? 【发布时间】:2013-12-03 21:22:01 【问题描述】:

我想监视给定目录中的所有文件的更改,即更新的时间戳。对于使用文件组件的 Camel 来说,这个用例似乎很自然,但我似乎找不到配置这种行为的方法。

类似的uri:

file:/some/directory

将使用提供的目录中的文件,但会删除它们。

类似的uri:

file:/some/directory?noop=true

在添加文件或启动路由时使用每个文件一次。

令人惊讶的是,没有类似的选项

consumeOnChange=true

是否有一种直接的方法来监控文件更改并且在使用后不删除文件?

【问题讨论】:

【参考方案1】:

我认为 Camel 不支持该特定功能,但通过现有选项,您可以提出类似的目录监控解决方案。

您需要做的是设置一个小的延迟值来检查目录并维护已读取文件的存储库。根据您配置存储库的方式(按大小、按文件名、按它们的混合...),此解决方案将能够为您提供有关新闻文件和修改文件的信息。需要注意的是,它会经常使用目录中的文件。

也许您可以使用与 Camel 不同的其他解决方案,例如 Apache Commons VFS2(我写了一篇关于如何在这种情况下使用它的说明:WatchService locks some files?

【讨论】:

说得好。这是务实的答案 :-) 就我而言(Camel FTP 客户端在文件可用后立即发送文件)我添加了一个 JMS 队列,文件生产者在其中发布一条消息,唤醒 FTP 客户端。【参考方案2】:

您可以通过设置 idempotentKey 来告诉 Camel 如何认为文件已更改。例如,如果文件大小发生变化,或者其时间戳发生变化等。

在 Camel 文件文档中查看更多详细信息:https://camel.apache.org/components/latest/file-component.html

参见避免多次读取同一个文件(幂等消费者)部分。并阅读有关 idempotent 和 idempotentKey 的信息。

类似的东西

from("file:/somedir?noop=true&idempotentKey=$file:name-$file:size")

或者

from("file:/somedir?noop=true&idempotentKey=$file:name-$file:modified")

您可以在此处阅读有关可以使用的各种 $file:xxx 令牌:http://camel.apache.org/file-language.html

【讨论】:

感谢您抽出宝贵时间回复,克劳斯。我非常感谢您在 Camel 上所做的工作。我在下一次会议之前尝试了 20 分钟,但我似乎无法让它发挥作用。我尝试了大小并修改无济于事。我现在明白 noop 默认情况下变为幂等,这是有道理的。当我有更多时间时,我会继续查看文件令牌,但我希望它会在我添加 $file:name-$file:modified 时开始拾取修改过的文件。还有更多吗?再次感谢! 啊,我记得我最近用 idempotentKey 修复了一个错误,虽然是针对 FTP 报告的。它的CAMEL-6936。因此将在即将发布的版本中修复。对不起那个错误。 不用担心 - 所以像您发布的第二个这样的网址应该可以在未来的版本中使用? SNAPSHOT 工件是否在任何地方发布? 嗯 - 我尝试了最新的 2.12.2-SNAPSHOT 和 2.13-SNAPSHOT。没有运气。需要明确的是,我的网址现在看起来像“ ?noop=true&idempotentKey=$file:name-$file:modified 也许它还没有在构建中? 啊,感谢 CAMEL-6936 的第一个修复并没有涵盖所有内容。我已经再次解决了这个问题。因此,任何未来的 SNAPSHOT 更新都应包含此修复程序。【参考方案3】:

我遇到了同样的问题,即也想复制更新的文件(连同新文件)。下面是我的配置,

public static void main(String[] a) throws Exception 

    CamelContext cc = new DefaultCamelContext();

    cc.addRoutes(createRouteBuilder());

    cc.start();

    Thread.sleep(10 * 60 * 1000);

    cc.stop();



protected static RouteBuilder createRouteBuilder() 
    return new RouteBuilder() 
        public void configure() 
            from("file://D:/Production"
                    + "?idempotent=true"
                    + "&idempotentKey=$file:name-$file:size"
                    + "&include=.*.log"
                    + "&noop=true"
                    + "&readLock=changed")

            .to("file://D:/LogRepository");
        
    ;

我的测试步骤:

    运行程序,它会将几个 .log 文件从 D:/Production 复制到 D:/LogRepository,然后继续轮询 D:/Production 目录 我从 D:/Production 打开了一个已经复制的日志,比如 A.log(因为 noop=true 没有移动任何内容)并使用一些编辑器工具对其进行了编辑。这使文件大小翻倍并保存。

此时我认为 Camel 应该再次复制该特定文件,因为它的大小已修改,并且在我的路由定义中我使用了 "idempotent=true&idempotentKey=$file:name-$file:size &readLock=更改”。但是骆驼忽略了该文件。 当我使用 TRACE 进行记录时,它显示“正在跳过文件...”,但是当我编辑并保存文件时,我在 D:/Production 目录中没有找到任何锁定文件。

我还检查了如果我从外部替换 D:/Production 目录中的 A.log(名称相同但大小更大),camel 仍然会忽略该文件。

但我发现,如果我删除 noop=true 选项,一切都会按预期工作

我错过了什么吗?

【讨论】:

您是否尝试过将此作为单独的问题发布? 当从监视文件夹中删除而不是修改文件时,是否有任何标志来触发路由?【参考方案4】:

noop 设置为 true 也会导致 Camel 设置 idempotent=true,尽管 idempotent 默认为 false

监控文件的最简单解决方案是:

.from("file:path?noop=true&idempotent=false&delay=60s")

这将每隔一分钟监控给定目录中所有文件的更改。

这可以在 Camel 文档中找到:http://camel.apache.org/file2.html。

【讨论】:

【参考方案5】:

如果你想监控camel中的文件变化,使用file-watch组件。

示例 -> 递归查看所有事件(文件创建、文件删除、文件修改):

from("file-watch://some-directory")
.log("File event: $header.CamelFileEventType occurred on file $header.CamelFileName at $header.CamelFileLastModified");

您可以在此处查看完整的文档: Camel file-watch component

【讨论】:

以上是关于如何使用 Apache Camel 来监控文件更改?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Apache Camel 中更改 SOAP Web 服务端点 URL 和 WSDL URL

如何调查 Apache Camel Route 上的数据?

如何在apache camel中附加速度文件内容

在 Apache Camel 应用程序中,单元测试如何注入模拟端点来代替真实端点?

将更改日志转换为 Apache Camel 中的实际状态

如何使用 Apache Camel 从 Java 类访问 JMS 队列?