Вопрос или проблема
Я пытаюсь скопировать партию файлов с помощью scp
, но это очень медленно. Вот пример с 10 файлами:
$ time scp cap_* user@host:~/dir
cap_20151023T113018_704979707.png 100% 413KB 413.2KB/s 00:00
cap_20151023T113019_999990226.png 100% 413KB 412.6KB/s 00:00
cap_20151023T113020_649251955.png 100% 417KB 416.8KB/s 00:00
cap_20151023T113021_284028464.png 100% 417KB 416.8KB/s 00:00
cap_20151023T113021_927950468.png 100% 413KB 413.0KB/s 00:00
cap_20151023T113022_567641507.png 100% 413KB 413.1KB/s 00:00
cap_20151023T113023_203534753.png 100% 414KB 413.5KB/s 00:00
cap_20151023T113023_855350640.png 100% 412KB 411.7KB/s 00:00
cap_20151023T113024_496387641.png 100% 412KB 412.3KB/s 00:00
cap_20151023T113025_138012848.png 100% 414KB 413.8KB/s 00:00
cap_20151023T113025_778042791.png 100% 413KB 413.4KB/s 00:00
real 0m43.932s
user 0m0.074s
sys 0m0.030s
Странно, что скорость передачи составляет около 413KB/s, а размер файла — около 413KB, так что на самом деле должно передаваться по одному файлу в секунду, однако это занимает около 4,3 секунд на файл.
Есть идеи, откуда берется это время простоя, и есть ли способ сделать это быстрее?
Вы можете использовать rsync
(по ssh
), который использует одно соединение для передачи всех исходных файлов.
rsync -avP cap_* user@host:dir
Если у вас нет rsync
(и почему бы и нет!?) вы можете использовать tar
с ssh
вот так, это избегает создания временного файла (эти два варианта эквивалентны):
tar czf - cap_* | ssh user@host tar xvzfC - dir
tar cf - cap_* | gzip | ssh user@host 'cd dir && gzip -d | tar xvf -'
Предпочтение следует отдавать rsync
, если все остальные факторы постоянны, так как он позволяет продолжить передачу в случае прерывания.
@wurtel’s comment вероятно, верен: установка каждого соединения требует много времени. Если вы сможете это исправить, вы получите более быстрые передачи (а если нет, просто используйте @решение rsync
от roaima). Я провел эксперимент, передавая файлы примерно одинакового размера (head -c 417K /dev/urandom > foo.1
и сделал несколько копий этого файла) на хост, который медленно подключается (HOST4), и один, который отвечает очень быстро (HOST1):
$ time ssh $HOST1 echo
real 0m0.146s
user 0m0.016s
sys 0m0.008s
$ time scp * $HOST1:
foo.1 100% 417KB 417.0KB/s 00:00
foo.2 100% 417KB 417.0KB/s 00:00
foo.3 100% 417KB 417.0KB/s 00:00
foo.4 100% 417KB 417.0KB/s 00:00
foo.5 100% 417KB 417.0KB/s 00:00
real 0m0.337s
user 0m0.032s
sys 0m0.016s
$ time ssh $HOST4 echo
real 0m1.369s
user 0m0.020s
sys 0m0.016s
$ time scp * $HOST4:
foo.1 100% 417KB 417.0KB/s 00:00
foo.2 100% 417KB 417.0KB/s 00:00
foo.3 100% 417KB 417.0KB/s 00:00
foo.4 100% 417KB 417.0KB/s 00:00
foo.5 100% 417KB 417.0KB/s 00:00
real 0m6.489s
user 0m0.052s
sys 0m0.020s
$
Именно переговоры о передаче занимают время. Операции над n файлами по b байт каждый требуют гораздо больше времени, чем одна операция с одним файлом размером n * b байт. Это также верно для операций ввода-вывода на диске.
Если вы посмотрите внимательно, то увидите, что скорость передачи в этом случае составляет размер_файла/сек.
Чтобы передать файлы более эффективно, объедините их с помощью tar
, затем передайте архив:
tar cvf myarchive.tar cap_20151023T*.png
или, если вы хотите также сжать архив,
tar cvzf myarchive.tar.gz myfile*
Компрессировать или нет — зависит от типа файлов внутри архива: если они все JPEG или PNG, например, компрессия не даст никакого эффекта, так как данные внутри этих типов файлов уже сжаты.
Еще одной причиной, по которой scp
медленнее, чем должна быть, особенно в сетях с высокой пропускной способностью, является то, что он имеет статически определенные внутренние буферы управления потоком, которые становятся узким местом в производительности сети.
HPN-SSH — это патченная версия OpenSSH, которая увеличивает размер этих буферов. Это существенно увеличивает скорость передачи scp
(смотрите графики на сайте, но я также говорю из личного опыта). Конечно, для получения преимуществ вам нужно установить HPN-SSH на все свои хосты, но это стоит того, если вам регулярно нужно передавать большие файлы.
Я использовал технику, описанную здесь (в архиве), которая использует параллельный gzip и netcat для быстрого сжатия и копирования данных.
Это сводится к:
# SOURCE:
> tar -cf - /u02/databases/mydb/data_file-1.dbf | pigz | nc -l 8888
# TARGET:
> nc <source host> 8888 | pigz -d | tar xf - -C /
Это использует tar
, чтобы собрать файл или файлы. Затем используется pigz
, чтобы задействовать множество потоков ЦП для сжатия и отправки файла, а передача по сети осуществляется с помощью netcat
. На стороне получателя netcat
слушает, затем распаковывает (параллельно) и распаковывает файлы.
Только что столкнулся с этой проблемой, выполняя передачу большого mp4 файла через scp
. Скорость составляла ~250KB/s. После отключения защиты от атак UDP (FP) на конечном фаерволе скорость передачи увеличилась до 6.5MB/s. Когда FP снова включили, скорость вернулась к ~250KB/s.
Отправитель: cygwin, Получатель: Fedora 20, Фаервол Sophos UTM.
Для чего SSH использует UDP? @ superuser.com — Он не использует это напрямую, судя по тому, что я прочитал.
При проверке журнала фаервола обнаружено, что обнаружение потопа происходит как на исходных, так и на конечных портах 4500 по общедоступным IP-адресам, а не по внутренним VPN-адресам. Похоже, что моя проблема, скорее всего, связана с ситуацией NAT Traversal, где данные TCP scp
в конечном итоге шифруются и инкапсулируются в пакетах ESP и UDP, и, следовательно, подлежат FP. Чтобы исключить scp
из уравнения, я выполнил операцию копирования файлов Windows через VPN и заметил аналогичную производительность с scp
с включенной и отключенной FP. Также провел тест iperf
через TCP и заметил 2Mbit/с с FP и 55Mbit/с без.
Поскольку этот вопрос не так уж стар, и никто другой не ссылался на это решение, думаю, это уместно, поскольку оно позволяет максимально использовать пропускную способность (10MiB/s в моем случае), в отличие от scp
, который составляет около 250kb/s, так что это отвечает на ваш вопрос.
На самом деле те же 250kb/s с rsync
— по крайней мере, с спецификатором порта rclone -Avvp cap_* -e "ssh -p 1087 -i id_rsa" user@host:~/dir
Цитируя сообщение в списке рассылки openssh-unix-dev:
Протокол
scp
устарел, не гибок и не поддается легкому исправлению. Его авторы рекомендуют использовать более современные протоколы, такие какsftp
иrsync
для передачи файлов вместо этого.
sftp, так что вместо scp text.txt user@host
теперь sftp text.txt user@host
(примеры использования scp
аналогично sftp
)
Также последняя версия OpenSSH должна активировать демона — по крайней мере, в моем случае на сервере arch linux, но вам, возможно, придется установить пакет sftp
на других дистрибутивах.
Еще один рабочий пример с флагом файла шифрования ssh (id_rsa) и нестандартным ssh портом 1087 вместо 22, чтобы сэкономить ваше время на настройку синтаксиса:
sftp -P 1087 -i id_rsa user@server:/home/user/Downloads/Video/*/*.mp4 /home/user/Videos/
Также ваш sftp
может быть ограничен 800kb/s или ~1 Mbit/s. Вы можете проверить это с помощью:
# sysctl -a | grep net.*rmem
и вы можете изменить пределы, например, так, если они слишком медленные:
# sysctl -w net.ipv4.tcp_rmem='40960 873800 62914560'
# sysctl -w net.core.rmem_max=8388608
Вы можете сделать свой сервер онлайн-веб-сайтом.
$ sudo apt-get install apache2
# откройте порт 80 на своем сервере
# скопируйте свои файлы на сервер в /var/www/html/
# если вы не можете копировать или делать ссылки, используйте:
$ sudo chown $USER /var/www/html/
и скачивайте свои файлы, используя wget или curl…
$ wget http://40.86.167.128/video.mp4
Для меня я получил 100% скорости по Wi-Fi 4 Mbit/s, что означает, что моя скорость составляет 4 Mbit/s
и 25% для Wi-Fi 100 Mbit/s, что означает 25 Mbit/s, а не 100 Mbit/s
но с rsync или scp я получил 1 Mbit/s для Wi-Fi 4 Mbit/s
Ответ или решение
Почему передача файлов с помощью SCP такая медленная и как ее ускорить
Скопировать файлы с помощью программы scp
(secure copy), возможно, один из самых простых способов передачи данных между компьютерами по сети. Однако многие пользователи сталкиваются с проблемой низкой скорости передачи. В данной статье мы подробно рассмотрим основные причины медленной передачи с использованием scp
и предложим несколько решений для ускорения процесса.
Основные причины медленной передачи
-
Установка соединения:
Каждое новое соединение SSH, которое устанавливается для передачи файла, требует времени на аутентификацию и шифрование данных. Для нескольких файлов, процесс становится долгим: требует повторной аутентификации и установления канала для каждого файла. Поэтому, при передаче n файлов размером b байт, время, необходимое для их передачи, увеличивается многократно по сравнению с передачей одного файла размером n * b байт. -
Ограничения по размеру буфера:
По умолчаниюscp
использует статически заданные буферы. В сетях с высокой пропускной способностью это может привести к узким местам в производительности. Некоторые патчи, такие как HPN-SSH, увеличивают размер этих буферов и могут значительно улучшить скорость передачи. -
Прочие сетевые факторы:
Параметры сети, такие как задержка, потери пакетов и конфигурация маршрутизаторов, могут оказывать значительное влияние на скорость передачи. Например, фаерволы или системы защиты от атак могут ухудшать производительность, как это было обнаружено в одном случае, когда отключение защиты от "флуд-атак" увеличивало скорость передачи с 250 КБ/с до 6,5 МБ/с.
Как ускорить передачу файлов
-
Используйте
rsync
:
Вместоscp
, используйтеrsync
, который создает одно соединение для передачи всех файлов и умеет сохранять только измененные части файлов. Например:rsync -avP cap_* user@host:~/dir
-
Сжатием с использованием
tar
:
Объедините файлы в один архив и передавайте его, что существенно сокращает время на установление соединений и может ускорить процесс. Например:tar czf - cap_* | ssh user@host tar xzf - -C dir
-
Настройка TCP буферов:
Увеличение значений TCP-буферов может помочь. Для этого выполните следующие команды:sysctl -w net.ipv4.tcp_rmem='40960 873800 62914560' sysctl -w net.core.rmem_max=8388608
Однако изменения будут временными и потребуют перезапуска для достижения постоянного эффекта.
-
Использование HPN-SSH:
Проверьте, используется ли версия OpenSSH с патчем HPN-SSH и установите его, если это необходимо. Это может значительно повысить скорость передачи при интенсивной работе с файлами. -
Откажитесь от
scp
:
Если вы не обязаны использовать именноscp
, рассмотрите возможность использованияsftp
, который основан на более современном протоколе:sftp user@host
Заключение
Существуют различные способы ускорения передачи файлов через scp
, от использования rsync
и бинарного сжатия до корректировки сетевых настроек. Учитывая, что многие сетевые проблемы могут быть проблематичными, оцените каждое из предложенных решений и выберите то, которое подходит вам наиболее. Таким образом, вы сможете не только ускорить процесс передачи файлов, но и оптимизировать работу с сетевой инфраструктурой в целом.