public function testAllInOne() { // ²âÊÔ´òÓ¡µ½ÆÁÄ» BigpipeLog::debug('[%s:%u][%s][debug]', __FILE__, __LINE__, __FUNCTION__); BigpipeLog::trace('[%s:%u][%s][trace]', __FILE__, __LINE__, __FUNCTION__); BigpipeLog::notice('[%s:%u][%s][notice]', __FILE__, __LINE__, __FUNCTION__); BigpipeLog::monitor('[%s:%u][%s][monitor]', __FILE__, __LINE__, __FUNCTION__); BigpipeLog::warning('[%s:%u][%s][warning]', __FILE__, __LINE__, __FUNCTION__); BigpipeLog::fatal('[%s:%u][%s][fatal]', __FILE__, __LINE__, __FUNCTION__); // ²âÊÔ²»Êä³ö´òÓ¡ÐÅÏ¢log configure $conf = new BigpipeLogConf(); $conf->severity = BigpipeLogSeverity::FATAL; $conf->disable_ostream = true; $fatal_log = sprintf('[%s:%u][%s][fatal message]', __FILE__, __LINE__, __FUNCTION__); $warning_Log = sprintf('[%s:%u][%s][warning]', __FILE__, __LINE__, __FUNCTION__); $this->assertTrue(BigpipeLog::init($conf)); BigpipeLog::fatal('%s', $fatal_log); $msg = BigpipeLog::get_last_error_message(); BigpipeLog::warning('%s', $warning_Log); $this->assertEquals($msg, BigpipeLog::get_last_error_message()); $new_fatal_log = sprintf('[%s:%u][%s][fatal new message]', __FILE__, __LINE__, __FUNCTION__); $this->assertTrue($msg == BigpipeLog::get_last_error_message()); // ²âÊÔclose BigpipeLog::close(); }
/** * 从传入的configure array读取剩余配置 * @param array $conf_arr: 含meta agent配置的array * @return true on success or false on failure */ private function _load_other($conf_arr) { try { $obj = new ReflectionClass($this); foreach ($conf_arr as $key => $val) { if (true === is_array($val)) { BigpipeLog::debug('[%s:%u][%s][skip configure node][name:%s]', __FILE__, __LINE__, __FUNCTION__, $key); continue; } if (false === $obj->hasProperty($key)) { continue; } BigpipeLog::debug('[%s:%u][%s][an element is configured][key:%s][val:%s]', __FILE__, __LINE__, __FUNCTION__, $key, $val); $fld = $obj->getProperty($key); $fld->setValue($this, $val); } } catch (Exception $e) { BigpipeLog::warning('[%s:%u][%s][fail to load configure][error message:%s]', __FILE__, __LINE__, __FUNCTION__, $e->getMessage()); return false; } // todo // 根据checksum level修改check frame标志现在在publish和subscirbe中 // 以后应该移到这里 return true; }
/** * 更新meta信息, 记录重试次数 * @return boolean */ private function _failover() { if ($this->_fo_count >= $this->_max_fo_cnt) { // 重置failover BigpipeLog::fatal("[_failover][can not do more][max_cnt:%d]", $this->_max_fo_cnt); $this->_fo_sleep_time = 0; $this->_fo_count = 0; return false; } if (0 == $this->_fo_sleep_time) { // php中只有微秒级的usleep和秒级的sleep // 目前只有当start时才会进入这个分支。 // 这时我们会跳过failover $this->_fo_sleep_time = BigpipeCommonDefine::INIT_FO_SLEEP_TIME * 1000; } else { usleep($this->_fo_sleep_time); } // usleep($this->_fo_sleep_time); $this->_fo_count++; $this->_fo_sleep_time *= 2; // increase failover sleep time if ($this->_fo_sleep_time > BigpipeCommonDefine::MAX_FO_SLEEP_TIME) { // failover sleep time不能无限制增长 $this->_fo_sleep_time = BigpipeCommonDefine::MAX_FO_SLEEP_TIME; } // 通过meta跟新stripe $broker = $this->_update_meta(); if (false === $broker) { BigpipeLog::fatal("[_failover][can not update meta from meta agent]"); return false; } // 连接broker $pub_dest = array("socket_address" => $broker['ip'], "socket_port" => $broker['port'], "socket_timeout" => $this->_conn_timeo); $this->_stomp_adapter->set_destination($pub_dest); $this->_stomp_adapter->role = BStompRoleType::PUBLISHER; $this->_stomp_adapter->topic_name = $broker['stripe']; $this->_stomp_adapter->session_id = $this->_session_id; // 发布时session不变 if ($this->_stomp_adapter->connect()) { BigpipeLog::debug("[Success][connected on broker][ip:%s][port:%u]", $broker['ip'], $broker['port']); BigpipeLog::debug('[session message id][%u]', $this->_stomp_adapter->session_message_id); $this->_broker = $broker; return true; } return false; // 连接失败 }
/** * Create a connection between server and php client<p> * Or close the existing connection and re-connect it. * @param no parameter * @return true on success or false on failure. */ public function create_connection() { if ($this->is_connected()) { $this->close(); // 防止重复创建connection } $agents = $this->_destinations; $num = count($agents); if (0 == $num) { BigpipeLog::warning("[no destination]"); return false; } $try = $this->_max_try_time; $curr_agent = rand() % $num; $idx = $curr_agent; // 从curr_agent开始尝试连接meta agent while ($try-- > 0) { $agent = $agents[$idx]; // $stub_sock用于测试时传入mocked c_socket $socket = true === isset($this->unittest) ? $this->stub_sock : new c_socket(); $agent['socket_timeout'] = $this->_conn_timeo; // c_socket内部使用socket_timeout作为read/write timeout $socket->set_vars_from_array($agent); //<<< 调试信息 BigpipeLog::debug('[connect to][%s:%u]', $agent['socket_address'], $agent['socket_port']); // 连接agent if ($socket->connect($this->_conn_timeo)) { $this->_socket = $socket; $this->_target = $agent; // 记录连接对象 break; } else { // 换地址重试 if (!array_key_exists($idx + 1, $agents)) { // next idx will be out of range // reset $idx and try from the first agent $idx = 0; } else { $idx++; } } // end of connect } // end of try return $this->is_connected(); }
/** * 更新meta信息, 记录重试次数 * @return boolean */ private function _failover() { // failover时, 订阅、发布状态无效,重置状态 if (true == $this->_is_subscribed) { $this->_unsubscribe(); // 先尝试取消订阅, 但是不用考虑错误 (因为failover中有错误是常态) $this->_is_subscribed = false; } if ($this->_fo_count > $this->_max_fo_cnt) { // 重置failover BigpipeLog::fatal("[%s:%u][%s][can not do more]", __FILE__, __LINE__, __FUNCTION__); $this->_fo_sleep_time = 0; $this->_fo_count = 0; return false; } if (0 == $this->_fo_sleep_time) { // 第一次flush subscribe时,我们往往不希望等待, // 因此这时跳过sleep过程 // php中只有微秒级的usleep和秒级的sleep $this->_fo_sleep_time = BigpipeCommonDefine::INIT_FO_SLEEP_TIME * 1000; } else { usleep($this->_fo_sleep_time); } $this->_fo_count++; $this->_fo_sleep_time *= 2; // increase failover sleep time if ($this->_fo_sleep_time > BigpipeCommonDefine::MAX_FO_SLEEP_TIME) { // failover sleep time不能无限制增长 $this->_fo_sleep_time = BigpipeCommonDefine::MAX_FO_SLEEP_TIME; } // 通过meta跟新stripe if (false === $this->_update_meta()) { BigpipeLog::fatal("[%s:%u][%s][can not update meta from meta agent]", __FILE__, __LINE__, __FUNCTION__); return false; } // 随机选择并连接一个broker $is_ok = false; do { $broker = $this->_random_select_broker(); if (false === $broker) { // 无新broker可选, failover失败 BigpipeLog::fatal("[%s:%u][%s][no broker to subcribe]", __FILE__, __LINE__, __FUNCTION__); break; } // try to connect to broker $sub_dest = array("socket_address" => $broker->ip, "socket_port" => $broker->port, "socket_timeout" => $this->_conn_timeo); $this->_stomp_adapter->set_destination($sub_dest); $this->_stomp_adapter->role = BStompRoleType::SUBSCRIBER; $this->_stomp_adapter->topic_name = $this->_stripe['stripe_name']; $this->_stomp_adapter->session_id = BigpipeUtilities::get_pipelet_name($this->_pipe_name, $this->_pipelet_id) . '_' . BigpipeUtilities::get_uid(); if ($this->_stomp_adapter->connect()) { BigpipeLog::debug("[%s:%u][%s][Success][connected on broker][ip:%s][port:%u]", __FILE__, __LINE__, __FUNCTION__, $broker->ip, $broker->port); BigpipeLog::debug('[%s:%u][%s][session message id][smid:%s]', __FILE__, __LINE__, __FUNCTION__, $this->_stomp_adapter->session_message_id); $is_ok = true; break; // 跳出连接 } } while (true); return $is_ok; }