/** * 从存储中删除删除连不上的gateway通讯端口 * @param string $addr * @param string $errstr */ public function tryToDeleteGatewayAddress($addr, $errstr) { $key = 'GLOBAL_GATEWAY_ADDRESS'; if (!isset($this->_badGatewayAddress[$addr])) { $this->_badGatewayAddress[$addr] = 0; } // 删除连不上的端口 if ($this->_badGatewayAddress[$addr]++ > self::MAX_RETRY_COUNT) { Lock::get(); $addresses_list = Store::instance('gateway')->get($key); unset($addresses_list[$addr]); Store::instance('gateway')->set($key, $addresses_list); Lock::release(); $this->log("tcp://{$addr} " . $errstr . " del {$addr} from store", false); } }
/** * 删除当前Gateway的内部通信地址 * @param string $address * @return bool */ protected function unregisterAddress() { $address = $this->lanIp . ':' . $this->lanPort; $key = 'GLOBAL_GATEWAY_ADDRESS'; try { $store = Store::instance('gateway'); } catch (\Exception $msg) { $this->log($msg); return false; } // 为保证原子性,需要加锁 Lock::get(); $addresses_list = $store->get($key); if (empty($addresses_list)) { $addresses_list = array(); } unset($addresses_list[$address]); if (!$store->set($key, $addresses_list)) { Lock::release(); $msg = "unregisterAddress fail"; if (get_class($store) == 'Memcached') { $msg .= " reason:" . $store->getResultMessage(); } $this->log($msg); return; } Lock::release(); return true; }
/** * @param $config_name * @return mixed * @throws Exception */ protected function getStore($config_name) { return Store::instance($config_name, $this->getStoreConfig()); }
/** * @param $config_name * @return mixed * @throws Exception */ protected static function getStore($config_name) { return Store::instance($config_name, self::$store_config); }
/** * 添加到客户端列表中 * @param int $client_id * @param string $client_name */ public static function addClientToRoom($room_id, $client_id, $client_name) { $key = "ROOM_CLIENT_LIST-{$room_id}"; $store = Store::instance('room'); // 获取所有所有房间的实际在线客户端列表,以便将存储中不在线用户删除 $all_online_client_id = Gateway::getOnlineStatus(); // 存储驱动是memcached if (get_class($store) == 'Memcached') { $cas = 0; $try_count = 3; while ($try_count--) { $client_list = $store->get($key, null, $cas); if (false === $client_list) { if ($store->getResultCode() == \Memcached::RES_NOTFOUND) { $client_list = array(); } else { throw new \Exception("Memcached->get({$key}) return false and memcache errcode:" . $store->getResultCode() . " errmsg:" . $store->getResultMessage()); } } if (!isset($client_list[$client_id])) { // 将存储中不在线用户删除 if ($all_online_client_id && $client_list) { $all_online_client_id = array_flip($all_online_client_id); $client_list = array_intersect_key($client_list, $all_online_client_id); } // 添加在线客户端 $client_list[$client_id] = $client_name; // 原子添加 if ($store->getResultCode() == \Memcached::RES_NOTFOUND) { $store->add($key, $client_list); } else { $store->cas($cas, $key, $client_list); } if ($store->getResultCode() == \Memcached::RES_SUCCESS) { return $client_list; } } else { return $client_list; } } throw new \Exception("addClientToRoom({$room_id}, {$client_id}, {$client_name})->cas({$cas}, {$key}, \$client_list) fail ." . $store->getResultMessage()); } else { $handler = fopen(__FILE__, 'r'); flock($handler, LOCK_EX); $client_list = $store->get($key); if (!isset($client_list[$client_id])) { // 将存储中不在线用户删除 if ($all_online_client_id && $client_list) { $all_online_client_id = array_flip($all_online_client_id); $client_list = array_intersect_key($client_list, $all_online_client_id); } // 添加在线客户端 $client_list[$client_id] = $client_name; $ret = $store->set($key, $client_list); flock($handler, LOCK_UN); return $client_list; } flock($handler, LOCK_UN); } return $client_list; }
/** * 想某个用户网关发送命令和消息 * @param int $client_id * @param int $cmd * @param string $message * @return boolean */ protected static function sendCmdAndMessageToClient($client_id, $cmd, $message) { // 如果是发给当前用户则直接获取上下文中的地址 if ($client_id === Context::$client_id || $client_id === null) { $address = Context::$local_ip . ':' . Context::$local_port; } else { $address = Store::instance('gateway')->get('client_id-' . $client_id); if (!$address) { return false; } } $gateway_data = GatewayProtocol::$empty; $gateway_data['cmd'] = $cmd; $gateway_data['client_id'] = $client_id ? $client_id : Context::$client_id; $gateway_data['body'] = $message; return self::sendToGateway($address, $gateway_data); }
/** * 向所有gateway发送数据 * @param string $gateway_data */ protected static function sendToAllGateway($gateway_data) { // 如果有businessWorker实例,说明运行在workerman环境中,通过businessWorker中的长连接发送数据 if (self::$businessWorker) { foreach (self::$businessWorker->gatewayConnections as $gateway_connection) { $gateway_connection->send($gateway_data); } } else { $all_addresses = Store::instance('gateway')->get('GLOBAL_GATEWAY_ADDRESS'); if (!$all_addresses) { throw new \Exception('GLOBAL_GATEWAY_ADDRESS is ' . var_export($all_addresses, true)); } foreach ($all_addresses as $address) { self::sendToGateway($address, $gateway_data); } } }
/** * 删除当前Gateway的内部通信地址 * @param string $address * @return bool */ protected function unregisterAddress() { $address = $this->lanIp . ':' . $this->lanPort; $key = 'GLOBAL_GATEWAY_ADDRESS'; try { $store = Store::instance('gateway'); } catch (\Exception $msg) { $this->log($msg); return false; } // 为保证原子性,需要加锁 Lock::get(); if (!$store->hDel($key, $address)) { Lock::release(); $msg = "unregisterAddress fail"; $this->log($msg); return; } Lock::release(); return true; }
public static function getStoreInstance() { return Store::instance('gateway'); }