PHP 多进程 解决难题

yizhihongxing

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日

相关文章

  • 实例讲解PHP设计模式编程中的简单工厂模式

    下面是关于“实例讲解PHP设计模式编程中的简单工厂模式”的完整攻略: 1. 简单工厂模式的概念 简单工厂模式(Simple Factory Pattern)是一种常用的工厂模式,又叫静态工厂方法模式(Static Factory Method Pattern)。 简单工厂模式的作用是根据不同的参数,返回不同类的实例。这样可以把对象的创建和客户代码的调用分离开…

    PHP 2023年5月23日
    00
  • PHP如何防止用户重复提交表单

    防止用户重复提交表单是一个比较常见的问题。下面,我提供一份针对 PHP 的防重复提交表单的攻略。 一、使用 Token 防止 CSRF 攻击 在 Web 应用中,CSRF(跨站点请求伪造)攻击是一个常见威胁。一般情况下,CSRF 攻击需要重复提交表单才能达到目的。因此,防重复提交表单也可以帮助防止 CSRF 攻击。 其中一个防止 CSRF 攻击的技术是利用 …

    PHP 2023年5月27日
    00
  • Yii调试SQL的常用方法

    下面是详细讲解“Yii调试SQL的常用方法”的完整攻略: 1. Yii调试SQL的必备工具 要调试Yii应用程序中的SQL查询,必须了解以下几个工具: Yii内置的调试器:Yii框架提供了一个调试器,可以在Web应用程序中显示SQL查询和其他调试信息。启用它可以快速定位SQL查询问题。 Xdebug调试器:Xdebug是一款PHP调试器,可以在PHP代码运行…

    PHP 2023年5月23日
    00
  • PHP中文乱码解决方案

    下面我将为您详细讲解 PHP 中文乱码的解决方案,步骤如下: 步骤一:设置php.ini文件 在PHP解释器的配置文件php.ini中,设置默认字符集为UTF-8,以解决中文乱码问题。 在php.ini中搜索字符编码相关设置,将以下值修改为: default_charset = "utf-8" mbstring.internal_enco…

    PHP 2023年5月26日
    00
  • PHP+Redis开发的书签案例实战详解

    PHP+Redis开发的书签案例实战详解 简介 本文将介绍如何使用PHP和Redis开发一个简单的书签应用程序。该应用程序可以存储用户的书签,以及允许用户为书签添加标签和注释。 步骤 第一步:安装Redis 在开始开发之前,需要先安装Redis。可以通过以下步骤来安装: 下载Redis安装包:可以从官方网站上下载安装包。 安装Redis:按照安装包中的指引进…

    PHP 2023年5月27日
    00
  • 深入研究PHP中的preg_replace和代码执行

    preg_replace函数简介: 首先要明确, preg_replace 函数是 PHP 中正则表达式处理函数中的一种。它的使用方法跟替换函数 str_replace 很类似,都是通过指定一个目标字符集和一个替换字符来完成字符替换的过程。但是不同的是,preg_replace函数可以使用正则表达式来识别目标字符集。 preg_replace函数的参数详解:…

    PHP 2023年5月26日
    00
  • 20个2014年最优秀的PHP框架回顾

    20个2014年最优秀的PHP框架回顾 – 完整攻略 简介 本文介绍了2014年最受欢迎的20个PHP框架,这些框架具有不同的特点和应用场景。本文将为您提供一些关于这些框架的基础知识、优点和缺点。 1. Laravel Laravel是当时最受欢迎的PHP框架之一,利用依赖注入容器和服务容器来帮助开发者构建高级应用程序。Laravel框架还提供了一系列有用的…

    PHP 2023年5月23日
    00
  • PHP的preg_match匹配字符串长度问题解决方法

    下面是详细讲解“PHP的preg_match匹配字符串长度问题解决方法”的完整攻略。 1. 背景介绍 在PHP中,我们经常需要使用正则表达式进行字符串的匹配,其中,preg_match是一个常用的函数。然而,有时候我们会遇到这样的问题:如何在使用preg_match匹配字符串时,限制字符串的最大长度? 2. 解决方法 要解决这个问题,我们可以使用一些正则表达…

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