尝试在 Linux 上的 Docker 容器中列出 FTP 服务器目录时读取超时

Read time out when trying to list FTP server directory in Docker container on Linux

我有使用 LIST 命令轮询 FTP 服务器的服务。我使用本地被动模式,使用具有以下设置的 FTPSClient:

ftpClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
ftpClient.setDataTimeout(1800000); //30 minutes
ftpClient.setBufferSize(1281000000);
ftpClient.setControlKeepAliveTimeout(120);

FTP 服务器目录中有大约 700,000 个文件,因此服务器响应需要时间。在我的本地机器上,通过启动原始 Java 应用程序,大约需要 5 分钟来检索文件列表,在 Windows 上的 Docker 容器中,它同时也可以正常工作,FileZilla - 没有问题,但更长。但是,当我 运行 Linux 机器(Ubuntu 18.04.4 LTS)上的容器时,尽管它可以连接到服务器,但它无法检索数据。在超时设置的指定时间后,我收到:

Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) ~[?:?] at java.net.SocketInputStream.socketRead(SocketInputStream.java:115) ~[?:?] at java.net.SocketInputStream.read(SocketInputStream.java:168) ~[?:?] at java.net.SocketInputStream.read(SocketInputStream.java:140) ~[?:?] at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) ~[?:?] at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) ~[?:?] at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) ~[?:?] at java.io.InputStreamReader.read(InputStreamReader.java:185) ~[?:?] at java.io.BufferedReader.fill(BufferedReader.java:161) ~[?:?] at java.io.BufferedReader.readLine(BufferedReader.java:326) ~[?:?] at java.io.BufferedReader.readLine(BufferedReader.java:392) ~[?:?] at org.apache.commons.net.ftp.FTPFileEntryParserImpl.readNextEntry(FTPFileEntryParserImpl.java:53) ~[app.jar:?] at org.apache.commons.net.ftp.FTPListParseEngine.readStream(FTPListParseEngine.java:142) ~[app.jar:?] at org.apache.commons.net.ftp.FTPListParseEngine.readServerList(FTPListParseEngine.java:118) ~[app.jar:?] at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3450) ~[app.jar:?] at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3371) ~[app.jar:?] at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3308) ~[app.jar:?] at org.my.org.ftp.FtpOperator.listDirectory(FtpOperator.java:30) ~[app.jar:?]

我想这不是防火墙的问题,因为我有类似的服务可以轮询外部服务器并且它工作正常。两种服务都使用 Apache FTP 客户端库的本地被动模式。

Docker-编写文件:

version: '2'
services:
  ingest:
    image: pl/ingest
    ports:
      - "8038:8038"

    volumes:
      - ./logs:/logs
      - ./processedFiles:/processedFiles

networks:                                
  default:                               
    driver: bridge                       
    driver_opts:                         
      com.docker.network.driver.mtu: 1500

在 docker 中将网络模式从网桥更改为主机-compose 使容器能够通过 FTPS/FTP:

列出文件
version: '2'
services:
  ingest:
    image: pl/ingest
    ports:
      - "8038:8038"
    volumes:
      - ./logs:/logs
      - ./processedFiles:/processedFiles
    network_mode: "host"

遇到了同样的问题 SuperUser answer:

... active mode ftp is not suited for containerized ftp clients, due to the server actively trying to initiate a data connection to the ftp client, which is not possible for a container.

有容器解决方法,但解决此问题的编程方法可能更简单:连接后更改为被动模式即可。

ftpClient.enterLocalPassiveMode()

现在对我有用了。