PHP 多进程 解决难题

PHP 多进程 解决难题

背景

随着互联网的快速发展,现代网站往往承载着大量的请求和用户访问。这些访问一般都需要进行计算和处理,处理数据的计算量逐渐变得越来越大,单线程的方式难以满足这些需求,需要使用多进程的技术来提高并发性能。

多进程实现方式

在PHP中,多进程可以通过开多线程或者创建子进程来实现。其中,开多线程是常见做法,但是多线程带来的内存分配、数据共享、线程同步等问题需要特殊关注。所以相对来说,PHP创建子进程的方案更为常用和实践。

在PHP中创建子进程的方法有很多,比如pcntl_fork(), pcntl_exec(), proc_open()等,这里只介绍较为常用的pcntl_fork()。

pcntl_fork()的用途是开启一个子进程,当前进程(parent process)会克隆一个子进程(child process)并分别在父进程和子进程中执行不同的任务。可以利用子进程来分压在主进程中的一些繁重任务,达到协作的目的。

示例一:多进程爬虫

多进程爬虫适用于大量URL访问,并且URL访问数目不可预测的场景。比如,爬取多个网页、API、爬虫数据等。

下面是一个示例程序:

<?php
$urlList = [
    'https://www.baidu.com',
    'http://www.sina.com',
    'https://www.qq.com',
    'https://www.360.cn',
    'http://wenda.so.com'
];
$maxProcesses = 3;   // 最大进程数

// 创建子进程
echo "Parent PID: " . getmypid() . PHP_EOL;   // 输出主进程的PID
while (count($urlList) > 0) {
    while (count($urlList) > 0 && $activeProcesses < $maxProcesses) {
        $pid = pcntl_fork();
        if ($pid == -1) {
            exit("Error: fork failed\n");
        } elseif ($pid) {
            $activeProcesses++;    // 父进程
            $childs[] = $pid;
            array_shift($urlList);  // 从待处理URL队列中删除一个URL
        } else {
            $url = array_shift($urlList);  // 从待处理URL队列中取出一个URL
            // do some stuff
            sleep(rand(0, 9));  // 模拟请求等待时间
            echo "Child PID: " . getmypid() . ", URL: " . $url . PHP_EOL;
            exit(); // 子进程退出,避免继续执行父进程的代码
        }
    }

    // 等待子进程结束并更新跟踪列表
    if ($activeProcesses > 0) {
        foreach ($childs as $key => $pid) {
            $res = pcntl_waitpid($pid, $status, WNOHANG);
            // 如果子进程退出,将它从childs数组中删除
            if ($res == -1 || $res > 0) {
                $activeProcesses--;
                unset($childs[$key]);
            }
        }
    }
}

// 等待所有子进程结束
while (count($childs) > 0) {
    foreach ($childs as $key => $pid) {
        $res = pcntl_waitpid($pid, $status, WNOHANG);
        // 如果子进程退出,将它从childs数组中删除
        if ($res == -1 || $res > 0) {
            unset($childs[$key]);
        }
    }
}

echo "Done.\n";

上面的示例代码通过创建子进程来并发爬取URL,可以看到执行结果中父进程的PID和每个子进程在执行的时候都会输出它的PID和处理的URL。

示例二:多进程大文件处理

多进程大文件处理适用于对大型文件进行分片处理的场景,比如分析日志文件、统计大量数据等。使用多进程可以快速处理文件,提高处理速度。

下面是一个示例程序:

<?php
// 要处理的大文件
$fileName = 'bigdata.log';

// 分片数量
$sliceNumber = 10;

// 创建子进程
echo "Parent PID: " . getmypid() . PHP_EOL;

for ($i = 0; $i < $sliceNumber; $i++) {
    $pid = pcntl_fork();
    if ($pid == -1) {
        exit("Error: fork failed\n");
    } elseif ($pid) {
        $childs[] = $pid;
    } else {
        // 打开文件
        $fh = fopen($fileName, 'r');

        // 定位到起始位置
        fseek($fh, ($i * filesize($fileName)) / $sliceNumber);

        // 读取文件中的一部分数据
        $data = fread($fh, filesize($fileName) / $sliceNumber);

        // 对数据进行处理操作
        // ...

        echo "Child PID: " . getmypid() . ", Slice No: " . $i . PHP_EOL;

        // 关闭文件句柄
        fclose($fh);

        // 子进程退出
        exit();
    }
}

// 等待所有子进程结束
while (count($childs) > 0) {
    foreach ($childs as $key => $pid) {
        $res = pcntl_waitpid($pid, $status, WNOHANG);
        // 如果子进程退出,将它从childs数组中删除
        if ($res == -1 || $res > 0) {
            unset($childs[$key]);
        }
    }
}

