spring - Spring 集成:使用 NioFileLocker 的入站通道导致只读文件系统异常
问题描述
版本:
Spring: 5.2.16.RELEASE
Spring Integrations: 5.3.9.RELEASE
Ubuntu: focal [20.04.3 LTS]
Java (build and runtime): 11
请参阅下面粘贴的堆栈跟踪。我的入站通道定义如下:
<int-file:inbound-channel-adapter id="channelIn" directory="${channel.dir}" auto-create-directory="false" use-watch-service="true" filter="channelFilter" watch-events="CREATE,MODIFY">
<int-file:locker ref="channelLocker"/>
<int:poller fixed-delay="${channel.polling.delay}" max-messages-per-poll="${channel.polling.maxmsgs}"></int:poller>
</int-file:inbound-channel-adapter>
和
<bean id="channelLocker" class="org.springframework.integration.file.locking.NioFileLocker"/>
我的ServiceActivator
逻辑是这样的:
@Autowired
@Qualifier("channelLocker")
private NioFileLocker nioFileLocker;
@ServiceActivator(inputChannel = "channelIn")
public void processResultsFile(File results)
{
if (!results.exists() || !results.isFile()) {
logger.error("could not process invalid file {}", results.getAbsolutePath());
return;
}
try (InputStream in = new BufferedInputStream(new FileInputStream(results))) {
// Process input stream ...
} catch (Exception ex) {
logger.error("could not process file {}", results.getAbsolutePath(), ex);
}
nioFileLocker.unlock(results);
}
一篇文章讨论了使用 nio FileLock 的挑战。但我不相信我对 nio FileLock 的使用是错误的。相反,我怀疑我正在读取的已安装的网络文件系统是只读的,它会给 nio FileLock 带来问题。所述文件系统的挂载点如下所示:
/etc/auto.pathto on /pathto type autofs (rw,relatime,fd=6,pgrp=634173,timeout=300,minproto=5,maxproto=5,indirect,pipe_ino=2386182)
现在,我将不得不删除 nio FileLock,因为它会妨碍而不是帮助。但是,在从网络只读文件系统读取资源时,是否有某种方法仍然可以获得文件锁定?
22:01:53.262 [task-scheduler-2] ERROR org.springframework.integration.handler.LoggingHandler - org.springframework.messaging.MessagingException: Failed to lock file: /pathto/myfile.txt; nested exception is java.io.FileNotFoundException: /pathto/myfile.txt (Read-only file system)
at org.springframework.integration.file.locking.NioFileLocker.lock(NioFileLocker.java:54)
at org.springframework.integration.file.DefaultDirectoryScanner.tryClaim(DefaultDirectoryScanner.java:85)
at org.springframework.integration.file.FileReadingMessageSource.doReceive(FileReadingMessageSource.java:362)
at org.springframework.integration.file.FileReadingMessageSource.doReceive(FileReadingMessageSource.java:93)
at org.springframework.integration.endpoint.AbstractMessageSource.receive(AbstractMessageSource.java:184)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.receiveMessage(SourcePollingChannelAdapter.java:212)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:408)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.pollForMessage(AbstractPollingEndpoint.java:377)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$null$3(AbstractPollingEndpoint.java:324)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.lambda$execute$0(ErrorHandlingTaskExecutor.java:57)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:55)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$createPoller$4(AbstractPollingEndpoint.java:321)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.io.FileNotFoundException: /pathto/myfile.txt (Read-only file system)
at java.base/java.io.RandomAccessFile.open0(Native Method)
at java.base/java.io.RandomAccessFile.open(RandomAccessFile.java:345)
at java.base/java.io.RandomAccessFile.<init>(RandomAccessFile.java:259)
at java.base/java.io.RandomAccessFile.<init>(RandomAccessFile.java:214)
at org.springframework.integration.file.locking.FileChannelCache.tryLockFor(FileChannelCache.java:61)
at org.springframework.integration.file.locking.NioFileLocker.lock(NioFileLocker.java:51)
... 20 more
解决方案
您对只读文件系统的假设可能是正确的。至少我看到我们有类似的逻辑FileChannelCache
:
FileChannel newChannel = new RandomAccessFile(fileToLock, "rw").getChannel();
所以,我们确实在这里失败了。我相信即使我们只将它设置为r
,我们也会在逻辑上进一步失败,例如:
public final FileLock tryLock() throws IOException {
return tryLock(0L, Long.MAX_VALUE, false);
}
...
if (shared && !readable)
throw new NonReadableChannelException();
if (!shared && !writable)
throw new NonWritableChannelException();
因此 aNioFileLocker
不适合您。
您可以实现自己的FileLocker
,但在大多数情况下,我们只建议使用共享持久性MetadataStore
和FileSystemPersistentAcceptOnceFileListFilter
用于该文件入站通道适配器。这样,您的应用程序的所有实例都将访问同一个存储,并且只有一个实例会处理该文件。所有其他实例将跳过它并转到另一个实例。
在文档中查看更多信息:https ://docs.spring.io/spring-integration/docs/current/reference/html/file.html#file-reading
推荐阅读
- python - numpy 数组的值在读取它们时会发生变化
- android - 如何将 Firebase Cloud Messaging 添加到 android 库模块中
- java - StringUtils 替换两个模式之间的文本
- python - 在大型 GeoJSON 对象中查找多边形坐标交点的最有效方法
- javascript - 为什么 parent::before {width: 继承;position: absolute} 让孩子指定祖父母的百分比宽度?
- istio - Istio CircuitBreaker 通过 URI 路径而不是主机?
- flask - 如何使模型烧瓶棉花糖_sqlalchemy反序列化相关对象
- java - Java 中由 Base64 和 RFC2047 编码的解码字符串(来自标头)
- r - 如何评估嵌套函数中的胶水表达式?
- xamarin.forms - 在 Visual Studio for Mac 上调试 nuget 包不起作用