public static async ETTask <IActorResponse> Call(
            this ActorMessageSenderComponent self,
            long actorId,
            int rpcId,
            MemoryStream memoryStream,
            bool needException = true
            )
        {
            if (actorId == 0)
            {
                throw new Exception($"actor id is 0: {memoryStream.ToActorMessage()}");
            }

            var tcs = ETTask <IActorResponse> .Create(true);

            self.requestCallback.Add(rpcId, new ActorMessageSender(actorId, memoryStream, tcs, needException));

            self.Send(actorId, memoryStream);

            long           beginTime = TimeHelper.ServerFrameTime();
            IActorResponse response  = await tcs;
            long           endTime   = TimeHelper.ServerFrameTime();

            long costTime = endTime - beginTime;

            if (costTime > 200)
            {
                Log.Warning("actor rpc time > 200: {0} {1}", costTime, memoryStream.ToActorMessage());
            }

            return(response);
        }
Пример #2
0
        private async Task <IActorResponse> RunInner(IActorRequest iActorRequest)
        {
            try
            {
                if (ActorId == 0)
                {
                    Log.Info($"actor send message fail, actorid: {Id}");
                    Dispose();
                    return(new ActorResponse()
                    {
                        Error = ErrorCode.ERR_ActorNotOnline
                    });
                }

                LastSendOrRecvTime = TimeHelper.CurrentLocalMilliseconds();
                IActorResponse response = await ActorMessageSenderComponent.Instance.CallWithoutException(ActorId, iActorRequest);

                switch (response.Error)
                {
                case ErrorCode.ERR_NotFoundActor:
                {
                    // 如果没找到Actor,重试
                    ++FailTimes;
                    if (FailTimes > ActorLocationSender.MaxFailTimes)
                    {
                        Log.Info($"actor send message fail, actorid: {Id}");
                        Dispose();
                        return(response);
                    }

                    // 等待0.5s再发送
                    long instanceId = InstanceId;
                    await TimerComponent.Instance.WaitAsync(500);

                    if (InstanceId != instanceId)
                    {
                        throw new RpcException(ErrorCode.ERR_ActorRemove, $"{DCETRuntime.MongoHelper.ToJson(iActorRequest)}");
                    }
                    ActorId = await LocationProxyComponent.Instance.Get(Id);

                    return(await RunInner(iActorRequest));
                }
                }

                LastSendOrRecvTime = TimeHelper.CurrentLocalMilliseconds();
                FailTimes          = 0;

                return(response);
            }
            catch (RpcException)
            {
                Dispose();
                throw;
            }
            catch (Exception e)
            {
                Dispose();
                throw new Exception($"{DCETRuntime.MongoHelper.ToJson(iActorRequest)}\n{e}");
            }
        }
Пример #3
0
        public async ETTask Handle(Entity entity, object actorMessage, Action <IActorResponse> reply)
        {
            Message msg = actorMessage as Message;

            if (msg == null)
            {
                Log.Error($"消息类型转换错误: {actorMessage.GetType().FullName} to {typeof (Message).Name}");
                return;
            }

            E e = entity as E;

            if (e == null)
            {
                Log.Error($"Actor类型转换错误: {entity.GetType().Name} to {typeof (E).Name} --{typeof (Message).Name}");
                return;
            }

            IActorResponse response = (IActorResponse)Activator.CreateInstance(GetResponseType());

            response.RpcId = msg.RpcId;
            reply.Invoke(response);

            await this.Run(e, msg);
        }
