简体   繁体   English

Apache Camel - FTP组件失败

[英]Apache Camel - Failing FTP Component

I made wrote a little piece of camel to consume a ftp server. 我写了一小块骆驼来使用ftp服务器。

But after it was running for some time, it throws an exception, keeps running but doesn't consume anything any more. 但是在它运行一段时间后,它会抛出异常,继续运行但不再消耗任何东西。 Also when I start it again and there are a larger number of file waiting to be consumed it will crash again. 此外,当我再次启动并且有大量文件等待消耗时,它将再次崩溃。 I already added an exception handler but it seems like is doesn't catch the exceptions. 我已经添加了一个异常处理程序,但它似乎没有捕获异常。

This is the exception I receive: 这是我收到的例外情况:

Caused by: [org.apache.camel.component.file.GenericFileOperationFailedException - File operation failed: 150 Opening ASCII mode data connection for 2386442.XML(3895 bytes).
Accept timed out. Code: 150]
org.apache.camel.component.file.GenericFileOperationFailedException: File operation failed: 150 Opening ASCII mode data connection for 2386442.XML(3895 bytes).
Accept timed out. Code: 150
    at org.apache.camel.component.file.remote.FtpOperations.retrieveFileToStreamInBody(FtpOperations.java:336)
    at org.apache.camel.component.file.remote.FtpOperations.retrieveFile(FtpOperations.java:297)
    at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:333)
    at org.apache.camel.component.file.remote.RemoteFileConsumer.processExchange(RemoteFileConsumer.java:94)
    at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:175)
    at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:136)
    at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:140)
    at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:92)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.net.SocketTimeoutException: Accept timed out
    at java.net.PlainSocketImpl.socketAccept(Native Method)
    at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
    at java.net.ServerSocket.implAccept(ServerSocket.java:462)
    at java.net.ServerSocket.accept(ServerSocket.java:430)
    at org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:560)
    at org.apache.commons.net.ftp.FTPClient.retrieveFile(FTPClient.java:1442)
    at org.apache.camel.component.file.remote.FtpOperations.retrieveFileToStreamInBody(FtpOperations.java:328)
    ... 16 more
Caused by: [org.apache.camel.component.file.GenericFileOperationFailedException - Cannot retrieve file: GenericFile[2386448.XML] from: Endpoint[ftp://1.1.1.1?delay=15000&delete=true&disconnect=true&exclude=((?i).*pdf$)&password=******&username=user]
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot retrieve file: GenericFile[2386448.XML] from:   Endpoint[ftp://1.1.1.1?delay=15000&delete=true&disconnect=true&exclude=((?i).*pdf$)&password=******&username=user]
   at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:338)
  at org.apache.camel.component.file.remote.RemoteFileConsumer.processExchange(RemoteFileConsumer.java:94)
    at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:175)
    at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:136)
    at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:140)
    at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:92)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

And this is the route I made using the Java DSL: 这是我使用Java DSL制作的路线:

    // XML Predicate
    // only allows names without spaces
    Predicate xmlPredicate = header(RssUtils.CAMEL_FILE_NAME).regex(
            "([\\S]+(\\.(?i)(xml))$)");
    // Images Predicate
    // only allows names without spaces
    Predicate imgPredicate = header(RssUtils.CAMEL_FILE_NAME).regex(
            "([\\S]+(\\.(?i)(jpg|png|gif))$)");

    onException(SchemaValidationException.class).to(
            "file://" + props.getProperty(RssUtils.ROOT_DIR)
                    + "/errors/SchemaValidationException");

    onException(GenericFileOperationFailedException.class).to(
            "file://" + props.getProperty(RssUtils.ROOT_DIR)
                    + "/errors/GenericFileExceptions");

    from(
            "ftp://"
                    + props.getProperty(RssUtils.FTP_URL)
                    + "?username="
                    + props.getProperty(RssUtils.FTP_USER)
                    + "&password="
                    + props.getProperty(RssUtils.FTP_PWD)
                    + "&disconnect=true&delete=true&exclude=((?i).*pdf$)&delay="
                    + props.getProperty(RssUtils.FTP_DELAY))
            .choice()
            .when(xmlPredicate)
            .to("jms:xmlQueue")
    .to("jms:archiveQueue")
            .when(imgPredicate)
            .to("file://" + props.getProperty(RssUtils.ROOT_DIR) + "/img")
            .otherwise()
            .to("file://" + props.getProperty(RssUtils.ROOT_DIR)
                    + "/errors/other");

    from("jms:xmlQueue").to("validator:FtpXmlValidator.xsd")
            .to("xslt://XmlToRssConverter.xsl")
            .process(rssFeedProcessor)
            .to("file://" + props.getProperty(RssUtils.ROOT_DIR) + "/rss/");

