Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Pembangunan coroutine tak segerak PHP: menyelesaikan masalah memuat naik dan memuat turun fail besar

Pembangunan coroutine tak segerak PHP: menyelesaikan masalah memuat naik dan memuat turun fail besar

PHPz
PHPzasal
2023-12-18 17:09:31959semak imbas

Pembangunan coroutine tak segerak PHP: menyelesaikan masalah memuat naik dan memuat turun fail besar

Dengan perkembangan teknologi rangkaian dan pengembangan berterusan senario aplikasi, memuat naik dan memuat turun fail besar telah menjadi masalah yang dihadapi oleh banyak aplikasi web. Kaedah pemprosesan tradisional selalunya memakan masa dan tidak cekap, manakala pembangunan coroutine tak segerak PHP boleh menyelesaikan masalah ini dengan berkesan.

Dalam beberapa tahun kebelakangan ini, teknologi pengaturcaraan tak segerak bagi bahasa PHP secara beransur-ansur telah digunakan secara meluas, antaranya teknologi coroutine telah digunakan dengan lebih meluas dalam pembangunan sebenar. Coroutine ialah bentuk lanjutan penjalinan pengguna yang membenarkan utas untuk mengganggu, menunggu beberapa peristiwa berlaku, dan kemudian menyambung semula pelaksanaan utas itu. Dalam istilah orang awam, ini bermakna secara aktif menyerahkan CPU untuk melaksanakan beberapa operasi lain semasa pelaksanaan kod.

Aplikasi pembangunan coroutine tak segerak PHP dalam muat naik dan muat turun fail besar akan diperkenalkan secara terperinci di bawah.

1. Muat naik fail besar

Dalam aplikasi web, muat naik fail besar biasanya dilaksanakan melalui protokol HTTP. Apabila pengguna memuat naik fail yang besar, pelayan perlu membaca fail ke dalam memori dan menulisnya ke cakera Proses ini memerlukan banyak masa dan sumber. Jika dalam kaedah pemprosesan tradisional, sebaik sahaja fail besar dimuat naik, pelayan akan menunggu muat naik selesai dan tidak dapat mengendalikan permintaan lain pada masa yang sama. Ini bukan sahaja membazir sumber tetapi juga menjejaskan pengalaman pengguna.

Penyelesaian berasaskan coroutine:

1 Klien memuat naik fail ke pelayan dalam kepingan Ini dilaksanakan menggunakan API FormData dan objek XMLHttpRequest 2. Selepas pelayan menerima permintaan muat naik, ia menyemak bilangan kepingan fail yang dimuat naik Adakah ia konsisten dengan saiz fail Jika ya, simpan kepingan yang diterima dalam fail sasaran.

3 Jika ia tidak konsisten, mesej ralat akan dikembalikan. Jika mana-mana blok fail gagal diterima, blok lain yang dimuat naik harus dibersihkan untuk mengelakkan daripada menghasilkan fail separuh siap.

4 Selepas muat naik selesai, pelayan boleh mengendalikan atribut fail, dsb. Jika fail agak besar, fail boleh diproses secara tak segerak untuk mengelakkan sensitiviti intensif IO dan CPU kepada CPU.

Berikut ialah contoh kod:

<?php
// 启用协程运行时
SwooleRuntime::enableCoroutine();

$http = new SwooleHttpServer("127.0.0.1", 9501);

// 监听HTTP请求
$http->on("request", function ($request, $response) {

    // 从请求中获取分块数据
    $chunk = $request->rawContent();

    // 获取分块所属的文件名和分块编号
    $fileName = $_POST['fileName'];
    $chunkIndex = $_POST['chunkIndex'];

    // 将分块数据追加写入到目标文件中
    $fp = fopen($fileName, 'ab');
    fwrite($fp, $chunk);
    fclose($fp);

    // 判断是否上传完成
    if (intval($_POST['totalChunks']) == $chunkIndex + 1) {
        $response->end("Upload completed.");
    } else {
        $response->end("Upload success.");
    }
});

$http->start();

2. Muat turun fail besar