Пример #4
0
        private static async ETTask <IActorResponse> RunInner(this ActorLocationSender self, IActorRequest iActorRequest)
        {
            try
            {
                if (self.ActorId == 0)
                {
                    Log.Info($"actor send message fail, actorid: {self.Id}");
                    self.Dispose();
                    return(new ActorResponse()
                    {
                        Error = ErrorCode.ERR_ActorNotOnline
                    });
                }

                self.LastSendOrRecvTime = TimeHelper.Now();
                IActorResponse response = await ActorMessageSenderComponent.Instance.CallWithoutException(self.ActorId, iActorRequest);

                switch (response.Error)
                {
                case ErrorCode.ERR_NotFoundActor:
                {
                    // 如果没找到Actor,重试
                    ++self.FailTimes;
                    if (self.FailTimes > ActorLocationSender.MaxFailTimes)
                    {
                        Log.Info($"actor send message fail, actorid: {self.Id}");
                        self.Dispose();
                        return(response);
                    }

                    // 等待0.5s再发送
                    long instanceId = self.InstanceId;
                    await TimerComponent.Instance.WaitAsync(500);

                    if (self.InstanceId != instanceId)
                    {
                        throw new RpcException(ErrorCode.ERR_ActorRemove, $"{MongoHelper.ToJson(iActorRequest)}");
                    }
                    self.ActorId = await LocationProxyComponent.Instance.Get(self.Id);

                    return(await self.RunInner(iActorRequest));
                }
                }

                self.LastSendOrRecvTime = TimeHelper.Now();
                self.FailTimes          = 0;

                return(response);
            }
            catch (RpcException)
            {
                self.Dispose();
                throw;
            }
            catch (Exception e)
            {
                self.Dispose();
                throw new Exception($"{MongoHelper.ToJson(iActorRequest)}\n{e}");
            }
        }
        public static void Check(this ActorMessageSenderComponent self)
        {
            long timeNow = TimeHelper.ServerNow();

            foreach ((int key, ActorMessageSender value) in self.requestCallback)
            {
                // 因为是顺序发送的,所以,检测到第一个不超时的就退出
                if (timeNow < value.CreateTime + ActorMessageSenderComponent.TIMEOUT_TIME)
                {
                    break;
                }

                self.TimeoutActorMessageSenders.Add(key);
            }

            foreach (int rpcId in self.TimeoutActorMessageSenders)
            {
                ActorMessageSender actorMessageSender = self.requestCallback[rpcId];
                self.requestCallback.Remove(rpcId);
                try
                {
                    IActorResponse response = ActorHelper.CreateResponse((IActorRequest)actorMessageSender.MemoryStream.ToActorMessage(), ErrorCore.ERR_ActorTimeout);
                    Run(actorMessageSender, response);
                }
                catch (Exception e)
                {
                    Log.Error(e.ToString());
                }
            }

            self.TimeoutActorMessageSenders.Clear();
        }
Пример #6
0
        /// <summary>
        /// 处理发送消息
        /// </summary>
        /// <param name="self"></param>
        /// <param name="task"></param>
        /// <returns></returns>
        private static async Task RunTask(this ActorLocationSender self, ActorTask task)
        {
            //获得和其他服务器通讯的会话
            ActorMessageSender actorMessageSender = Game.Scene.GetComponent <ActorMessageSenderComponent>().Get(self.ActorId);
            //发送一个rpc消息
            IActorResponse response = await actorMessageSender.Call(task.ActorRequest);

            // 发送成功
            switch (response.Error)
            {
            case ErrorCode.ERR_NotFoundActor:
                // 如果没找到Actor,重试
                ++self.FailTimes;

                // 失败MaxFailTimes次则清空actor发送队列,返回失败
                if (self.FailTimes > ActorLocationSender.MaxFailTimes)
                {
                    // 失败直接删除actorproxy
                    Log.Info($"actor send message fail, actorid: {self.Id}");
                    self.RunError(response.Error);
                    self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);                           //从字典中移除这个会话通道
                    return;
                }

                // 等待0.5s再发送
                await Game.Scene.GetComponent <TimerComponent>().WaitAsync(500);

                self.ActorId = await Game.Scene.GetComponent <LocationProxyComponent>().Get(self.Id);                        //重新获得map服务器地址

                self.Address = StartConfigComponent.Instance
                               .Get(IdGenerater.GetAppIdFromId(self.ActorId))
                               .GetComponent <InnerConfig>().IPEndPoint;                         //得到IP
                self.AllowGet();
                return;

            case ErrorCode.ERR_ActorNoMailBoxComponent:
                self.RunError(response.Error);
                self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                return;

            default:                                  //发送成功
                self.LastSendTime = TimeHelper.Now(); //记录最后发送时间
                self.FailTimes    = 0;
                self.WaitingTasks.Dequeue();          //出栈

                if (task.Tcs == null)
                {
                    return;
                }

                IActorLocationResponse actorLocationResponse = response as IActorLocationResponse;
                if (actorLocationResponse == null)
                {
                    task.Tcs.SetException(new Exception($"actor location respose is not IActorLocationResponse, but is: {response.GetType().Name}"));
                }
                task.Tcs.SetResult(actorLocationResponse);                          //返回PRC消息回应
                return;
            }
        }
