2011-08-22 98 views
2

我正在嘗試編寫一個包裝模擬器,它提供了一個Web API,以便用戶可以在服務器上生成仿真並收集結果。進程管理器

我最初的設計是在Apache中運行一個php模擬StartSimulation.php,它將執行模擬操作,並將結果傳輸到一個文件。但是,你不能在Apache模塊中的php中執行& exec。此外,在這個實現中有點麻煩,因爲沒有任何進程管理孤立的模擬,因此殺死它們並對它們進行計數是非常棘手的。使用標準Web服務器似乎有點困難,因爲沒有存儲正在運行的進程列表(模擬)的全局狀態。

該模擬器是用C++編寫的,但它應該儘可能少地修改。我更願意爲它編寫一個包裝器並執行模擬器並捕獲它的標準輸出並使用戶可以訪問它。

基本上,包裝應該有一個網絡訪問的API與3個命令。 1)start_simulation - 這基本上是分支模擬器的一個實例,將它的pid記錄在一個表中,並將其stdout管道傳輸到一個已知的緩衝區。包裝不應該允許模擬器超過16個實例在服務器上運行。如果成功,它會向用戶返回一個模擬代碼。否則,它會返回一個錯誤代碼。 (2)停止仿真 - 取(1)中返回的仿真代碼,並殺死相關進程。 3.)get_process - 獲取(1)中返回的模擬代碼,查找保存該進程的stdout的已知緩衝區,並將該信息返回給用戶。

我應該爲此編寫一個自定義應用程序服務器嗎?如果是這樣,是否有一個很好的包含一些入門代碼的包?

感謝 凱爾

+0

http://stackoverflow.com/questions/6915191/simple- ipc-between-c-and-python-cross-platform/6915365#6915365可能對你感興趣 – jterrace

+0

可能的重複[管理長時間運行的php腳本的最佳方法?](http://stackoverflow.com/questions/ 2212635 /最佳方式管理的,長時間運行的PHP腳本) – symcbean

回答

1

我知道這是一個老問題,但希望這將仍然證明是有益的給別人...

具有流程管理(叉/ EXEC /等待/殺/信號等。 )在通過http請求直接從Apache調用的PHP腳本中絕對不是要走的路。正如你所說,它很快就會變得很凌亂:)

我建議通過http調用的PHP腳本只是一個簡單的服務器進程的命令代理。如果PHP是你的首選語言,你可以用這種方式實現。

例如,你可以使用消息隊列如下做到這一點...

  1. 您可以創建一個用於創建一個消息隊列一個相當簡單的PHP服務器,等待 消息進來,它可以然後執行啓動或停止模擬器進程的工作

  2. 遠程用戶通過網頁表單選擇操作(開始,停止,獲取輸出)。

  3. 這將導致一個HTTP/POST請求的形式發送數據到你的PHP腳本(我做這個作爲一個AJAX調用這樣我就可以發送數據和解釋結果無需重新加載頁面)

  4. 您的服務器端的PHP腳本可以解釋的形式數據,並通過消息發送命令到PHP服務器進程

讓我們來說明這一點與一些PHP代碼。爲了簡潔起見,我保持這種微不足道和不成熟的特點。

PHP腳本(Web表單目標)

這是我們解釋我們進來的表單請求,並把它變成一個消息服務器進程

<?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()」函數。我只是潦草地寫下這個想法來說明這個想法(並且我從袖口寫下了這一點,所以它可能充滿了其他錯誤!)