from("jms:archiveQueue")
    .to("file://" + props.getProperty(RssUtils.ROOT_DIR) + "/archive/");

Is there anything I can do to avoid this kind af behavior? 我有什么办法可以避免这种行为吗? It is really difficult to test so I'm hoping somebody spots a flaw in my code. 测试真的很难,所以我希望有人发现我的代码存在漏洞。 I have searching for quite some time now but I don't find anything solid. 我现在已经找了很长时间,但我找不到任何可靠的东西。 Maybe some way I could debug this issue? 也许某种方式我可以调试这个问题?

There maybe a few things that I found somebody could give his tought on: 可能有一些我发现有人可以给他的东西:

  • use handled(true) when using the onException 使用onException时使用processed(true)
  • can I set the max batch size of the consumer? 我可以设置消费者的最大批量大小吗? (can I use throttle for this ?) (我可以用油门吗?)
  • use explicit try catch finally because I'm using the Java DSL 最后使用显式try catch因为我正在使用Java DSL

Don't shoot me if I'm saying anything wrong here, I just learning Camel. 如果我在这里说错了,请不要开枪,我只是学习骆驼。 So if anybody has suggestions on the code above I would appreciate it! 所以,如果有人对上面的代码有任何建议,我将不胜感激!

Thanks a lot in advance! 非常感谢提前!

What you have here is an FTP issue, the fact that it is occurring in Apache Camel is largely irrelevant. 你在这里有一个FTP问题,它在Apache Camel中发生的事实在很大程度上是无关紧要的。

The telltale part of the bomb is: 炸弹的一部分是:

at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408) at java.net.ServerSocket.implAccept(ServerSocket.java:462) at java.net.ServerSocket.accept(ServerSocket.java:430) at org.apache.commons.net.ftp.FTPClient. java.net.ServerSocket.ccept.accept上的java.net.ServerSocket.implAccept(ServerSocket.java:462)java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)上的java.net.PlainSocketImpl.socketAccept(Native Method) (ServerSocket.java:430)org.apache.commons.net.ftp.FTPClient。 openDataConnection (FTPClient.java:560) openDataConnection (FTPClient.java:560)

The openDataConnection method of org.apache.commons.net.ftp.FTPClient is there to support active mode FTP - passive mode just uses the same port as for commands, so it doesn't need a separate port connection. org.apache.commons.net.ftp.FTPClient的openDataConnection方法支持主动模式FTP - 被动模式只使用与命令相同的端口,因此不需要单独的端口连接。

Try switching to passive mode (passiveMode = true with Apache Camel). 尝试切换到被动模式(使用Apache Camel时passiveMode = true)。

On the surface, without looking at WHY your route is failing, it sounds like what you're looking to do is handle and continue --ie, handle this exception and continue your route where you left off. 从表面上看,没有看你的路线为什么失败,听起来你正在寻找的是处理和继续 -我,处理这个例外并继续你离开的路线。 Per the documentation: 根据文件:

Available as of Camel 2.3 自Camel 2.3起可用
In Camel 2.3 we introduced a new option continued which allows you to both handle and continue routing in the original route as if the exception did not occur. 在骆驼2.3我们引入了一个新的选择continued它允许您同时处理 ,并继续作为,如果没有发生异常的原来的路线路由。

For instance to just ignore and continue if the IDontCareException was thrown we can do this: 例如,如果抛出IDontCareException,则忽略并继续,我们可以这样做:

onException(IDontCareException).continued(true);

What happens here is: 这里发生的是:

Camel will catch the exception and . 骆驼会抓住异常而且。 . . just ignore it and continue routing in the original route. 只是忽略它并继续在原始路由中路由。 However . 但是。 . . it will route that [onException] route first, before it will continue routing in the original route. 它将首先路由[onException]路由,然后继续在原始路由中路由。

Give this a try and it may solve your problem. 试一试,它可以解决您的问题。 As I implied, above, depending on what your root issue is, this may be more of a bandaid than a proper solution. 正如我所暗示的那样,根据你的根本问题,这可能更像是一个合适的解决方案。 The better approach might be to figure out why the FTP consumer is failing. 更好的方法可能是弄清楚FTP消费者失败的原因。 At a glance, it appears that it can't find the file named 2386448.XML . 一目了然,它似乎找不到名为2386448.XML的文件。

Once you determine the root cause, you can use a choice to behave differently at the right time as in: 确定根本原因后,您可以使用choice在正确的时间采取不同的行为,如下所示:

.choice()
    .when(isValidFtpResponse())
         .to(DIRECT_CONTINUE_FTP_ROUTE)
    .otherwise()
        .setBody(constant(null))
        .log(ERROR, "FTP failed: ${headers}")
.end()

Hopefully, that gives you a few ideas and helps you get passed this issue. 希望,这会给你一些想法,并帮助你通过这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM