Hi,
I have a few questions regarding how VFS’s StandardFileSystemManager manages 
SFTP sessions.

In my usage, I noticed that after a file transfer is completed, the session is 
not actively closed, and corresponding sshd processes remain on the SFTP server.

I am using VFS in a service with 5 StandardFileSystemManager instances, each 
handling a large number of concurrent upload tasks.

During local testing, when concurrency is high (e.g., 100), most server-side 
processes are cleaned up, with only a few residual SSH-related processes. 
However, in our production environment, we observe a large number of lingering 
server-side processes.



Eventually, I found that SftpFileSystem#doCloseCommunicationLink is responsible 
for closing the session.

I also noticed that explicitly calling FileSystemManager#closeFileSystem does 
close the session, but it carries potential risks. Another alternative I found 
is to call DefaultFileSystemManager#freeUnusedResources. And it worked.



Here are my questions:

Do we have to close the session manually now? If it is supposed to be 
automatic, how does the mechanism work, and why aren’t the sessions being 
closed?

If manual intervention is required, should we set 
standardFileSystemManager.setFilesCache(new WeakRefFilesCache()) (to help with 
quicker resource release), and then periodically call 
DefaultFileSystemManager#freeUnusedResources()?

In the case of SoftRefFilesCache, I see a log that says “Close FileSystem” — 
does this merely release the association, or does it actually close the 
FileSystem?



The code is:

private StandardFileSystemManager fileSystemManager;

  public FileClient() throws FileSystemException {
    this.fileSystemManager = new StandardFileSystemManager();
    this.fileSystemManager.init();
  }

  private <T> T execute(String path, Function<FileObject, T> function) throws 
FileSystemException {
    FileSystemOptions fileSystemOptions = this.genOptions();
    try {
      FileObject fileObject = fileSystemManager.resolveFile(path, 
fileSystemOptions);
      try {
        return function.apply(fileObject);
      } finally {
        fileObject.close();
//          manager.closeFileSystem(fileObject.getFileSystem());
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public boolean upload(String path, InputStream inputStream) throws 
FileSystemException {
    return execute(path, (fileObject) -> {
      long startTime = YqgClock.now();
      long total;
      try (FileContent fileContent = fileObject.getContent();
           OutputStream outputStream = fileContent.getOutputStream()) {
        total = IOUtils.copy(inputStream, outputStream);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
      return true;
    });
  }

Thanks!

Reply via email to