Пример #7
0
        private static async ETTask RunTask(this ActorLocationSender self, ActorTask task)
        {
            ActorMessageSender actorMessageSender = Game.Scene.GetComponent <ActorMessageSenderComponent>().Get(self.ActorId);
            IActorResponse     response           = await actorMessageSender.Call(task.ActorRequest);

            // 发送成功
            switch (response.Error)
            {
            case ErrorCode.ERR_NotFoundActor:
                // 如果没找到Actor,重试
                ++self.FailTimes;

                // 失败MaxFailTimes次则清空actor发送队列,返回失败
                if (self.FailTimes > ActorLocationSender.MaxFailTimes)
                {
                    // 失败直接删除actorproxy
                    Log.Info($"actor send message fail, actorid: {self.Id}");
                    self.RunError(response.Error);
                    self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                    return;
                }

                // 等待0.5s再发送
                await Game.Scene.GetComponent <TimerComponent>().WaitAsync(500);

                self.ActorId = await Game.Scene.GetComponent <LocationProxyComponent>().Get(self.Id);

                self.AllowGet();
                return;

            case ErrorCode.ERR_ActorNoMailBoxComponent:
                self.RunError(response.Error);
                self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                return;

            default:
                self.LastRecvTime = TimeHelper.Now();
                self.FailTimes    = 0;
                self.WaitingTasks.Dequeue();

                // 如果所有的发送消息都得到了返回,发送任务完成,那么删除这个ActorLocationSender,及时回收发送对象
                if (self.WaitingTasks.Count == 0)
                {
                    self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                }

                if (task.Tcs != null)
                {
                    IActorLocationResponse actorLocationResponse = response as IActorLocationResponse;
                    if (actorLocationResponse == null)
                    {
                        task.Tcs.SetException(new Exception($"actor location respose is not IActorLocationResponse, but is: {response.GetType().Name}"));
                    }
                    task.Tcs.SetResult(actorLocationResponse);
                }
                return;
            }
        }
Пример #8
0
        public static IActorResponse CreateResponse(IActorRequest iActorRequest, int error)
        {
            Type           responseType = OpcodeTypeComponent.Instance.GetResponseType(iActorRequest.GetType());
            IActorResponse response     = (IActorResponse)Activator.CreateInstance(responseType);

            response.Error = error;
            response.RpcId = iActorRequest.RpcId;
            return(response);
        }
        public void RunMessage(IActorResponse response)
        {
            ActorMessageSender actorMessageSender;

            if (!requestCallback.TryGetValue(response.RpcId, out actorMessageSender))
            {
                Log.Error($"not found rpc, maybe request timeout, response message: {StringHelper.ToString(response)}");
                return;
            }
            requestCallback.Remove(response.RpcId);

            actorMessageSender.Callback(response);
        }
Пример #10
0
        public static void RunMessage(this ActorMessageSenderComponent self, IActorResponse response)
        {
            ActorMessageSender actorMessageSender;

            if (!self.requestCallback.TryGetValue(response.RpcId, out actorMessageSender))
            {
                Log.Error($"not found rpc, maybe request timeout, response message: {StringHelper.MessageToStr(response)}");
                return;
            }
            self.requestCallback.Remove(response.RpcId);

            actorMessageSender.Callback(response);
        }
