Многопоточная загрузка файлов для Linux
Когда большой файл загружается с одного HTTP- или FTP-сервера с помощью обычного инструмента, такого как curl или wget, открывается одно TCP-соединение, и файл загружается последовательно. В быстрой сети это может быть ограничено скоростью сервера для одного соединения, механизмом TCP Slow Start или задержкой туда и обратно. Утилиты для параллельной загрузки одновременно открывают несколько соединений к одному источнику, каждое из которых получает отдельный диапазон байтов, а затем локально собирают результат. Это работает только в том случае, если сервер поддерживает HTTP Range-запросы (отвечая кодом HTTP 206 Partial Content); на серверах, которые поддерживают эту возможность, результатом часто становится заметно более быстрая передача по сравнению с загрузкой через одно соединение.
В этой статье термин «многопоточная загрузка» означает именно такой способ использования параллельных соединений, а не многопоточность внутри самого процесса загрузки.
В статье рассматриваются две такие утилиты для Linux: Axel и aria2.
Axel
Axel — лёгкая утилита для загрузки файлов из командной строки. Она открывает несколько соединений к одному источнику и параллельно загружает разные диапазоны байтов. Поддерживаются HTTP, HTTPS, FTP и FTPS, а также возобновление прерванной загрузки.
Установка Axel
В Debian и Ubuntu:
sudo apt install axel
В RHEL, CentOS Stream, AlmaLinux и Rocky Linux сначала включите EPEL:
sudo dnf install epel-release sudo dnf install axel
В Fedora:
sudo dnf install axel
Использование Axel
Базовая загрузка:
axel https://nl.lg.introserv.eu/1000MB.test
Флаг -a включает компактный индикатор прогресса:
axel -a https://nl.lg.introserv.eu/1000MB.test
Ограничить максимальную скорость загрузки в байтах в секунду можно с помощью -s (или --max-speed). Например, чтобы ограничить скорость передачи до 500 КБ/с:
axel --max-speed=512000 https://nl.lg.introserv.eu/1000MB.test
Сохранить файл под другим именем можно с помощью -o:
axel -o gigabyte.test https://nl.lg.introserv.eu/1000MB.test
Установить количество параллельных соединений можно с помощью -n:
axel -n 10 https://nl.lg.introserv.eu/1000MB.test
Возобновить частично загруженный файл можно с помощью -c:
axel -c https://nl.lg.introserv.eu/1000MB.test
При использовании -c, если локальный файл с таким же именем уже существует, Axel продолжит загрузку с места, на котором она была прервана, вместо повторного скачивания файла с начала.
aria2
aria2 решает ту же задачу параллельной загрузки, что и Axel, но предлагает более широкий набор возможностей. Утилита поддерживает HTTP, HTTPS, FTP, SFTP, BitTorrent и Metalink, а также позволяет одновременно загружать один и тот же файл из нескольких источников. Как и Axel, aria2 разделяет файл на сегменты и загружает их параллельно.
Основные возможности:
- настраиваемое количество соединений с каждым сервером, размер сегментов и общее количество параллельных загрузок
- автоматическое возобновление прерванных загрузок
- проверка целостности на основе контрольных сумм
- поддержка HTTPS и FTPS
- встроенные клиенты BitTorrent и Metalink
Установка aria2
В Debian и Ubuntu:
sudo apt install aria2
В RHEL, CentOS Stream, AlmaLinux и Rocky Linux:
sudo dnf install aria2
В Fedora:
sudo dnf install aria2
Использование aria2
Базовая загрузка:
aria2c https://nl.lg.introserv.eu/1000MB.test
Загрузить один и тот же файл одновременно с двух зеркал. aria2 объединяет соединения с обоими источниками и собирает файл локально:
aria2c "https://nl.lg.introserv.eu/1000MB.test" "https://uk.lg.introserv.eu/1000MB.test"
Объединить HTTP- и FTP-источники, указав учётные данные FTP:
aria2c --ftp-user=<USER> --ftp-passwd=<PASSWD> "ftp://<ftpserver_ip>/<file>" "https://uk.lg.introserv.eu/1000MB.test"
Открыть восемь параллельных соединений с одним сервером, разделив файл на восемь сегментов:
aria2c -x8 -s8 https://nl.lg.introserv.eu/1000MB.test
Флаг -x (или --max-connection-per-server) ограничивает количество соединений, которые aria2 открывает с одним сервером (по умолчанию 1). Флаг -s (или --split) задаёт максимальное количество сегментов, на которые разделяется файл (по умолчанию 5). Для одного источника эффективное количество параллельных соединений равно меньшему из этих двух значений: -x8 -s5 открывает 5 соединений, а -x5 -s8 также открывает 5. Чтобы действительно получить 8 параллельных соединений с одним сервером, необходимо увеличить оба значения, поэтому обычно их устанавливают одинаковыми.
Флаг -k (или --min-split-size) задаёт минимальный размер фрагмента, на который разделяется файл. Меньшие значения позволяют использовать больше параллельных сегментов, но увеличивают накладные расходы:
aria2c -x8 -s8 -k1M https://nl.lg.introserv.eu/1000MB.test
-x, -s и -j решают разные задачи. -x управляет количеством соединений, открываемых с одним сервером при загрузке одного файла. -s определяет, на сколько сегментов разделяется один файл. -j (или --max-concurrent-downloads) определяет, сколько отдельных файлов aria2 загружает одновременно.
Загрузить два файла параллельно:
aria2c -j2 https://nl.lg.introserv.eu/1000MB.test https://uk.lg.introserv.eu/1000MB.test
Возобновить частично загруженный файл с помощью -c:
aria2c -c https://nl.lg.introserv.eu/1000MB.test
При использовании файла Metalink aria2 может автоматически выбирать зеркала, проверять загруженные данные по контрольным суммам, указанным в Metalink, и повторять попытки загрузки с неисправных зеркал без ручного вмешательства.
При регулярном использовании aria2 считывает параметры по умолчанию из файла ~/.aria2/aria2.conf, если этот файл существует. Поэтому такие значения, как max-connection-per-server и split, можно задать там один раз, вместо того чтобы указывать их при каждом запуске.
Открытие большого количества параллельных соединений с публичным зеркалом или CDN может нарушать правила использования оператора и привести к ограничению скорости или временной блокировке. Для публичных источников используйте умеренное количество соединений (обычно безопасным считается значение от 4 до 8); более высокие значения следует использовать только в инфраструктуре, где известно, что они разрешены.
Когда параллельные загрузки помогают
Параллельные загрузки наиболее эффективны, когда узким местом является ограничение скорости сервера для одного соединения или ограничение пропускной способности источника, а не локальный диск или сетевое соединение в целом. Если канал полностью загружен, открытие дополнительных соединений не увеличивает общую пропускную способность — оно лишь перераспределяет её. Некоторые HTTP-серверы также отклоняют Range-запросы или ограничивают количество одновременных соединений от одного клиента. В таком случае инструмент с одним потоком, например wget, будет работать так же быстро, как Axel или aria2.