5

同じ LAN 上に 2 つの Linux サーバーがあります。
PHP を使用して、サーバー A からサーバー B に 100000 個の小さな (10KB) ファイルをコピーする必要があります。

今、私は ssh2_scp_send を使用していますが、非常に遅いです (20 分で 10K ファイル)。

速くする方法は?

4

4 に答える 4

4

SSH トンネルを介して gzip された TAR を使用すると、非常に高速です。scp特に多くの小さなファイルに関して、pure よりも高速です。Linux コマンド ラインの例を次に示します。

user@local# cd /source/ ; タール czf - * | ssh user@remote "cd /target/ ; tar xzf -"


更新:要求に応じて、ここでは純粋な PHP ソリューションを使用します。このトリッキーなビットをいじって楽しんでいました。

注: これを機能させるには、PHP のlibssh 拡張機能が必要です。また、STDIN は、SSH のストリーム ラッパーを使用する場合にのみ使用できるようです。

これはストリームを直接操作しているため、オーバーヘッドはほとんどありません。CPU は、転送に使用しているネットワーク リンクよりも常に高速である可能性が高いです。

ネットワークと CPU 速度をトレードするために-z、コマンド ラインからオプションを削除できます。(CPU 使用率は低下しますが、ネットワーク上のデータは増加します)

コード例:

<?php
$local_cmd = "cd /tmp/source && tar -czf - *";
$remote_cmd = "tar -C /tmp/target -xzf -";

$ssh = new SSH_Connection('localhost');
$auth = $ssh->auth_password('gast', 'gast');
$bytes = $ssh->command_pipe($local_cmd, $remote_cmd);
echo "finished: $bytes bytes of data transfered\n";

class SSH_Connection {
    private $link;
    private $auth;

    function __construct ($host, $port=22) {
        $this->link = @ssh2_connect('localhost', 22);
    }  

    function auth_password ($username, $password) {
        if (!is_resource($this->link))
            return false;
        $this->auth = @ssh2_auth_password($this->link, $username, $password); 
        return $this->auth;
    }   

    function command_pipe ($localcmd, $remotecmd) {
        if (!is_resource($this->link) || !$this->auth)
            return false;
        // open remote command stream (STDIN)
        $remote_stream = fopen("ssh2.exec://{$this->link}/$remotecmd", 'rw');
        if (!is_resource($remote_stream))
            return false;
        // open local command stream (STDOUT)
        $local_stream = popen($localcmd, 'r');
        if (!is_resource($local_stream))
            return false;
        // connect both, pipe data from local to remote
        $bytes = 0;
        while (!feof($local_stream)) 
            $bytes += fwrite($remote_stream,fread($local_stream,8192));
        // close streams
        fclose($local_stream);
        fclose($remote_stream);
        return $bytes; 
    }   

    function is_connected () { return is_resource($this->link); }
    function is_authenticated () { return $this->auth; }
}
于 2012-05-09T10:39:25.673 に答える
0

大量の小さなファイルを送信するオーバーヘッドは、ここでの速度低下である可能性があります。

あなたはそれをあなたのローカルサーバー、shell_exec()にアーカイブすることができます

それをリモートサーバーに送信します、ssh2_scp_send()

次に、もう一方の端で展開します。ssh2_exec()

アーチ/拡張のオーバーヘッドは少なくなると思いますが、これはテストしていません。

于 2012-05-09T10:37:03.017 に答える
0

別のオプションは Zip です。

<?php
$zip = new ZipArchive();

if ($zip->open('TempFileToTransfer.zip', ZIPARCHIVE::CREATE)!==TRUE) {
    exit("cannot open <$filename>\n");
}

$zip->addFile('File 1');
$zip->addFile('File 2');
$zip->addFile('File 3');
$zip->close();
?>

その一方のファイルを転送し、もう一方の端で解凍し、もう一方の端で zip_entry_open と zip_entry_read を使用します。

また、一度に 1000 個のファイルのチャンクを提案しますか?

于 2012-05-09T10:32:19.497 に答える