Пример #11
0
        public static void Run(ActorMessageSender self, IActorResponse response)
        {
            if (response.Error == ErrorCore.ERR_ActorTimeout)
            {
                self.Tcs.SetException(new Exception($"Rpc error: request, 注意Actor消息超时,请注意查看是否死锁或者没有reply: actorId: {self.ActorId} {self.MemoryStream.ToActorMessage()}, response: {response}"));
                return;
            }

            if (self.NeedException && ErrorCore.IsRpcNeedThrowException(response.Error))
            {
                self.Tcs.SetException(new Exception($"Rpc error: actorId: {self.ActorId} request: {self.MemoryStream.ToActorMessage()}, response: {response}"));
                return;
            }

            self.Tcs.SetResult(response);
        }
Пример #12
0
        private static async Task RunTask(this ActorLocationSender self, ActorTask task)
        {
            ActorMessageSender actorMessageSender = Game.Scene.GetComponent <ActorMessageSenderComponent>().Get(self.ActorId);
            IActorResponse     response           = await actorMessageSender.Call(task.ActorRequest);

            // 发送成功
            switch (response.Error)
            {
            case ErrorCode.ERR_NotFoundActor:
                // 如果没找到Actor,重试
                ++self.FailTimes;

                // 失败MaxFailTimes次则清空actor发送队列,返回失败
                if (self.FailTimes > ActorLocationSender.MaxFailTimes)
                {
                    // 失败直接删除actorproxy
                    Log.Info($"actor send message fail, actorid: {self.Id}");
                    self.RunError(response.Error);
                    self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                    return;
                }

                // 等待0.5s再发送
                await Game.Scene.GetComponent <TimerComponent>().WaitAsync(500);

                self.ActorId = await Game.Scene.GetComponent <LocationProxyComponent>().Get(self.Id);

                self.Address = StartConfigComponent.Instance
                               .Get(IdGenerater.GetAppIdFromId(self.ActorId))
                               .GetComponent <InnerConfig>().IPEndPoint;
                self.AllowGet();
                return;

            case ErrorCode.ERR_ActorNoMailBoxComponent:
                self.RunError(response.Error);
                self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                return;

            default:
                self.LastSendTime = TimeHelper.Now();
                self.FailTimes    = 0;
                self.WaitingTasks.Dequeue();
                task.Tcs?.SetResult(response);
                return;
            }
        }
Пример #13
0
 public static void HandleIActorResponse(ushort opcode, long actorId, IActorResponse iActorResponse)
 {
     ActorMessageSenderComponent.Instance.RunMessage(actorId, iActorResponse);
 }
Пример #14
0
        private static void FailResponse(IActorRequest iActorRequest, int error, Action <IActorResponse> reply)
        {
            IActorResponse response = ActorHelper.CreateResponse(iActorRequest, error);

            reply.Invoke(response);
        }
 public static async ETVoid HandleIActorResponse(Session session, IActorResponse iActorResponse)
 {
     ActorMessageSenderComponent.Instance.RunMessage(iActorResponse);
 }
