我正在开发一个简单的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程序员)。
答案 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()
}