如何在PHP/Windows中通知用户异步任务结束
考虑下图: 思想如何在PHP/Windows中通知用户异步任务结束,php,windows,asynchronous,publish-subscribe,Php,Windows,Asynchronous,Publish Subscribe,考虑下图: 思想 用户可以执行单个文件/批上传(我知道HTTP规范),批是指某人可以一次发送多个文件 图像上传服务旨在为每个发送的文件创建一个子进程(图像处理器) 问题 那么,什么样的客户机-服务器通信方法最适合将这些子进程的通知发送回客户机 创建子进程的最佳方法是什么?我读过关于proc\u open,curl方法的书。我不知道如何使用消息队列(如果它适用的话) 注释 我要说的是,我正在ASP.NET中使用Windows操作系统(Windows Server 2008)和XAMPP,这是很容
proc\u open
,curl
方法的书。我不知道如何使用消息队列(如果它适用的话)我要说的是,我正在ASP.NET中使用Windows操作系统(
Windows Server 2008
)和XAMPP
,这是很容易做到的。下面是一个在ASP.NET中实现的示例
但是,由于您希望在PHP/windows中完成,因此可以通过几种方法来完成
为什么不能让imageprocessing在完成后更新数据库表或会话中的某些字段,并从HTML页面保留一个javascript计时器,用于轮询数据库/会话变量的可能状态?一旦从db/session(由图像处理逻辑更新)获得完成状态,javascript计时器可以采取进一步的操作吗
希望这有帮助。为了在文件上传过程中实现正确的客户机-服务器通信,我们通常在jQuery中使用AJAX(异步JS)。 发送任何需要的数据,在您的情况下,这些数据将是文件详细信息。在服务器(PHP)上执行操作,完成后将json响应发送回客户机以进行通知。 关键是,您需要在AJAX的success函数中获得子进程的响应。只有在成功完成后,通知才会到达。您可以查看 它已经有了和libs
因为并非所有浏览器都支持套接字,所以您应该小心使用它,或者为旧浏览器提供任何备用功能用户上载图像。完成此步骤后,可以创建任务。一个Taks是数据库中任务表中的一行
class Task
{
const STATUS_PENDING = 'pending'
const STATUS_ERROR = 'error'
const STATUS_FINISHED = 'finished'
private $userid;
private $taskData = array();
public function run()
{
// create process
}
public function update()
{
// update the status an other changes you need to the database
// or any other storage you use.
}
public function getStatus();
}
class TaskManager
{
const MAX_TASKS = 5;
private $tasks = array();
public function addTaks();
public function start()
{
foreach ($tasks as $task) {
$task->run();
}
}
}
在服务器端,您必须考虑如何工作/组织任务。这取决于你的需要。借助TaskManager的强大功能,您可以
控制你的过程。这是非常重要的,不是100个进程并行运行
客户端现在可以使用userid轻松地请求任务表检查挂起的任务。如果状态为“已完成”或“错误”,则可以向用户提供
非常好的反馈。您可以每五秒钟轮询一次此信息。间隔时间取决于你的需要。5秒以下的投票对于您的客户来说可能是很奇怪的
浏览器最好由客户机获取状态,而不是由服务器将状态发送给客户机。如果服务器发送您必须使用web套接字的状态很重要。后端可以相同
下面是一个简单的轮询示例
setInterval(function(){
$.ajax({ url: "server", success: function(data){
//Update your dashboard gauge
salesGauge.setValue(data.value);
}, dataType: "json"});
}, 30000);
class Task
{
private $process = null;
private $pipes = array();
private $status = 'pending'
public function run()
{
$descriptor = array (
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$cmd = "/path/to/progam --with --some-arguments"
$this->process = proc_open($command, $descriptor, $this->pipes);
stream_set_blocking($this->pipes[1], 0);
}
public function close()
{
foreach($this->pipes as $pipe) {
fclose($pipe);
}
$exitStatus = proc_close($this->process);
$this->process = NULL;
return $exitStatus;
}
}
只有当您有一些高级选项时,proc_open才是好的。使用proc\u open
(注意管道)的功能,并结合流设置阻塞。
您可以编写异步任务处理。如果您不需要一些特殊的exec
就足够了
下面是一个非阻塞示例
setInterval(function(){
$.ajax({ url: "server", success: function(data){
//Update your dashboard gauge
salesGauge.setValue(data.value);
}, dataType: "json"});
}, 30000);
class Task
{
private $process = null;
private $pipes = array();
private $status = 'pending'
public function run()
{
$descriptor = array (
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$cmd = "/path/to/progam --with --some-arguments"
$this->process = proc_open($command, $descriptor, $this->pipes);
stream_set_blocking($this->pipes[1], 0);
}
public function close()
{
foreach($this->pipes as $pipe) {
fclose($pipe);
}
$exitStatus = proc_close($this->process);
$this->process = NULL;
return $exitStatus;
}
}
我希望这会给你一些灵感来解决你的问题。
对于真正的消息队列,您可以使用您想要的。我是一个粉丝,现在我将停止讨论解决方案和想法,因为这个问题
更复杂,我可以再写100页。如果你有问题,你可以写一行 最好的方法是利用消息队列,例如ActiveMQ、RabbitMQ等。然后将执行以下步骤:
是的,谢谢,我一直在考虑实施某种形式的长轮询过程。关于发布/订阅模式或消息队列,您能说些什么?你试过了吗?我看过一些关于如何在*nix系统上使用PHP的文章。也许是使用?