Почему SCP так медленно и как сделать его быстрее?

Вопрос или проблема

Я пытаюсь скопировать партию файлов с помощью 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/с без.

Как работает NAT-T с IPSec? @ cisco.com

Поскольку этот вопрос не так уж стар, и никто другой не ссылался на это решение, думаю, это уместно, поскольку оно позволяет максимально использовать пропускную способность (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 и предложим несколько решений для ускорения процесса.

Основные причины медленной передачи

  1. Установка соединения:
    Каждое новое соединение SSH, которое устанавливается для передачи файла, требует времени на аутентификацию и шифрование данных. Для нескольких файлов, процесс становится долгим: требует повторной аутентификации и установления канала для каждого файла. Поэтому, при передаче n файлов размером b байт, время, необходимое для их передачи, увеличивается многократно по сравнению с передачей одного файла размером n * b байт.

  2. Ограничения по размеру буфера:
    По умолчанию scp использует статически заданные буферы. В сетях с высокой пропускной способностью это может привести к узким местам в производительности. Некоторые патчи, такие как HPN-SSH, увеличивают размер этих буферов и могут значительно улучшить скорость передачи.

  3. Прочие сетевые факторы:
    Параметры сети, такие как задержка, потери пакетов и конфигурация маршрутизаторов, могут оказывать значительное влияние на скорость передачи. Например, фаерволы или системы защиты от атак могут ухудшать производительность, как это было обнаружено в одном случае, когда отключение защиты от "флуд-атак" увеличивало скорость передачи с 250 КБ/с до 6,5 МБ/с.

Как ускорить передачу файлов

  1. Используйте rsync:
    Вместо scp, используйте rsync, который создает одно соединение для передачи всех файлов и умеет сохранять только измененные части файлов. Например:

    rsync -avP cap_* user@host:~/dir
  2. Сжатием с использованием tar:
    Объедините файлы в один архив и передавайте его, что существенно сокращает время на установление соединений и может ускорить процесс. Например:

    tar czf - cap_* | ssh user@host tar xzf - -C dir
  3. Настройка TCP буферов:
    Увеличение значений TCP-буферов может помочь. Для этого выполните следующие команды:

    sysctl -w net.ipv4.tcp_rmem='40960 873800 62914560'
    sysctl -w net.core.rmem_max=8388608

    Однако изменения будут временными и потребуют перезапуска для достижения постоянного эффекта.

  4. Использование HPN-SSH:
    Проверьте, используется ли версия OpenSSH с патчем HPN-SSH и установите его, если это необходимо. Это может значительно повысить скорость передачи при интенсивной работе с файлами.

  5. Откажитесь от scp:
    Если вы не обязаны использовать именно scp, рассмотрите возможность использования sftp, который основан на более современном протоколе:

    sftp user@host

Заключение

Существуют различные способы ускорения передачи файлов через scp, от использования rsync и бинарного сжатия до корректировки сетевых настроек. Учитывая, что многие сетевые проблемы могут быть проблематичными, оцените каждое из предложенных решений и выберите то, которое подходит вам наиболее. Таким образом, вы сможете не только ускорить процесс передачи файлов, но и оптимизировать работу с сетевой инфраструктурой в целом.

Оцените материал
Добавить комментарий

Капча загружается...