php - 流程经理

标签 php c++ apache

我正在尝试围绕提供 Web API 的模拟器编写包装器,以便用户可以在服务器上生成模拟并收集结果。

我最初的设计是在 Apache 中运行一个 php 模拟 StartSimulation.php,它将 fork 并执行模拟,并将结果通过管道传输到文件中。但是,您不能在 apache 模块内的 php 中 fork & exec。此外,在这个实现中它变得有点困惑,因为没有进程管理孤立的模拟,所以杀死它们并计算它们是很棘手的。使用标准 Web 服务器似乎有点困难,因为没有全局状态来存储正在运行的进程(模拟)列表。

模拟器是用c++写的,但是尽量少修改。我更喜欢为它编写一个包装器并执行模拟器并捕获它的标准输出并使用户可以访问它。

基本上,包装器应该有一个带有 3 个命令的 Web 可访问 API。

1.) start_simulation - 它基本上派生并执行模拟器的一个实例,将其 pid 记录在表中,并将其 stdout 传输到已知缓冲区。包装器不应允许超过 16 个模拟器实例在服务器上运行。如果成功,它会向用户返回一个模拟代码。否则,它返回一个错误代码。

2.) 停止模拟 - 获取在 (1) 中返回的模拟代码,并终止相关进程。

3.) get_process - 获取在 (1) 中返回的模拟代码,查找保存该进程标准输出的已知缓冲区,并将该信息返回给用户。

我应该为此编写一个自定义应用程序服务器吗?如果是这样,是否有包含一些入门代码的不错的软件包?

谢谢 凯尔

最佳答案

我知道这是一个老问题,但希望这仍然对某些人有所帮助......

在通过 http 请求直接从 Apache 调用的 PHP 脚本中进行进程管理(fork/exec/wait/kill/signal 等)绝对不是可行的方法。正如你所说,它很快就会变得困惑 :)

我建议通过 http 调用的 PHP 脚本只是简单服务器进程的命令代理。如果 PHP 是您的首选语言,您可以通过这种方式实现。

例如,您可以按如下方式对消息队列执行此操作...

  1. 您可以创建一个相当简单的 PHP 服务器来创建一个消息队列并等待 消息进来。然后它可以完成启动或停止模拟器进程的工作

  2. 远程用户通过网页表单选择操作(启动、停止、获取输出)。

  3. 这会导致 HTTP/POST 请求将表单数据发送到您的 PHP 脚本(我将此操作作为 AJAX 调用,这样我就可以发送数据并解释结果而无需重新加载页面)

  4. 您的服务器端 PHP 脚本可以解释表单数据并通过消息向 PHP 服务器进程发送命令

让我们用一些 PHP 代码来说明这一点。为了简洁起见,我保持这种琐碎和简单。

PHP 脚本(网络表单目标)

这是我们解释传入的表单请求并将其转换为服务器进程的消息的地方

<?php
/*
 * Responses are sent as simple text strings to be interpreted by
 * the client-side JavaScript handling this AJAX call. Responses
 * starting with 'ERR:' are errors, responses starting with 'ACK:'
 * are acknowledgements. Simply check the first few characters of
 * the response in the client-side JavaScript.
 */
header('Content-Type: text/plain; charset=UTF-8);

/*
 * Here we define some message types, one per command. These should correspond
 * to the command string sent from the web form
 */
$command = array(
    'START_SIM'  => 1,
    'STOP_SIM'   => 2,
    'GET_STATUS' => 3,
    'GET_OUTOUT' => 4
);

$queue_id = 0xbeef;             /* An arbitrary message queue id */
$cmd = $_REQUEST['command'];    /* The command from the web form */

/* get simulator instance id to act upon, if specified */
if (isset($_REQUEST['id']))
    $sim_id = $_REQUEST['id'];
else
    $sim_id = '';               /* no sim id? probably a create command */

/* check the message queue exists... */
if (msg_queue_exists($queue_id) === false) {
    echo 'ERR:Message queue not found!';
    return;
}

/* open the message queue and pass the command on to the server... */
if (($qhandle = msg_get_queue($queue_id)) === false) {
    echo 'ERR:Failed to open message queue to server';
    return;
}

if (msg_send($qhandle, $command[$cmd], $sim_id) === false)
    echo 'ERR:Failed to send command';
else
    echo 'ACK:Command sent ok';
?>

PHP 服务器(在您的网络服务器上单独运行)

这是一个同样简单的服务器...

<?php
/*
 * assume the same queue id's and defines as in the
 * client code above, etc..
 */

if (($qhandle = msg_get_queue($queue_id)) === false) {
    /* emit failure message to log file etc.. */
    ...
    return;
}

while (1) {
    if (msg_receive($qhandle, 0, $msgtype, $message,
        true, 0, $rc) === false) {
            /* log error message ... */
    } else {
        /*
         * Get the client id (in case you want to send
         * a reply back to the client) and the
         * message data, which is the simulation id.
         *
         * Remember that we use the message type to
         * indicate the command being requested
         */
        $client = $message['client'];
        $sim_id = $message['msg'];
        evaluate_command($client, $msgtype, $sim_id);
    }
}
?>

显然这非常简单,没有错误检查,您需要自己编写“evaluate_command()”函数。我只是草草记下了这个来说明这个想法(我是即兴写下的,所以它可能也充满了其他错误!)

关于php - 流程经理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7150564/

相关文章:

php - 在单页表单应用程序上插入数据库

php - 为房地产 php 应用程序设计数据库,表中的列太多

c++ - 基于模板的容器的迭代器

java.io.IOException : Error detected parsing the header , 在 Java 中解压 .tgz 文件

javascript - 如何自动关闭 BootStrap 警报?

php - 为 Heroku 应用程序选择 PHP 版本

c++ - 如何运行多个源文件???需要帮助(C++代码块)

C++ 服务示例 - Unicode 转换

java - 如何使用CMD启动停止tomcat服务器?

Apache 配置,使用 HTTP 请求并返回空 200 OK