无法在IDE中删除Kafka Stream Application

时间:2018-05-30 10:36:02

标签: java windows apache-kafka apache-kafka-streams

我正在开发一个简单的Kafka Stream应用程序,它从主题中提取消息并在转换后将其放入另一个主题。我正在使用Intelij进行开发。

当我调试/运行此应用程序时,如果我的IDE和Kafka服务器位于 SAME计算机

,它将完美运行
  

(即BOOTSTRAP_SERVERS_CONFIG = localhost:9092和   SCHEMA_REGISTRY_URL_CONFIG = localhost:8081)

然而,当我尝试使用另一台机器进行开发时

  

(即BOOTSTRAP_SERVERS_CONFIG = XXX.XXX.XXX:9092和   SCHEMA_REGISTRY_URL_CONFIG = XXX.XXX.XXX:8081其中XXX.XXX.XXX是   我的卡夫卡的IP地址),

调试过程第一次运行没有问题。但是,当我在重置偏移后第二次运行时,我收到以下错误:

ERROR stream-thread [main] Failed to delete the state directory. (org.apache.kafka.streams.processor.internals.StateDirectory:297) 
java.nio.file.DirectoryNotEmptyException: \tmp\kafka-streams\my_application_id\0_0
Exception in thread "main" org.apache.kafka.streams.errors.StreamsException: java.nio.file.DirectoryNotEmptyException:

如果我将my_application_id更改为my_application_id2并运行它,它会在第一次再次运行,但如果我再次运行它会再次收到错误。

我的申请中的最后一句话中有以下代码:

Runtime.getRuntime().addShutdownHook(new Thread(streams::close));

有任何建议如何解决这个问题?

更新:

我已经查看了在我的开发机器(Windows平台)中创建的状态目录,如果我在第二次运行之前手动删除了这些目录,则没有发现错误。我试图以管理员身份运行我的IDE,因为我认为这可能是关于该文件夹的权限。但是,这没有任何帮助。

完整筹码以供参考:

  

INFO Kafka版本:1.1.0(org.apache.kafka.common.utils.AppInfoParser:109)   INFO Kafka commitId:fdcf75ea326b8e07(org.apache.kafka.common.utils.AppInfoParser:110)   INFO stream-thread [main]删除任务0_0的状态目录0_0作为用户调用清理。 (org.apache.kafka.streams.processor.internals.StateDirectory:281)   断开与目标VM的连接,地址:' 127.0.0.1:16552',transport:' socket'   线程" main"中的例外情况org.apache.kafka.streams.errors.StreamsException:java.nio.file.DirectoryNotEmptyException:C:\ workspace \ bennychan \ kafka-streams \ my_application_001 \ 0_0       在org.apache.kafka.streams.processor.internals.StateDirectory.clean(StateDirectory.java:231)       在org.apache.kafka.streams.KafkaStreams.cleanUp(KafkaStreams.java:931)       在com.macroviewhk.financialreport.simpleStream.start(simpleStream.java:60)       在com.macroviewhk.financialreport.simpleStream.main(simpleStream.java:45)   引起:java.nio.file.DirectoryNotEmptyException:C:\ workspace \ bennychan \ kafka-streams \ my_application_001 \ 0_0       at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:266)       at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)       at java.nio.file.Files.delete(Files.java:1126)       在org.apache.kafka.common.utils.Utils $ 1.postVisitDirectory(Utils.java:651)       在org.apache.kafka.common.utils.Utils $ 1.postVisitDirectory(Utils.java:634)       在java.nio.file.Files.walkFileTree(Files.java:2688)       在java.nio.file.Files.walkFileTree(Files.java:2742)       在org.apache.kafka.common.utils.Utils.delete(Utils.java:634)   ERROR stream-thread [main]无法删除状态目录。 (org.apache.kafka.streams.processor.internals.StateDirectory:297)       在org.apache.kafka.streams.processor.internals.StateDirectory.cleanRemovedTasks(StateDirectory.java:287)   java.nio.file.DirectoryNotEmptyException:C:\ workspace \ bennychan \ kafka-streams \ my_application_001 \ 0_0       在org.apache.kafka.streams.processor.internals.StateDirectory.clean(StateDirectory.java:228)       at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:266)       ......还有3个       at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)       at java.nio.file.Files.delete(Files.java:1126)       在org.apache.kafka.common.utils.Utils $ 1.postVisitDirectory(Utils.java:651)       在org.apache.kafka.common.utils.Utils $ 1.postVisitDirectory(Utils.java:634)       在java.nio.file.Files.walkFileTree(Files.java:2688)       在java.nio.file.Files.walkFileTree(Files.java:2742)       在org.apache.kafka.common.utils.Utils.delete(Utils.java:634)       在org.apache.kafka.streams.processor.internals.StateDirectory.cleanRemovedTasks(StateDirectory.java:287)       在org.apache.kafka.streams.processor.internals.StateDirectory.clean(StateDirectory.java:228)       在org.apache.kafka.streams.KafkaStreams.cleanUp(KafkaStreams.java:931)       在com.macroviewhk.financialreport.simpleStream.start(simpleStream.java:60)       在com.macroviewhk.financialreport.simpleStream.main(simpleStream.java:45)

更新2: 经过另一次详细检查后,下面的行抛出IOException

Files.walkFileTree(file.toPath(), new SimpleFileVisitor<Path>() {

此行位于kafka-clients-1.1.0.jar org.apache.kafka.common.utilsUtils.class

可能这是Windows系统的问题(对不起,我不是一位经验丰富的JAVA程序员)。

4 个答案:

答案 0 :(得分:0)

我同意@ ideano1似乎与https://issues.apache.org/jira/browse/KAFKA-6647有关 - 您可以尝试的是,在测试之间明确调用KafkaStreams#cleanUp()。目前还不清楚为什么Window-OS存在问题。 Atm,所有测试都在Linux上进行。

答案 1 :(得分:0)

这是我们在Windows上实现的功能。这是用Kotlin写的。

使用的版本:kafka-streams-test-utils:2.3.0。

关键是要捕获异常。只要您捕获testDriver.close()引发的异常,测试就将通过,即使您不删除目录也是如此。但是,清理目录会使您的单元测试独立且可重复。

val directory = "test"

@BeforeEach
fun setup(){
    //other code omitted for setting the props
    props.setProperty(StreamsConfig.STATE_DIR_CONFIG,directory)
}

@AfterEach
fun tearDown(){
    try{
        testDriver.close()
    }catch(exception: Exception){
        FileUtils.deleteDirectory(File(directory)) //there is a bug on Windows that does not delete the state directory properly. In order for the test to pass, the directory must be deleted manually
    }
}

答案 2 :(得分:0)

对于测试(但不仅限于您自己负担得起的测试),可以为创建的每个IN_MEMORY("in-memory")使用KTable存储(例如通过聚合直接或间接);这样可以避免创建任何目录,从而不再发生错误。

答案 3 :(得分:-1)

对于Google员工。

我目前正在使用此Scala代码来帮助Windows人员处理状态存储的删除。

if (System.getProperty("os.name").toLowerCase.contains("windows")) {
  logger.info("WINDOWS OS MODE - Cleanup state store.")
  try {
    FileUtils.deleteDirectory(new File("/tmp/kafka-streams/" + config.getProperty("application.id")))
    FileUtils.forceMkdir(new File("/tmp/kafka-streams/" + config.getProperty("application.id")))
  } catch {
    case e: Exception => logger.error(e.toString)
  }
}
else {
  streams.cleanUp()
}