/** * 发送Socket命令的方式与memcacheq通讯 */ private static function sendCommand($command, array $terminator, $include_term = false) { if (!is_resource(self::$_socket)) { self::$_socket = fsockopen(self::$IP[0], self::$PORT, $errno, $errstr, 10); } if (self::$_socket === null) { return false; } $response = array(); $cmd = $command . self::$EOL; fwrite(self::$_socket, $cmd); $continue_reading = true; while (!feof(self::$_socket) && $continue_reading) { $resp = trim(fgets(self::$_socket, 1024)); if (in_array($resp, $terminator)) { if ($include_term) { $response[] = $resp; } $continue_reading = false; } else { $response[] = $resp; } } return $response; }
/** * 消息队列Client Deamon程序启动 */ public static function deamonStart($paramArr) { $options = array('queueType' => 'RedisQ', 'serverName' => 'ResysQ', 'queueName' => '', 'jobName' => '', 'cnName' => '', 'function' => false, 'msgNumAtm' => 10, 'maxSleep' => 30, 'adminMail' => '', 'phpFile' => '', 'life' => 0); if (is_array($paramArr)) { $options = array_merge($options, $paramArr); } foreach ($options as $k => $v) { #下面有sql操作,防注入处理 $options[$k] = addslashes($v); } extract($options); if (!$function || !function_exists($function)) { echo "[ERROR]数据处理函数function有误!"; return false; } if (!$queueName) { echo "[ERROR]消息队列名称不可为空!"; return false; } if (!$jobName) { $jobName = $queueName; } $sleepSec = 0; $startTm = 0; $life = (int) $life; $maxSleep = (int) $maxSleep > 10 ? (int) $maxSleep : 10; if (isset($_SERVER['SERVER_ADDR'])) { $serverIp = $_SERVER['SERVER_ADDR']; #当前服务器的IP } else { $serverIp = explode(" ", $_SERVER['SSH_CONNECTION']); #当前服务器的IP $serverIp = $serverIp[2]; } $runCnt = 0; $lifeStartTm = time(); #计算生命期用 #采用始终循环的方式进行处理 while (true) { #从队列中获得数据 if ('RedisQ' == $queueType) { #判断队列的类型 $dataArr = API_Item_Queue_RedisQ::pops(array('key' => $queueName, 'serverName' => $serverName, 'num' => $msgNumAtm)); } else { $dataArr = API_Item_Queue_MemcacheQ::pops(array('key' => $queueName, 'num' => $msgNumAtm)); } if ($dataArr) { foreach ($dataArr as $d) { #执行要调用的函数 $function($d); $runCnt++; #记录处理消息的个数 } $sleepSec = 0; } else { $sleepSec = intval(($sleepSec + 2) % $maxSleep); #递增,但限制最大sleep数字,不可等待过长 if ($sleepSec == 0) { $sleepSec = 1; } sleep($sleepSec); } #定时将自动运行的存活状态记录到数据库主中,便于监控和统计 #用这种方法模拟心跳,让监控程序知道这循环还活着 $tm = time(); $mustDie = $life && $tm - $lifeStartTm > $life ? true : false; #判断生命期,是否该结束了 //每隔一定时间记录下数据 if ($tm - $startTm > 120 || $mustDie) { $db = API_Db_Eagleeye::instance(); #便于记录运行状态用 $startTm = $tm; $nowD = date("d"); $sql = "select * from eagleeye_queue_status where job_name = '{$jobName}' and queue_name = '{$queueName}' "; $info = $db->getRow($sql); if ($info) { #获得当天处理的消息数量 $todaycnt = $info['msgcnt_date'] != $nowD ? $runCnt : 'msgcnt_day + ' . $runCnt; $sql = "update eagleeye_queue_status \r\n set tm = '{$tm}',server = '{$serverIp}',func='{$function}',filepath='{$phpFile}',admin='{$adminMail}',dostop=0,\r\n msgcnt_all = msgcnt_all + {$runCnt} , msgcnt_day = {$todaycnt},msgcnt_date='{$nowD}',cnname='{$cnName}'\r\n where job_name = '{$jobName}' and queue_name = '{$queueName}' "; $db->query($sql); #判断是否要停止,这个标志在后台中设置 if ((int) $info["dostop"]) { echo "手动设置了停止"; exit; } $runCnt = 0; } else { $sql = "insert into eagleeye_queue_status(job_name,queue_name,tm,server,func,filepath,admin,msgcnt_date,cnname)\r\n values('{$jobName}','{$queueName}',{$tm},'{$serverIp}','{$function}','{$phpFile}','{$adminMail}','{$nowD}','{$cnName}') "; $db->query($sql); } } #判断生命期 if ($mustDie) { exit; #生命结束,期待crontab } } }