以下程序使用的是 windows 版,我正在測試 linux 版。
今天寫了一個程序,程序要求客戶端執(zhí)行服務(wù)端的shell,有的是常規(guī)的shell,有的是shell監(jiān)聽的任務(wù)。
我把兩個任務(wù)作為如下示例:
ping www.baidu.com
ping www.sina.com -t
baidu作為一個短期的shell命令,sina作為一個長期監(jiān)視的shell命令。
在執(zhí)行中發(fā)現(xiàn):
1.如果瀏覽器執(zhí)行 sina 中,瀏覽器關(guān)閉了,那么服務(wù)端仍然在執(zhí)行,不會關(guān)閉當(dāng)前任務(wù);
如果 baidu 未執(zhí)行完畢時,執(zhí)行了 sina,那么瀏覽器會在 baidu 執(zhí)行完畢時執(zhí)行 sina
如果先執(zhí)行 sina,然后再執(zhí)行 baidu,那么返回的消息一直屬于 sina,baidu 沒有返回
$worker->onMessage = function ($connection, $data) {
if (($connection->handle = popen($data, 'r'))) {
$connection->send('----- Task Start -----');
while (!feof($connection->handle)) {
$str = fread($connection->handle, 1024);
echo $str, "\n";
$connection->send($str);
}
$connection->send('----- Task End -----');
$connection->close();
}
};
$worker->onClose = function ($connection) {
fclose($connection->handle);
};
前端代碼:
<script>
function execWebSocket(task){
var ws = new WebSocket("ws://127.0.0.1:2345");
ws.onopen = function() {
console.log("----- WebSocket Start -----");
ws.send(task);
};
ws.onmessage = function(msg) {
console.log(msg.data);
};
ws.onclose = function() {
console.log("----- WebSocket End -----");
};
return ws;
}
//execWebSocket("ping www.baidu.com");
//execWebSocket("ping www.sina.com -t");
</script>
這里的前端我采用執(zhí)行一個shell,打開關(guān)閉一次鏈接的模式,這是使用所有的命令始終使用一個 WebSocket 對象好,還是像我這樣,一個shell創(chuàng)建一次WebSocket好。
希望大神指點一下方向。
經(jīng)過測試 linux 可以支持多個任務(wù)并行執(zhí)行。
但是仍然存在客戶端關(guān)閉,服務(wù)端仍在執(zhí)行的情況。
執(zhí)行ping sina時,while (!feof($connection->handle))一直成立的,所以程序一直在while里死循環(huán),導(dǎo)致workerman無法得到程序控制權(quán),即使客戶端斷開鏈接,workerman無法運行到onClose。
假如我一臺服務(wù)器開了 10 個進程,有20個客戶,每個客戶執(zhí)行一個 sina (監(jiān)視任務(wù)),那么是不是我只有10個客戶能執(zhí)行成功 sina (監(jiān)視任務(wù)),其他的客戶都會在等待狀態(tài),同時所有客戶的baidu (短耗時)任務(wù)也沒法執(zhí)行
假如我一臺服務(wù)器開了 10 個進程,有20個客戶,每個客戶執(zhí)行一個 sina (監(jiān)視任務(wù)),那么是不是我只有10個客戶能執(zhí)行成功 sina (監(jiān)視任務(wù)),其他的客戶都會在等待狀態(tài),同時所有客戶的baidu (短耗時)任務(wù)也沒法執(zhí)行
我的這個需求是需要監(jiān)視一個目錄的文件變化然后復(fù)制到其他目錄中去,同時還有一個直接復(fù)制的命令 (類似于這樣),請問有什么建議嗎?假如有20個客戶監(jiān)視20個目錄的情況下 (當(dāng)然不是php監(jiān)視,而是一個其他 shell 程序)。
經(jīng)過測試,客戶的每個短耗時執(zhí)行時常(shell)需要5秒,長監(jiān)視任務(wù)(shell)為一直執(zhí)行,不過只有文件改變觸發(fā)才會返回數(shù)據(jù),有一臺 32 線程,64G內(nèi)存的服務(wù)器 (局域網(wǎng)),如果公司 100 個員工的話,這臺服務(wù)器是否可以支撐,同時對代碼上您有什么優(yōu)化建議嗎?
你可以看下這個demo
http://m.wtbis.cn/workerman-vmstat
關(guān)鍵代碼如下
// 進程啟動時,開啟一個vmstat進程,并廣播vmstat進程的輸出給所有瀏覽器客戶端
$worker->onWorkerStart = function($worker)
{
// 把進程句柄存儲起來,在進程關(guān)閉的時候關(guān)閉句柄
$worker->process_handle = popen('vmstat 1', 'r');
if($worker->process_handle)
{
$process_connection = new TcpConnection($worker->process_handle);
$process_connection->onMessage = function($process_connection, $data)use($worker)
{
foreach($worker->connections as $connection)
{
$connection->send($data);
}
};
}
else
{
echo "vmstat 1 fail\n";
}
};
另外php也可以用inotify擴展監(jiān)聽操作系統(tǒng)磁盤目錄文件訪問修改
參考 https://github.com/walkor/workerman-filemonitor-inotify
以上都是利用異步IO做的,支撐幾萬客戶端都沒事