async def update_remote_rpc_config(self): """ 更新远程rpc连接 :param server_type: int, 待更新的服务节点类型 :param addr_info: dict, {host: port1, host2: port2, ...} :return: """ for server_type, addr_info in GlobalObject().remote_ports.items(): remote_names = [ RpcConnectionManager.gen_node_name(k, v) for k, v in addr_info.items() ] for r in RpcConnectionManager().conns.keys(): if r not in remote_names: if RpcConnectionManager( ).conns[r]["status"] == ConnectionStatus.ESTABLISHED: RpcConnectionManager( ).conns[r]["conn"].transport.close() RpcConnectionManager().conns.pop(r) for k, v in addr_info.items(): name = RpcConnectionManager.gen_node_name(k, v) if name not in RpcConnectionManager().conns.keys() \ or RpcConnectionManager().conns[name]["status"] != ConnectionStatus.ESTABLISHED: RpcConnectionManager().add_type_node(server_type, k, v) RpcConnectionManager().store_connection(k, v, None) try: await self.loop.create_connection(RpcPushProtocol, host=k, port=v) logger.info("success connect to {}:{}".format(k, v)) except ConnectionRefusedError as e: logger.error("try connect to {}:{} failed!")
def config(self, config): """ :param config: :return: """ host = config.get("host") self.host = host ws_port = config.get("websocket", {}).get("port", 0) # web_socket port web_port = config.get("http", {}).get("port", 0) # web httpserver port rpc_port = config.get("rpc", {}).get("port", 0) # rpcserver port remote_ports = config.get("remote_ports", []) # remote_ports list if "mongo" == config.get("available_way", "local") and config.get( "mongo_uri", ""): # 如果高可用使用的是MongoDB存储配置方式 remote_ports = AvailServerConfig.get_instance( uri=config.get("mongo_uri")) GlobalObject().update_remote_ports(remote_ports) api_path = config.get("api_path", "") if api_path: __import__(api_path) GlobalObject().loop = self.loop GlobalObject().init_from_config(config) if ws_port and self.socket_handler: # websocketserver port start GlobalObject().ws_server = self.loop.run_until_complete( websockets.serve(self.socket_handler, self.host, ws_port, create_protocol=WebSocketProtocol)) if web_port and self.web_handler: # web httpserver port start GlobalObject().http_server = self.loop.run_until_complete( self.start_web(web_port)) if rpc_port: GlobalObject().rpc_server = self.loop.run_until_complete( self.loop.create_server(RpcProtocol, self.host, rpc_port)) if remote_ports: for rp in remote_ports: host = rp.get("host", "") port = rp.get("port", 0) s_type = NodeType.get_type(rp.get('type')) if host and port: RpcConnectionManager().add_type_node(s_type, host, port) RpcConnectionManager().store_connection(host, port, None) if not RpcConnectionManager().get_connection(host, port): remote_serv = self.loop.create_connection( RpcPushProtocol, host=host, port=port) try: self.loop.run_until_complete(remote_serv) except ConnectionRefusedError: logger.debug("config all conns:{}".format( RpcConnectionManager().conns)) logger.info("connecting to {}:{} failed!".format( host, port))
def connection_made(self, transport): self.transport = transport address = transport.get_extra_info('peername') self.host, self.port = address RpcConnectionManager().store_connection(*address, self, status=ConnectionStatus.ESTABLISHED) logger.debug( 'connected to {} port {}'.format(*address) )
def find_available_node(next_node_type, to=None): """ 寻找一个可用的节点,如果没有,则异步等待直到找到为止 :param next_node_type: :param to: string, node name :return: connect node object id """ logger.debug("find_available_node:{}".format( [next_node_type, to, RpcConnectionManager().conns])) while True: if to and to in RpcConnectionManager().conns.keys() and ConnectionStatus.ESTABLISHED == \ RpcConnectionManager().conns[to]["status"]: # 如果明确传输的目标,且和目标节点有直接可用的rpc连接,则直接通过该连接发送消息; next_node = to else: if not next_node_type or NodeType.ROUTE == next_node_type: # 选取一个可用的route节点 next_node = RpcConnectionManager().get_available_connection( NodeType.ROUTE) else: next_node = RpcConnectionManager().get_available_connection( next_node_type) if not next_node: # 如果没有可用的next_node_type类型对应的节点, 则转发往路由节点 next_node = RpcConnectionManager( ).get_available_connection(NodeType.ROUTE) if not next_node: logger.error("all route node dead!!!") # print("eeeeeeeee:", next_node_type, to, next_node) raise Exception() time.sleep(1) continue return next_node
async def schedule(self): # 定时rpc断线重连 while True: await asyncio.sleep(3) # logger.info("start new schedule task~") # print("schedule:", RpcConnectionManager().type_dict, RpcConnectionManager().conns) for node_type, name_lst in RpcConnectionManager().type_dict.items( ): for name in name_lst: if name not in RpcConnectionManager().conns.keys()\ or ConnectionStatus.ESTABLISHED != RpcConnectionManager().conns[name]["status"]: host = RpcConnectionManager().conns[name]["host"] port = RpcConnectionManager().conns[name]["port"] try: logger.debug("try to reconnect:{}".format( [name, host, port])) await self.loop.create_connection(RpcPushProtocol, host=host, port=port) logger.info("success connect to {}:{}".format( host, port)) except ConnectionRefusedError as e: logger.error( "schedule try connect to {}:{} failed!")
def connnection_lost(self, exc): logger.debug('server closed connection') RpcConnectionManager().lost_connection(self.host, self.port) super(RpcPushProtocol, self).connection_lost(exc)
def eof_received(self): logger.debug('rpc_push received EOF') if self.transport and self.transport.can_write_eof(): self.transport.write_eof() RpcConnectionManager().lost_connection(self.host, self.port)
async def send_message(self, remote_name, message): if remote_name not in RpcConnectionManager().conns.keys(): return await RpcConnectionManager().send_message(remote_name, message)