/** * 临时日志 * @param string $type 类型 * @param string $log 日志内容 * @return void */ public static function sendTmpLog($type, $log) { if (defined('DAGGER_ALARM_TMPLOG_URL')) { BaseModelHttp::sendRequest(DAGGER_ALARM_TMPLOG_URL, array('type' => $type, 'log' => $log)); } }
/** * online debug推送到监控中心 * @return void */ public static function sendOnlineDebug() { if (1 === DAGGER_ONLINE_DEBUG && defined("DAGGER_ALARM_DEBUG_API")) { $post = array('pid' => defined('PROJECT_ID') ? PROJECT_ID : 1, 'domain' => $_SERVER['HTTP_HOST'], 'debug_msg' => json_encode(self::$onlineDebugData), 'html' => ob_get_contents(), 'request' => json_encode(apache_request_headers()), 'response' => json_encode(apache_response_headers()), 'client_ip' => BaseModelIp::getClientIp(), 'remote_addr' => $_SERVER['REMOTE_ADDR']); BaseModelHttp::sendRequest(DAGGER_ALARM_DEBUG_API, $post); } }
//__autoload函数 require PATH_ROOT . 'config/DBConfig.php'; //载入数据库配置 //==========取代global.php功能==========// $time = time(); $db = new QueueRuntimeModelDB(); $sql = "SELECT * FROM " . $db->getTableName() . " WHERE `begin_time` < ?"; $data = $db->getData($sql, array($time - 60 * 50)); if (!empty($data)) { $ndb = new ProjectModelDB(); $queueConfigDB = new QueueConfigModelDB(); foreach ($data as $v) { $row = $ndb->getRow("SELECT `id`,`key`,`name` FROM `" . $ndb->getTableName() . "` WHERE `id` = ?", array($v['project_id'])); $task = trim(array_shift(explode(' ', $v['task']))); $runTimeConfig = $queueConfigDB->getFirst("SELECT `time` FROM `" . $queueConfigDB->getTableName() . "` WHERE `project_id` = ? AND `task` = ?", array($v['project_id'], $task)); if (empty($runTimeConfig)) { $runTimeConfig = 50; } $runTime = intval(($time - $v['begin_time']) / 60); if ($runTime >= $runTimeConfig) { $message = "[{$row['name']}]的队列[{$v['task']}]于[" . date("Y-m-d H:i:s", $v['begin_time']) . "]在[{$v['ip']}]开始运行,目前已超过{$runTime}分钟!"; // 多个监控点,同一次错误只提醒一次 $mc = new MyMemcache(); $mcKey = md5($message . $row['key'] . $row['id']); if ($mc->addPlain($mcKey, 1, 50)) { BaseModelHttp::sendRequest(array('http://i.alarm.mix.sina.com.cn/alarm.php', array('pid' => $row['id'], 'key' => $row['key'], 'sys_mid' => 8, 'code' => 1, 'message' => $message, 'name' => '队列超时', 'client_ip' => '127.0.0.1'))); // BaseModelHttp::sendRequest(array('http://i.alarm.mix.sina.com.cn/alarm.php',array('pid'=>1,'key'=>'b662346b2d7da90b8413a5ee095c8ff4','sys_mid'=>8,'code'=>1,'message'=>$message,'name'=>'队列超时','client_ip'=>'127.0.0.1'))); } } } }
private static function _multi_http_exec($args) { if (!extension_loaded('curl')) { return self::_error(90400, '服务器没有安装curl扩展!'); } if (empty($args['urls']) || !is_array($args['urls'])) { return self::_error(90401, '页面抓取请求url缺失'); } $args['post'] = isset($args['post']) ? $args['post'] : array(); $args['header'] = isset($args['header']) ? $args['header'] : array(); $args['timeout'] = isset($args['timeout']) ? intval($args['timeout']) : self::DAGGER_HTTP_TIMEOUT; $args['cookie'] = isset($args['cookie']) ? $args['cookie'] : ''; $args['redo'] = isset($args['redo']) ? $args['redo'] : self::DAGGER_HTTP_REDO; $args['maxredirect'] = isset($args['maxredirect']) ? intval($args['maxredirect']) : null; $args['headOnly'] = isset($args['headOnly']) ? $args['headOnly'] : false; $args['callback'] = isset($args['callback']) ? $args['callback'] : null; $urls = array_filter($args['urls']); defined('DAGGER_DEBUG') && BaseModelCommon::debug($urls, 'request_multi_urls'); $ch = curl_init(); self::_set_curl_opts($ch, $args); $header = $ret = $_ch = self::$last_header_info = array(); if (self::$dagger_http_lock_times > 0) { // mc锁处理 $mcd = new BaseModelMemcached('', '', $native = true); $mc_http_false_keys = $mc_http_lock_keys = array(); foreach ($urls as $k => $urlinfo) { $url = is_array($urlinfo) ? $urlinfo['url'] : $urlinfo; $mc_http_key_suffix = md5(($pos = strpos($url, '?')) ? substr($url, 0, $pos) : $url); $mc_http_false_keys[$k] = "http_false_" . $mc_http_key_suffix; // 存放最近连续失败累计时间、次数、最后一次正确结果。 $mc_http_lock_keys[$k] = "http_lock_" . $mc_http_key_suffix; } $http_lock_values = $mcd->getMultiByKey(self::DAGGER_HTTP_MC_SERVER_KEY, array_unique($mc_http_lock_keys)); } foreach ($urls as $k => $urlinfo) { if (self::$dagger_http_lock_times > 0) { // mc锁处理 if (is_array($http_lock_values) && isset($http_lock_values[$mc_http_lock_keys[$k]])) { $url = is_array($urlinfo) ? $urlinfo['url'] : $urlinfo; if (defined('DAGGER_DEBUG')) { BaseModelCommon::debug('接口[' . $url . ']在10秒内出现' . self::$dagger_http_lock_times . '次错误,锁定30秒返回false', 'request_multi_warn'); } self::_error(90403, "请求连续" . self::$dagger_http_lock_times . " 次失败[{$url}]"); self::$last_header_info[$k] = $header[$k] = $ret[$k] = false; continue; } } $_ch[$k] = curl_copy_handle($ch); if (is_array($urlinfo)) { //== multi时,不同请求的私有化参数设置 ==// self::_set_curl_opts($_ch[$k], $urlinfo, $first = false); // url curl_setopt($_ch[$k], CURLOPT_URL, $urlinfo['url']); } else { curl_setopt($_ch[$k], CURLOPT_URL, $urlinfo); } if (!isset($mh)) { $mh = curl_multi_init(); } curl_multi_add_handle($mh, $_ch[$k]); BaseModelCommon::addStatInfo('request'); } if (isset($mh)) { $startRunTime = microtime(true); do { $redoUrls = array(); do { $mrc = curl_multi_exec($mh, $active); } while ($mrc === CURLM_CALL_MULTI_PERFORM); while ($active && $mrc === CURLM_OK) { do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); if ($mhinfo = curl_multi_info_read($mh, $queue)) { $k = array_search($mhinfo['handle'], $_ch); if ($mhinfo['result'] === CURLE_OK) { $ret[$k] = curl_multi_getcontent($mhinfo['handle']); $code = curl_getinfo($mhinfo['handle'], CURLINFO_HTTP_CODE); // $chinfo = curl_getinfo($mhinfo['handle']); if (in_array($code, array(301, 302, 303, 307), true)) { $redirect[$k] = empty($redirect[$k]) ? 1 : ++$redirect[$k]; if ($redirect[$k] > $args['maxredirect']) { $msg = "redirect larger than {$maxredirect} [{$k}][{$urls[$k]['url']}]"; defined('DAGGER_DEBUG') && BaseModelCommon::debug($msg, 'request_redirect_warn'); self::_error(90406, $msg); } else { defined('DAGGER_DEBUG') && BaseModelCommon::debug("redirect times:{$redirect[$k]},url:{$urls[$k]['url']}", 'request_redirect_info'); preg_match('/Location:(.*?)\\n/i', $ret[$k], $matches); $newurl = trim($matches[1]); if ($newurl[0] === '/') { preg_match("@^([^/]+://[^/]+)/@", curl_getinfo($mhinfo['handle'], CURLINFO_EFFECTIVE_URL), $matches); $newurl = $matches[1] . $newurl; } $redoUrls[$k] = $urls[$k]; $redoUrls[$k]['url'] = $newurl; defined('DAGGER_DEBUG') && BaseModelCommon::debug("[{$k}][old]{$urls[$k]['url']}[new]{$newurl}", 'request_redirect_url'); } } else { if ($code !== 200) { $msg = "http code unnormal : [{$code}] [{$k}][{$urls[$k]['url']}]"; defined('DAGGER_DEBUG') && BaseModelCommon::debug($msg, 'request_http_warn'); self::_error(90405, $msg); } } if (strpos($ret[$k], "\r\n\r\n") !== false) { if (empty($args['callback'])) { list($header[$k], $ret[$k]) = explode("\r\n\r\n", $ret[$k], 2); self::$last_header_info[$k] = $header[$k]; // 抓取header时,解析header头 if ($args['headOnly']) { $ret[$k] = self::_parse_header($header[$k]); } } else { call_user_func($args['callback'], $k, $ret[$k]); } } else { $header[$k] = $ret[$k] = false; empty($args['callback']) || call_user_func($args['callback'], $k, $ret[$k]); } if (in_array($code, array(403, 404), true)) { $ret[$k] = false; } } else { $redo[$k] = empty($redo[$k]) ? 1 : ++$redo[$k]; if ($redo[$k] <= $args['redo']) { $redoUrls[$k] = $urls[$k]; } else { self::$last_header_info[$k] = $header[$k] = $ret[$k] = false; is_callable($args['callback']) && call_user_func($args['callback'], $k, $ret[$k]); } $curl_error = curl_error($mhinfo['handle']); defined('DAGGER_DEBUG') && BaseModelCommon::debug("[errno] {$mhinfo['result']} [error] {$curl_error}", 'request_curl_error'); self::_error(90404, "curl内部错误信息[{$mhinfo['result']}][{$urls[$k]['url']}]"); } curl_multi_remove_handle($mh, $mhinfo['handle']); curl_close($mhinfo['handle']); } } // 添加需要再次请求的句柄,包括redirect和redo if (!empty($redoUrls)) { defined('DAGGER_DEBUG') && BaseModelCommon::debug($redoUrls, 'request_redoUrl_info'); foreach ($redoUrls as $k => $urlinfo) { $_chs = curl_copy_handle($ch); curl_setopt($_chs, CURLOPT_URL, $urlinfo['url']); $_ch[$k] = $_chs; curl_multi_add_handle($mh, $_ch[$k]); BaseModelCommon::addStatInfo('request'); } } } while (!empty($redoUrls)); curl_multi_close($mh); $runTime = BaseModelCommon::addStatInfo('request', $startRunTime, 0); // mc缓存处理 if (self::$dagger_http_lock_times > 0) { foreach ($ret as $k => $_r) { if ($_r === false) { // 10秒钟内连续失败20次,30秒钟锁定,直接返回false; if (!$mcd->addByKey(self::DAGGER_HTTP_MC_SERVER_KEY, $mc_http_false_keys[$k], 1, 10)) { $falseCount = $mcd->incrementByKey(self::DAGGER_HTTP_MC_SERVER_KEY, $mc_http_false_keys[$k], 1, 1); if ($falseCount > self::$dagger_http_lock_times - 1) { $mcd->addByKey(self::DAGGER_HTTP_MC_SERVER_KEY, $mc_http_lock_keys[$k], 1, 30); } } } else { $mcd->deleteMultiByKey(self::DAGGER_HTTP_MC_SERVER_KEY, array($mc_http_false_keys[$k], $mc_http_lock_keys[$k])); } } } if (defined('DAGGER_DEBUG')) { $d = array(); foreach ($ret as $k => $v) { is_string($v) && ($len = strlen($v)) > 2000 && ($v = substr($v, 0, 2000) . '......超长(' . $len . '),截取2000字节'); $d[$k] = array($k, $urls[$k]['url'], $v); } asort($d); array_unshift($d, array('序号', '请求地址', '执行结果')); $d[] = array('', '运行时间', $runTime); BaseModelCommon::debug($d, 'request_multi_return'); } } return $ret; }
protected static function isResource($value) { $data = BaseModelHttp::header($value); if (empty($data)) { return '必须为有效资源'; } return true; }