Dalam aplikasi web, muat turun fail besar juga dilaksanakan melalui protokol HTTP. Apabila pengguna perlu memuat turun fail yang besar, pelayan perlu membaca fail dari cakera dan menghantarnya kepada klien Proses ini juga mengambil banyak masa dan sumber. Jika dalam kaedah pemprosesan tradisional, pelayan membaca keseluruhan fail ke dalam memori pada satu masa dan menghantarnya kepada pelanggan, ini bukan sahaja membazir sumber, tetapi juga boleh menyebabkan pelayan ranap.

Penyelesaian berasaskan coroutine:

Pertama, baca blok data tertentu dari cakera setiap kali dan hantarkannya kepada pelanggan

Kedua, gunakan coroutine untuk kawalan dan menyerah untuk menyerahkan CPU selepas setiap jumlah data tertentu dihantar

3 Selepas pelanggan menggunakan blok semasa, ia menghantar mesej kepada pelayan dan memasuki penghantaran data blok seterusnya

Berikut ialah kod contoh:

<?php
// 启用协程运行时
SwooleRuntime::enableCoroutine();

$server = new SwooleHttpServer('127.0.0.1', 9502);

$server->on('request', function($request, $response) {
    $filePath = '/path/to/large/file';
    $startPos = 0;
    $readChunkSize = 8192;

    $fileSize = filesize($filePath);

    $response->header('Content-Type', 'application/octet-stream');
    $response->header('Accept-Ranges', 'bytes');

    // 读取和发送一块数据
    function readAndSendChunk($fp, $response, $startPos, $readChunkSize, $fileSize) {
        fseek($fp, $startPos);
        $maxLength = $fileSize - $startPos;
        if ($maxLength > $readChunkSize) {
            $maxLength = $readChunkSize;
        }
        $data = fread($fp, $maxLength);
        $response->write($data);
        return $startPos + $maxLength;
    }

    // 每发送一定量的数据后yield,让出CPU
    function sendByYield($fp, $response, $startPos, $readChunkSize, $fileSize) {
        while ($startPos < $fileSize) {
            $startPos = readAndSendChunk($fp, $response, $startPos, $readChunkSize, $fileSize);
            yield;
        }
        fclose($fp);
        $response->end();
    }

    // 检查是否支持断点续传
    $range = $request->header['range'];
    if ($range) {
        $status = '206 Partial Content';
        $range = explode('-', substr($range, 6));
        if ($range[0] === '') {
            $startPos = $fileSize - intval($range[1]);
        } else if ($range[1] === '') {
            $startPos = intval($range[0]);
        } else {
            $startPos = intval($range[0]);
            $readChunkSize = intval($range[1]) - $startPos + 1;
            $response->header('Content-Length', $readChunkSize);
        }
    } else {
        $status = '200 OK';
        $response->header('Content-Length', $fileSize);
    }

    $response->header('HTTP/1.1', $status);
    $response->header('Content-Disposition', 'attachment;filename="'.basename($filePath).'"');
    $response->header('Content-Range', 'bytes '.$startPos.'-'.($startPos+$readChunkSize-1).'/'.$fileSize);

    $fp = fopen($filePath, 'rb');
    fseek($fp, $startPos);

    $response->status(200);

    // 使用协程进行控制
    for ($i = 1; $i <= 5; $i++) {
        go(function() use ($fp, $response, $startPos, $readChunkSize, $fileSize) {
            yield from sendByYield($fp, $response, $startPos, $readChunkSize, $fileSize);
        });
    }
});

$server->start();

Kesimpulan:

Artikel ini. memperkenalkan coroutine tak segerak PHP secara terperinci Membangunkan aplikasi untuk memuat naik dan memuat turun fail besar, dan menyediakan contoh pelaksanaan kod khusus. Dalam pembangunan sebenar, penggunaan teknologi pengaturcaraan tak segerak berasaskan coroutine boleh meningkatkan prestasi pemprosesan dan pengalaman pengguna aplikasi web secara berkesan, yang layak untuk penyelidikan dan penerokaan mendalam oleh pembangun.

Atas ialah kandungan terperinci Pembangunan coroutine tak segerak PHP: menyelesaikan masalah memuat naik dan memuat turun fail besar. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn