async def process_rpc_request(session: SocketSession, request: object): request = cast(RpcMessage, request) req, raw_args = request.meta, request.body if request.body else b"" req = cast(RpcRequest, req) req._args, req._kwargs = utils.pickle_loads(raw_args) try: current_server_id = Placement.instance().server_id() node = Placement.instance().find_position_in_cache( req.service_name, req.actor_id) # server_id是0, 就可以忽略掉服务器ID检查, 可以做一些特殊的任务 ignore_check_position = not req.server_id position_is_equal = ( node is not None and node.server_uid == req.server_id == current_server_id) # rpc请求方, 和自己的pd缓存一定要是一致的 # 否则就清掉自己的缓存, 然后重新查找一下定位 if position_is_equal or ignore_check_position: actor = _entity_manager.get_or_new_by_name(req.service_name, req.actor_id) if actor is None: raise RpcException.entity_not_found() actor_message_loop.run_actor_message_loop(actor) await actor_message_loop.dispatch_actor_message( actor, session, req) else: asyncio.create_task(process_rpc_request_slow(session, request)) except Exception as e: logger.error("process_rpc_request, Exception:%s, StackTrace:%s" % (e, traceback.format_exc())) await actor_message_loop._send_error_resp(session, req.request_id, e) pass
async def __call__(self, *args, **kwargs): # 这边要检测一下位置是否发生变化 # 如果位置发生变化, 可以补偿一次 for x in range(2): try: request_id = await self.__send_request(*args, **kwargs) return await _rpc_call(request_id) except RpcException as e: if e.code == RPC_ERROR_POSITION_CHANGED: Placement.instance().remove_position_cache( self.actor_type, self.actor_id) continue raise e
async def _dispatch_user_message(session: SocketSession, actor_type: str, actor_id: str, msg: object): # 这边获取到对象的位置, 然后直接把消息Push到对象Actor的MailBox里面 # 如果没找到位置, 那么先去定位, 如果不在当前服务器内, 那么帮忙转发到一下 node = Placement.instance().find_position_in_cache(actor_type, actor_id) if node is not None and node.server_uid == Placement.instance().server_id( ): actor = _entity_manager.get_or_new_by_name(actor_type, actor_id) if actor is None: raise RpcException.entity_not_found() actor_message_loop.run_actor_message_loop(actor) await actor_message_loop.dispatch_actor_message(actor, session, msg) else: asyncio.create_task( _dispatch_user_message_slow(session, actor_type, actor_id, msg))
async def patch_code(): await asyncio.sleep(3.0) placement = Placement.instance() servers = placement.get_all_servers() for server in servers: proxy = rpc_proxy.get_rpc_proxy(hotfix.IHotFix, "1", server_node=server, check_postion=False) await proxy.patch_code("print(112233)")
async def _try_update_load_loop(): impl = Placement.instance() last = 0 while True: await asyncio.sleep(10) try: v = _actor_manager.weight if last != v: logger.info("ActorWeight:%d" % v) last = v impl.set_load(last) except: pass
async def _dispatch_user_message_slow(session: SocketSession, actor_type: str, actor_id: str, msg: object): node = await Placement.instance().find_position(actor_type, actor_id) if node is not None and node.server_uid == Placement.instance().server_id( ): actor = _entity_manager.get_or_new_by_name(actor_type, actor_id) if actor is None: raise RpcException.entity_not_found() actor_message_loop.run_actor_message_loop(actor) await actor_message_loop.dispatch_actor_message(actor, session, msg) else: if node: node_session = node.session if node_session: await node_session.send_message(msg) else: logger.warning("Actor:%s/%s, cannot find position" % (actor_type, actor_id)) pass
async def _run_placement(): impl = Placement.instance() if impl is None: logger.error("Placement module not initialized") return try: await impl.register_server() except Exception as e: logger.error("register server fail, Exception:%s" % e) while True: try: await impl.placement_loop() except Exception as e: await asyncio.sleep(1.0) logger.error( "run placement fail, Exception:%s, StackTrace:%s" % (e, traceback.format_exc()) ) pass
async def process_rpc_request_slow(session: SocketSession, request: object): placement = Placement.instance() req, _ = cast(Tuple[RpcRequest, bytes], request) placement.remove_position_cache(req.service_name, req.actor_id) try: node = await placement.find_position(req.service_name, req.actor_id) if node is not None and node.server_uid == placement.server_id(): actor = _entity_manager.get_or_new_by_name(req.service_name, req.actor_id) if actor is None: raise RpcException.entity_not_found() actor_message_loop.run_actor_message_loop(actor) await actor_message_loop.dispatch_actor_message( actor, session, req) else: await actor_message_loop._send_error_resp( session, req.request_id, RpcException.position_changed()) except Exception as e: logger.error("process_rpc_request, Exception:%s, StackTrace:%s" % (e, traceback.format_exc())) await actor_message_loop._send_error_resp(session, req.request_id, e) pass
def use_pd(pd_impl: Optional[Placement] = None): if not pd_impl: pd_impl = PDPlacementImpl() Placement.set_instance(pd_impl)
async def patch_code(): await asyncio.sleep(3.0) placement = Placement.instance() servers = placement.get_all_servers() for server in servers: proxy = rpc_proxy.get_rpc_proxy(hotfix.IHotFix, "1", server_node=server, check_postion=False) await proxy.patch_code("print(112233)") PORT = 15555 placement = SelfHostedPlacement(PORT) Placement.set_instance(placement) logger.info(Placement.instance()) koala_host.init_server(globals()) koala_host.listen_rpc(PORT) koala_host.create_task(service_1()) for item in range(16): i = item koala_host.create_task(bench(i)) koala_host.create_task(patch_code()) koala_host.create_task(run_timer(1)) koala_host.create_task(qps()) koala_host.run_server()