Пример #16
0
        private static async ETTask <IActorResponse> CallInner(this ActorLocationSenderComponent self, ActorLocationSender actorLocationSender, int rpcId, MemoryStream memoryStream)
        {
            int  failTimes  = 0;
            long instanceId = actorLocationSender.InstanceId;

            actorLocationSender.LastSendOrRecvTime = TimeHelper.ServerNow();

            while (true)
            {
                if (actorLocationSender.ActorId == 0)
                {
                    actorLocationSender.ActorId = await LocationProxyComponent.Instance.Get(actorLocationSender.Id);

                    if (actorLocationSender.InstanceId != instanceId)
                    {
                        throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout2, $"{memoryStream.ToActorMessage()}");
                    }
                }

                if (actorLocationSender.ActorId == 0)
                {
                    IActorRequest iActorRequest = (IActorRequest)memoryStream.ToActorMessage();
                    return(ActorHelper.CreateResponse(iActorRequest, ErrorCore.ERR_NotFoundActor));
                }
                IActorResponse response = await ActorMessageSenderComponent.Instance.Call(actorLocationSender.ActorId, rpcId, memoryStream, false);

                if (actorLocationSender.InstanceId != instanceId)
                {
                    throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout3, $"{memoryStream.ToActorMessage()}");
                }

                switch (response.Error)
                {
                case ErrorCore.ERR_NotFoundActor:
                {
                    // 如果没找到Actor,重试
                    ++failTimes;
                    if (failTimes > 20)
                    {
                        Log.Debug($"actor send message fail, actorid: {actorLocationSender.Id}");
                        actorLocationSender.Error = ErrorCore.ERR_NotFoundActor;
                        // 这里不能删除actor,要让后面等待发送的消息也返回ERR_NotFoundActor,直到超时删除
                        return(response);
                    }

                    // 等待0.5s再发送
                    await TimerComponent.Instance.WaitAsync(500);

                    if (actorLocationSender.InstanceId != instanceId)
                    {
                        throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout4, $"{memoryStream.ToActorMessage()}");
                    }

                    actorLocationSender.ActorId = 0;
                    continue;
                }

                case ErrorCore.ERR_ActorTimeout:
                {
                    throw new RpcException(response.Error, $"{memoryStream.ToActorMessage()}");
                }
                }

                if (ErrorCore.IsRpcNeedThrowException(response.Error))
                {
                    throw new RpcException(response.Error, $"Message: {response.Message} Request: {memoryStream.ToActorMessage()}");
                }

                return(response);
            }
        }
Пример #17
0
        public static void RunMessage(this ActorMessageSenderComponent self, long actorId, IActorResponse response)
        {
            ActorMessageSender actorMessageSender;

            if (!self.requestCallback.TryGetValue(response.RpcId, out actorMessageSender))
            {
                return;
            }

            self.requestCallback.Remove(response.RpcId);

            Run(actorMessageSender, response);
        }
Пример #18
0
        private static async ETTask <IActorResponse> Run(this ActorLocationSender self, IActorRequest iActorRequest)
        {
            long instanceId = self.InstanceId;

            using (await CoroutineLockComponent.Instance.Wait(self.Id))
            {
                if (self.InstanceId != instanceId)
                {
                    throw new RpcException(ErrorCode.ERR_ActorRemove, "");
                }

                ActorMessageSender actorMessageSender = Game.Scene.GetComponent <ActorMessageSenderComponent>().Get(self.ActorId);
                try
                {
                    // ERR_NotFoundActor是需要抛异常的,但是这里不能抛
                    IActorResponse response = await actorMessageSender.CallWithoutException(iActorRequest);

                    switch (response.Error)
                    {
                    case ErrorCode.ERR_NotFoundActor:
                        // 如果没找到Actor,重试
                        ++self.FailTimes;

                        // 失败MaxFailTimes次则清空actor发送队列,返回失败
                        if (self.FailTimes > ActorLocationSender.MaxFailTimes)
                        {
                            // 失败直接删除actorproxy
                            Log.Info($"actor send message fail, actorid: {self.Id}");
                            self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                            throw new RpcException(response.Error, "");
                        }

                        // 等待0.5s再发送
                        await Game.Scene.GetComponent <TimerComponent>().WaitAsync(500);

                        if (self.InstanceId != instanceId)
                        {
                            throw new RpcException(ErrorCode.ERR_ActorRemove, "");
                        }
                        self.ActorId = await Game.Scene.GetComponent <LocationProxyComponent>().Get(self.Id);

                        IActorResponse iActorResponse = await Run(self, iActorRequest);

                        if (self.InstanceId != instanceId)
                        {
                            throw new RpcException(ErrorCode.ERR_ActorRemove, "");
                        }
                        return(iActorResponse);

                    case ErrorCode.ERR_ActorNoMailBoxComponent:
                        self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                        throw new RpcException(response.Error, "");

                    default:
                        self.LastRecvTime = TimeHelper.Now();
                        self.FailTimes    = 0;
                        break;
                    }

                    return(response);
                }
                catch (Exception)
                {
                    self.GetParent <ActorLocationSenderComponent>().Remove(self.Id);
                    throw;
                }
            }
        }