#java #docker #ftp #apache-commons-net
#java #докер #ftp #apache-commons-net
Вопрос:
У меня есть служба, которая опрашивает FTP-сервер с помощью команды LIST. Я использую локальный пассивный режим, использую FTPSClient со следующей настройкой:
ftpClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
ftpClient.setDataTimeout(1800000); //30 minutes
ftpClient.setBufferSize(1281000000);
ftpClient.setControlKeepAliveTimeout(120);
Каталог FTP-сервера содержит около 700 000 файлов, поэтому серверу требуется время для ответа. На моем локальном компьютере при запуске необработанного Java-приложения для получения списка файлов требуется около 5 минут, в контейнере Docker в Windows он также работает без проблем в то же время, FileZilla — без проблем, но дольше. Однако, когда я запускаю контейнер на компьютере с Linux (Ubuntu 18.04.4 LTS), он не может получить данные, несмотря на то, что он может подключаться к серверу. По истечении указанного времени в настройках таймаута я получаю:
Вызвано: java.net.SocketTimeoutException: время ожидания чтения истекло в java.net.SocketInputStream.socketRead0 (собственный метод) ~ [?:?] в java.net.SocketInputStream.socketRead(SocketInputStream.java:115) ~ [?:?] в java.net.SocketInputStream.read(SocketInputStream.java: 168) ~[?:?] в java.net.SocketInputStream.read(SocketInputStream.java:140) ~[?:?] в sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java: 284) ~[?:?] в sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java: 326) ~[?:?] в sun.nio.cs.StreamDecoder.read(StreamDecoder.java: 178) ~ [?:?] в java.io.InputStreamReader.read(InputStreamReader.java:185) ~ [?:?]:?] в java.io.BufferedReader.fill(BufferedReader.java: 161) ~ [?:?] в java.io.BufferedReader.readLine(BufferedReader.java: 326) ~ [?:?] в java.io.BufferedReader.readLine(BufferedReader.java: 392)~[?:?] в org.apache.commons.net.ftp.FTPFileEntryParserImpl.readNextEntry(FTPFileEntryParserImpl.java:53) ~ [app.jar :?] в org.apache.commons.net.ftp.FTPListParseEngine.ReadStream(FTPListParseEngine.java:142) ~[app.jar :?]в org.apache.commons.net.ftp.FTPListParseEngine.readServerList(FTPListParseEngine.java: 118) ~ [app.jar :?] в орг.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3450) ~[app.jar :?] в org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3371) ~[app.jar :?] в org.apache.commons.net .ftp.FTPClient.initiateListParsing (FTPClient.java:3308) ~[app.jar :?] в каталоге org.my.org.ftp.FtpOperator.list(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
Комментарии:
1. @MartinPrikryl Я мог получить список с помощью FTP-клиента командной строки (не FTPS). Я запускаю это приложение без Docker, запустив JAR-файл, который использует FTPS (фактически команду gradle run), и он также может указывать каталог. Все это было на компьютере с Linux.
2. Обычная работа FTP в Java, клиент командной строки FTPS также работает. Обычный FTP также не работает в Docker.
3. Я имею в виду, что FTP-клиент командной строки работает в той же среде, в которой нет контейнера Docker, как обычного, так и FTPS. Java JAR (gradle run) работает в той же среде, что и контейнер Docker not, как обычный, так и FTPS. Ни обычный FTP, ни FTPS (в Java JAR) не работают в контейнере Docker.
Ответ №1:
Изменение сетевого режима с моста на хост в docker-compose сделало контейнер способным перечислять файлы по FTPS / FTP:
version: '2'
services:
ingest:
image: pl/ingest
ports:
- "8038:8038"
volumes:
- ./logs:/logs
- ./processedFiles:/processedFiles
network_mode: "host"
Ответ №2:
С той же проблемой y обратился к этому ответу суперпользователя:
… ftp в активном режиме не подходит для контейнерных ftp-клиентов, поскольку сервер активно пытается инициировать подключение для передачи данных к ftp-клиенту, что невозможно для контейнера.
Существуют обходные пути для контейнеров, но программный способ решения этой проблемы может быть проще: просто переключитесь в пассивный режим после подключения.
ftpClient.enterLocalPassiveMode()
И теперь это работает для меня.
Комментарии:
1. У меня был включен локальный пассивный режим, и я все равно столкнулся с этой проблемой в контейнере Docker. Это зависит от FTP-сервера. Я подключался к FTP-серверам в локальном пассивном режиме, когда мне не нужно было устанавливать сетевой режим в конфигурации контейнера. В этом конкретном случае мне это было нужно.
2. Вы установили пассивный режим ПОСЛЕ подключения?
3. ДА. Как я уже упоминал, это работало для других FTP-серверов.