| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- using System;
- using System.Collections.Generic;
- using System.Net;
- namespace ET.Server
- {
- [EntitySystemOf(typeof(ProcessOuterSender))]
- public static partial class ProcessOuterSenderSystem
- {
- [EntitySystem]
- private static void Awake(this ProcessOuterSender self, IPEndPoint address)
- {
- switch (self.InnerProtocol)
- {
- case NetworkProtocol.TCP:
- {
- self.AService = new TService(address, ServiceType.Inner);
- break;
- }
- case NetworkProtocol.KCP:
- {
- self.AService = new KService(address, NetworkProtocol.UDP, ServiceType.Inner);
- break;
- }
- }
-
- self.AService.AcceptCallback = self.OnAccept;
- self.AService.ReadCallback = self.OnRead;
- self.AService.ErrorCallback = self.OnError;
- }
-
-
- [EntitySystem]
- private static void Update(this ProcessOuterSender self)
- {
- self.AService.Update();
- }
- [EntitySystem]
- private static void Destroy(this ProcessOuterSender self)
- {
- self.AService.Dispose();
- }
- private static void OnRead(this ProcessOuterSender self, long channelId, MemoryBuffer memoryBuffer)
- {
- Session session = self.GetChild<Session>(channelId);
- if (session == null)
- {
- return;
- }
-
- session.LastRecvTime = TimeInfo.Instance.ClientFrameTime();
- (ActorId actorId, object message) = MessageSerializeHelper.ToMessage(self.AService, memoryBuffer);
-
- if (message is IResponse response)
- {
- self.HandleIActorResponse(response);
- return;
- }
- Fiber fiber = self.Fiber();
- int fromProcess = actorId.Process;
- actorId.Process = fiber.Process;
- switch (message)
- {
- case ILocationRequest:
- case IRequest:
- {
- CallInner().Coroutine();
- break;
- async ETTask CallInner()
- {
- IRequest req = (IRequest)message;
- int rpcId = req.RpcId;
- // 注意这里都不能抛异常,因为这里只是中转消息
- IResponse res = await fiber.Root.GetComponent<ProcessInnerSender>().Call(actorId, req, false);
- // 注意这里的response会在该协程执行完之后由ProcessInnerSender dispose。
- actorId.Process = fromProcess;
- res.RpcId = rpcId;
- self.Send(actorId, res);
- ((MessageObject)res).Dispose();
- }
- }
- default:
- {
- fiber.Root.GetComponent<ProcessInnerSender>().Send(actorId, (IMessage)message);
- break;
- }
- }
- }
- private static void OnError(this ProcessOuterSender self, long channelId, int error)
- {
- Session session = self.GetChild<Session>(channelId);
- if (session == null)
- {
- return;
- }
- session.Error = error;
- session.Dispose();
- }
- // 这个channelId是由CreateAcceptChannelId生成的
- private static void OnAccept(this ProcessOuterSender self, long channelId, IPEndPoint ipEndPoint)
- {
- Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
- session.RemoteAddress = ipEndPoint;
- //session.AddComponent<SessionIdleCheckerComponent, int, int, int>(NetThreadComponent.checkInteral, NetThreadComponent.recvMaxIdleTime, NetThreadComponent.sendMaxIdleTime);
- }
- private static Session CreateInner(this ProcessOuterSender self, long channelId, IPEndPoint ipEndPoint)
- {
- Session session = self.AddChildWithId<Session, AService>(channelId, self.AService);
- session.RemoteAddress = ipEndPoint;
- self.AService.Create(channelId, session.RemoteAddress);
- //session.AddComponent<InnerPingComponent>();
- //session.AddComponent<SessionIdleCheckerComponent, int, int, int>(NetThreadComponent.checkInteral, NetThreadComponent.recvMaxIdleTime, NetThreadComponent.sendMaxIdleTime);
- return session;
- }
- // 内网actor session,channelId是进程号
- private static Session Get(this ProcessOuterSender self, long channelId)
- {
- Session session = self.GetChild<Session>(channelId);
- if (session != null)
- {
- return session;
- }
- IPEndPoint ipEndPoint = StartProcessConfigCategory.Instance.Get((int) channelId).IPEndPoint;
- session = self.CreateInner(channelId, ipEndPoint);
- return session;
- }
- private static void HandleIActorResponse(this ProcessOuterSender self, IResponse response)
- {
- if (!self.requestCallback.Remove(response.RpcId, out MessageSenderStruct actorMessageSender))
- {
- return;
- }
- Run(actorMessageSender, response);
- }
- private static void Run(MessageSenderStruct self, IResponse response)
- {
- if (response.Error == ErrorCore.ERR_MessageTimeout)
- {
- self.SetException(new RpcException(response.Error, $"Rpc error: request, 注意Actor消息超时,请注意查看是否死锁或者没有reply: actorId: {self.ActorId} {self.RequestType.FullName}, response: {response}"));
- return;
- }
- if (self.NeedException && ErrorCore.IsRpcNeedThrowException(response.Error))
- {
- self.SetException(new RpcException(response.Error, $"Rpc error: actorId: {self.ActorId} request: {self.RequestType.FullName}, response: {response}"));
- return;
- }
- self.SetResult(response);
- }
- public static void Send(this ProcessOuterSender self, ActorId actorId, IMessage message)
- {
- self.SendInner(actorId, message as MessageObject);
- }
- private static void SendInner(this ProcessOuterSender self, ActorId actorId, MessageObject message)
- {
- if (actorId == default)
- {
- throw new Exception($"actor id is 0: {message}");
- }
- Fiber fiber = self.Fiber();
- // 如果发向同一个进程,则报错
- if (actorId.Process == fiber.Process)
- {
- throw new Exception($"actor is the same process: {fiber.Process} {actorId.Process}");
- }
-
- StartProcessConfig startProcessConfig = StartProcessConfigCategory.Instance.Get(actorId.Process);
- Session session = self.Get(startProcessConfig.Id);
- actorId.Process = fiber.Process;
- session.Send(actorId, message);
- }
- private static int GetRpcId(this ProcessOuterSender self)
- {
- return ++self.RpcId;
- }
- public static async ETTask<IResponse> Call(this ProcessOuterSender self, ActorId actorId, IRequest iRequest, bool needException = true)
- {
- if (actorId == default)
- {
- throw new Exception($"actor id is 0: {iRequest}");
- }
- Fiber fiber = self.Fiber();
-
- int rpcId = self.GetRpcId();
- iRequest.RpcId = rpcId;
- Type requestType = iRequest.GetType();
- MessageSenderStruct messageSenderStruct = new(actorId, requestType, needException);
- self.requestCallback.Add(rpcId, messageSenderStruct);
-
- self.SendInner(actorId, iRequest as MessageObject);
- async ETTask Timeout()
- {
- await fiber.Root.GetComponent<TimerComponent>().WaitAsync(ProcessOuterSender.TIMEOUT_TIME);
- if (!self.requestCallback.Remove(rpcId, out MessageSenderStruct action))
- {
- return;
- }
-
- if (needException)
- {
- action.SetException(new Exception($"actor sender timeout: {requestType.FullName}"));
- }
- else
- {
- IResponse response = MessageHelper.CreateResponse(requestType, rpcId, ErrorCore.ERR_Timeout);
- action.SetResult(response);
- }
- }
- Timeout().Coroutine();
- long beginTime = TimeInfo.Instance.ServerFrameTime();
- IResponse response = await messageSenderStruct.Wait();
- long endTime = TimeInfo.Instance.ServerFrameTime();
- long costTime = endTime - beginTime;
- if (costTime > 200)
- {
- Log.Warning($"actor rpc time > 200: {costTime} {requestType.FullName}");
- }
- return response;
- }
- }
-
- [ComponentOf(typeof(Scene))]
- public class ProcessOuterSender: Entity, IAwake<IPEndPoint>, IUpdate, IDestroy
- {
- public const long TIMEOUT_TIME = 40 * 1000;
-
- public int RpcId;
- public readonly Dictionary<int, MessageSenderStruct> requestCallback = new();
-
- public AService AService;
-
- public NetworkProtocol InnerProtocol = NetworkProtocol.KCP;
- }
- }
|