Esempio n. 1
0
 /**
  * @brief 获取一个db连接
  *
  * @param $key 选择的key
  * @param $getNew 是否生成新连接
  * @param $replace 指出是否用新生成连接覆盖保存的连接
  *
  * @return 
  */
 public function getDB($key = NULL, $getNew = false, $replace = true)
 {
     if ($this->db !== NULL && !$getNew) {
         return $this->db;
     }
     $db = new Bd_DB(Bd_Db_DBMan::$ENABLE_PROFILING);
     if (Bd_Db_DBMan::$CONN_TIMEOUT > 0) {
         $db->setConnectTimeOut(Bd_Db_DBMan::$CONN_TIMEOUT);
     }
     // 尝试的次数
     $try_count = 0;
     while (true) {
         if (count($this->validHosts) == 0 || ($index = $this->hostSelector->select($this, $key)) === false) {
             return false;
         }
         // return the same host
         if ($this->currentHostIndex === $index) {
             return $this->db;
         }
         // do connect
         $host = $this->allHosts[$index];
         $ret = $db->connect($host[0], $this->userConf['uname'], $this->userConf['passwd'], $this->dbname, $host[1], Bd_Db_DBMan::$CONN_FLAGS);
         // got it
         if ($ret) {
             break;
         }
         // record failed host
         $this->_recordFailedHost($index);
         // try count exceeded
         if (++$try_count == Bd_Db_DBMan::$MAX_TRY_COUNT) {
             return false;
         }
     }
     if ($this->db == NULL || $replace) {
         $this->currentHostIndex = $index;
         $this->db = $db;
     }
     return $db;
 }
Esempio n. 2
0
 /**
  * @brief 获取db对象
  *
  * @param $clusterName 集群名称
  * @param $key 负载均衡key
  * @param $getNew 是否重新连接
  *
  * @return 
  */
 public static function getConn($clusterName, $key = NULL, $getNew = false)
 {
     $hookBeforeInit = Bd_Conf::getConf('/db/hook_before_init');
     if ($hookBeforeInit === false) {
         //cannot find hookBeforeInit in conf file
         self::$_error['errno'] = LOAD_CONF_ERROR;
         self::$_error['error'] = 'Can not read hookBeforeInit, please check db/global.conf';
         Bd_Log::warning(self::$_error['error'], self::$_error['errno']);
         return false;
     }
     if ($hookBeforeInit != NULL) {
         //user sets hookBeforeInit
         if (is_callable($hookBeforeInit)) {
             $clusterName = call_user_func($hookBeforeInit, $clusterName);
         } else {
             //warnning
             self::$_error['errno'] = SET_HOOK_ERROR;
             self::$_error['error'] = 'Hook(beforinit):' . $before . 'is not callable';
             Bd_Log::warning(self::$_error['error'], self::$_error['errno']);
         }
     }
     $conf =& self::$_conf;
     $hosts =& self::$_hosts;
     $dbData =& self::$_dbData;
     $lastDb =& self::$_lastDb;
     //(1) alreay save a connection (2)user do not need to recreate
     if (!empty($lastDb[$clusterName]) && !$getNew) {
         Bd_Log::trace('Return an existing connection', 0, array('db_cluster' => $clusterName));
         return $lastDb[$clusterName];
     }
     if (self::_init($clusterName) === false) {
         return false;
     }
     //create a new db object
     $db = new Bd_DB(Bd_Db_ConnMgr::$ENABLE_PROFILING);
     //add hook
     if ('' !== ($before = $conf['hook_before_query'])) {
         if (!$db->addHook(Bd_Db::HK_BEFORE_QUERY, $clusterName . '-before', $before)) {
             self::$_error['errno'] = SET_HOOK_ERROR;
             self::$_error['error'] = 'Hook(befor query):' . $before . ' is not callable';
             Bd_Log::warning(self::$_error['error'], self::$_error['errno']);
         }
     }
     if ('' !== ($after = $conf['hook_after_query'])) {
         if (!$db->addHook(Bd_Db::HK_AFTER_QUERY, $clusterName . '-after', $after)) {
             self::$_error['errno'] = SET_HOOK_ERROR;
             self::$_error['error'] = 'Hook(after query):' . $after . ' is not callable';
             Bd_Log::warning(self::$_error['error'], self::$_error['errno']);
         }
     }
     if ('' !== ($onFail = $conf['hook_on_fail'])) {
         if (!$db->onFail($onFail)) {
             self::$_error['errno'] = SET_HOOK_ERROR;
             self::$_error['error'] = 'Hook(on fail):' . $onFail . ' is not callable';
             Bd_Log::warning(self::$_error['error'], self::$_error['errno']);
         }
     }
     //try to connect host until there is not host or connecting successfully
     while (true) {
         //balancer could not select a valid host to connect
         if (count($hosts['valid_hosts']) === 0 || ($index = $dbData['host_selector']->select($hosts, $key)) === false) {
             self::$_error['errno'] = ALL_CONNECT_ERROR;
             self::$_error['error'] = 'No host could be connected in the cluster';
             Bd_Log::warning(self::$_error['error'], self::$_error['errno'], array('db_cluster' => $clusterName));
             $hookOnConnFail = $conf['hook_on_connect_fail'];
             if ($hookOnConnFail != NULL) {
                 if (is_callable($hookOnConnFail)) {
                     call_user_func($hookOnConnFail);
                 } else {
                     //warnning
                     self::$_error['errno'] = SET_HOOK_ERROR;
                     self::$_error['error'] = 'Hook(on connect fail):' . $hookOnConnFail . 'is not callable';
                     Bd_Log::warning(self::$_error['error'], self::$_error['errno']);
                 }
             }
             return false;
         }
         //log parameters
         $logPara = array('db_cluster' => $clusterName, 'db_host' => $hosts['valid_hosts'][$index]['ip'], 'db_port' => $hosts['valid_hosts'][$index]['port'], 'default_db' => $conf['default_db']);
         for ($i = 1; $i <= $conf['retry_times']; $i++) {
             $timeout = $conf['connect_timeout_s'];
             if ($timeout > 0) {
                 $db->setConnectTimeOut($timeout);
             }
             $r_timeout = $conf['read_timeout_s'];
             if ($r_timeout > 0) {
                 $db->setOption(MYSQL_OPT_READ_TIMEOUT, $r_timeout);
             }
             $w_timeout = $conf['write_timeout_s'];
             if ($w_timeout > 0) {
                 $db->setOption(MYSQL_OPT_WRITE_TIMEOUT, $w_timeout);
             }
             Bd_Log::debug("retry times: {$i}");
             $start = microtime(true) * 1000;
             //connect
             $ret = $db->connect($hosts['valid_hosts'][$index]['ip'], $conf['username'], $conf['password'], $conf['default_db'], $hosts['valid_hosts'][$index]['port'], $conf['connect_flag']);
             $end = microtime(true) * 1000;
             if ($ret) {
                 if (empty($conf['charset']) || $db->charset($conf['charset'])) {
                     $logPara['time_ms'] = $end - $start;
                     Bd_Log::trace('Connect to Mysql successfully', 0, $logPara);
                     $lastDb[$clusterName] = $db;
                     return $lastDb[$clusterName];
                 } else {
                     Bd_Log::debug('Set charset failed');
                 }
             }
         }
         //connect failed
         self::$_error['errno'] = CONNECT_ERROR;
         self::$_error['error'] = 'Connect to Mysql failed';
         Bd_Log::warning(self::$_error['error'], self::$_error['errno'], $logPara);
         self::_recordFailedHost($index);
     }
     return false;
 }