echo "Done.\n";

上面的示例代码通过对大型文件进行分片处理,可以看到执行结果中父进程的PID和每个子进程在执行的时候都会输出它的PID和处理的片段序号。

结论

多进程是一种提高PHP应用并发性能的有效方式,可以利用多核CPU资源进行并发处理,适用于大量请求和高计算量的场景。在使用多进程的过程中,需要注意进程同步和资源共享等问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:PHP 多进程 解决难题 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • Laravel 5框架学习之向视图传送数据(进阶篇)

    Laravel是一种流行的PHP Web开发框架。使用Laravel可以高效地构建Web应用程序。 在Laravel中,视图是展示数据的一种方法。在此处,我们将讲解一些向视图传递数据的方法。 1.使用数组向视图传递数据 使用Laravel向视图传递数据的最基本方法是将数据存储在数组中,然后将该数组传递给视图。以下是一个简单的示例,展示如何向视图传递数组: p…

    PHP 2023年5月23日
    00
  • php实现通用的从数据库表读取数据到数组的函数实例

    下面就详细讲解一下“PHP实现通用的从数据库表读取数据到数组的函数实例”的攻略。 步骤一:连接数据库 首先,我们需要连接数据库,可以使用PHP内置的PDO或MySQLi扩展来完成。这里以PDO为例: $db = new PDO(‘mysql:host=localhost;dbname=mydatabase;charset=utf8mb4’, ‘usernam…

    PHP 2023年5月26日
    00
  • PHP实现提取多维数组指定一列的方法总结

    下面是PHP实现提取多维数组指定一列的方法总结的攻略: 背景介绍 在开发中,经常需要对多维数组进行一些操作,比如提取其中的某一列数据。例如,一个二维数组中包含学生的姓名、分数和班级,我们需要从中提取所有学生的姓名列。 总结方法 提取多维数组的指定一列需要用到循环和数组操作。以下是常见的两种方法: 方法一:使用 foreach 循环 下面是使用 foreach…

    PHP 2023年5月26日
    00
  • 使用 libevent 和 libev 提高网络应用性能的方法

    使用 libevent 和 libev 是提高网络应用性能的常见方法之一,下面将详细讲解使用这两个库提高网络应用性能的完整攻略。 1. libevent 和 libev 简介 libevent 是一个可移植的事件通知库,用于实现事件驱动的程序。 libev 是一个可移植的高性能事件驱动库,与 libevent 类似,但设计更为简单,效率更高。 2. 使用 l…

    PHP 2023年5月27日
    00
  • 用windows自带的ftp.exe实现断点续传的方法

    使用Windows自带的ftp.exe实现断点续传的方法,可以通过以下步骤实现: 1. 开启FTP服务端和连接服务器 在本地开启FTP服务端,比如使用FileZilla Server软件,将文件上传到服务器。 在本地打开cmd终端,输入以下命令连接FTP服务器: ftp IP地址或域名 然后输入FTP服务器的用户名和密码进行登录。 2. 开启二进制模式和断点…

    PHP 2023年5月27日
    00
  • 华为MateBook E怎么样?华为MateBook E变形本详细评测图解

    华为MateBook E 怎么样? 华为MateBook E是一款2合1的变形本,结合了笔记本电脑和平板电脑的优势,搭载了Windows 10操作系统和Intel Core i5处理器。那么,这款产品究竟有什么亮点?下面从几个方面对它进行详细评测。 设计与外观 华为MateBook E采用了全金属外观,细腻的金属质感打磨工艺令人印象深刻。它的重量为1.2kg…

    PHP 2023年5月27日
    00
  • php计算几分钟前、几小时前、几天前的几个函数、类分享

    关于PHP计算几分钟前、几小时前、几天前的函数和类,可以使用一些常用的函数或者类来实现。 以函数方式计算 1.计算几分钟前,可以使用以下代码: function minute_ago($time){ $t = time()-strtotime($time); $f = array( ‘31536000’=>’年’, ‘2592000’=>’个月’…

    PHP 2023年5月26日
    00
  • 超常用的PHP正则表达式收集整理

    超常用的PHP正则表达式收集整理 前言 正则表达式是一个十分强大的工具,可以用来处理各种字符串操作,例如匹配、替换、分割等。在PHP开发中,正则表达式也是一种十分常见的技巧。然而,正则表达式语法复杂,需要我们认真学习和练习。本文将整理收集了一些超常用的PHP正则表达式,供大家参考和学习。 常见正则表达式 匹配中文字符 preg_match(‘/^[\x{4e…

    PHP 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部