这是一个设计问题,我感谢您的见解/建议。我理解这个问题根据经验可能有不同的答案,我只是在选择如何进行之前寻求一些指导。
背景 - 我的应用程序主要基于LAMP堆栈 - Linux,Apache,MySQL和PHP。我还使用jQuery来进行客户端脚本编写,应用程序非常简单并且执行速度非常快。我也在使用CakePHP框架
场景#1 -
问题 -
情景2
ignore_user_abort
,因此即使用户退出也会执行。问题
感谢您的建议和见解
答案 0 :(得分:1)
简短的回答是
情景#1
所有/大多数语言是同步的,即表示运行ajax是异步的,并且通过ajax运行php的扩展是异步的。事情就是在这里你很困惑"同步"在这种情况下,它意味着阻止直到操作完成或进程阻塞,并行处理或甚至多线程。
再次多线程与并行处理完全不同,php完全能够运行几十个并行进程。它是最好的语言,可能不是,但它可以用尽可能少的工作来运行带有exec的shell脚本和linux上的这个exec(usr/bin/php -f pathtophpfile/index.php arg1 > /dev/null & );
命令。多线程的定义如下:
多线程是程序或操作系统进程的能力 一次管理多个用户的使用,甚至管理 同一用户的多个请求,而不必具有多个 计算机中运行的程序的副本
并行处理定义为此
并行处理是同时使用多个CPU或 处理器核心来执行程序或多个计算线程。
因此,虽然技术上php无法执行其中任何一项操作,但您可以在同一台计算机上同时运行多个php副本,就像您可以手动打开多个shell窗口并在每个shell中运行命令一样。是并行处理还是多线程?不,它只是同时运行多个PHP副本。
但任何"多线程或并行处理"是竞争条件。如果你小心避免它们,你会没事的。比赛条件就像这样
现在您将丢失process2所做的任何更改,因为process1将数据存储在内存中,并且从不考虑process2更改它。这也是我所谓的并发问题,它们基本上是一回事。如果使用CRON或其他一些基本的排队方法,另一件需要注意的事情就是不要用多个进程来完成同样的工作。
同样调试可能是一个挑战,任何后台进程都是如此,而不是特定于php。最简单的方法是使用文件将输出记录为ob_start()
& $var = ob_get_clean()
(输出缓冲)并录制。使用关闭处理程序记录错误(例如
http://php.net/manual/en/function.register-shutdown-function.php
当然,这些都是简化的例子,解释,但这是它的要点。
情景#2
怎么会这样?正如我所提到的,php和Apache可以同时为超过200个客户端提供服务,另一个请求只是与Apache的另一个连接(当使用ajax或CURL时),但即使只使用CLI(命令行界面)它也基本相同。没有固有的原因你不能同时运行几十个php进程。
如何排队,他们只需再次执行,就像在浏览器中选择多个标签一样。至于超时,无论您使用何种语言,服务器上始终都有资源限制。您可以使用排队系统来确保在给定时间只处理少量文件,这可以像cron一样简单,也可以是具有某些状态列的数据库表,例如排队,运行,完成。然后cron脚本运行一个标记为排队的作业,在运行时将其标记为正在运行,标记完成后完成,冲洗并重复。
这是一个意见问题,更多的是你对这些语言的能力问题。
我实际上是在php中构建一个系统,它接受一个csv文件并将其分成25000个行块(不重写单独的文件,只读取多个线程的同一文件中的偏移量)。然后由最多10名工作人员并行处理这些块,然后将它们聚合在一起,然后生成一些报告和电子邮件等。这样做很容易,不。有可能,肯定是。
我正在构建的系统例如采用一个100万行+的文件,并查询超过700k记录的数据库。它有点像这样
作业预处理(一个进程创建多个块)
进程(多个进程分别处理一个或多个块)
聚合(仅一个进程,接收作业的位)
这里的技巧是多个处理部分(步骤2)在步骤1中没有触及该作业文件(或者它将遇到竞争条件),此外只有一个进程接收作业的所有块。一旦收到所有的块,我们将它们压缩成一个文件做一些清理,然后发送电子邮件等。
有了这个,我在2分钟内运行了一个包含100万行的文件。使用单个线程/进程运行相同的文件大约需要15分钟。
所以(再次)我向你保证它可以做到,它很棘手,你必须非常小心你如何移动你的数据,但在php中做这些事情并非不可能。 PHP和现代硬件可以一秒钟处理数千个操作。通常瓶颈在数据库中索引不好或等待网络连接等......
如果你打算做一些真正重要的工作,我建议你像我一样(RabbitMq)调查排队或消息系统,但这可能在你的情况下有点过分。我使用排队系统来帮助保持流程清晰,避免竞争条件,基本上我唯一的目的就是组织数据流。
答案 1 :(得分:1)
在前端使用线程没有意义。如上所述,您的Web服务器具有已定义的处理模型,它旨在与该模型一起扩展,创建用户线程,因为Web请求会中断该模型。即使用户代码创建了合理数量的线程,例如8,如果同时出现100个客户端,您将要求硬件同时执行800个线程。
这显然是一个坏主意!
在两种情况下,您似乎遇到的问题基本相同。
不要做任何比它必须更复杂的事情;在这两种情况下,问题是你的接收服务器端代码的响应速度比想要的慢。
如果您有许多HTTP请求要处理请求,您的代码是I / O绑定的,不要直接进行多处理或多线程,请尝试非阻塞I / O首先,这更简单,更易于访问,更适合用PHP扩展。
例如,在您拥有受CPU限制的代码的情况下,您已解决了I / O问题,并且正在使用非阻塞I / O发出所有请求,但是一旦下载了数据,就需要相当多的要使用的处理。然后您可能会考虑使用多个进程或线程。
无论发生什么,你都不应该在前端使用多线程,你要做的就是隔离那些需要多线程的应用程序部分,并使用一些理智的RPC与这个孤立的子应用程序进行通信。 / p>