提交 ecc0429e 编写于 作者: T tanghai

1.actor进行了一次更新,location中保存actor的instanceid,actorproxy获取location得

到的是actor的instanceid,因为instanceid头16字节表示服务器id,因此可以得到actor的服
务器。actor消息中的actorid也变成了instanceid,这样即使actor销毁重新创建也不会有同
样的actorid,保证了唯一性。
2.这样改动的原因是,比如一个gate挂掉导致player意外掉线,然后player立即上线,其他服务器发给player的消息有可能是之前的消息。产生异常。
3.erlang中的actorid是processid,保证是唯一的。与逻辑无关。ET的改动保证与erlang一致。
上级 fd6374b6
......@@ -8,6 +8,7 @@
message M2M_TrasferUnitResponse // IResponse
{
required int64 InstanceId = 1;
}
message M2A_Reload // IRequest
......@@ -101,7 +102,7 @@
message ObjectAddRequest // IRequest
{
required int64 Key = 1;
required int AppId = 2;
required int64 InstanceId = 2;
}
message ObjectAddResponse // IResponse
......@@ -120,7 +121,7 @@
message ObjectLockRequest // IRequest
{
required int64 Key = 1;
required int LockAppId = 2;
required int64 InstanceId = 2;
required int Time = 3;
}
......@@ -131,8 +132,8 @@
message ObjectUnLockRequest // IRequest
{
required int64 Key = 1;
required int UnLockAppId = 2;
required int AppId = 3;
required int64 OldInstanceId = 2;
required int64 InstanceId = 3;
}
message ObjectUnLockResponse // IResponse
......@@ -146,7 +147,7 @@
message ObjectGetResponse // IResponse
{
required int AppId = 1;
required int64 InstanceId = 1;
}
message R2G_GetLoginKey // IRequest
......
......@@ -52,7 +52,6 @@ namespace App
Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(innerConfig.IPEndPoint);
Game.Scene.AddComponent<NetOuterComponent, IPEndPoint>(outerConfig.IPEndPoint);
Game.Scene.AddComponent<AppManagerComponent>();
Game.Scene.AddComponent<ActorManagerComponent>();
break;
case AppType.Realm:
Game.Scene.AddComponent<ActorMessageDispatherComponent>();
......@@ -60,7 +59,6 @@ namespace App
Game.Scene.AddComponent<NetOuterComponent, IPEndPoint>(outerConfig.IPEndPoint);
Game.Scene.AddComponent<LocationProxyComponent>();
Game.Scene.AddComponent<RealmGateAddressComponent>();
Game.Scene.AddComponent<ActorManagerComponent>();
break;
case AppType.Gate:
Game.Scene.AddComponent<PlayerComponent>();
......@@ -70,12 +68,10 @@ namespace App
Game.Scene.AddComponent<LocationProxyComponent>();
Game.Scene.AddComponent<ActorProxyComponent>();
Game.Scene.AddComponent<GateSessionKeyComponent>();
Game.Scene.AddComponent<ActorManagerComponent>();
break;
case AppType.Location:
Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(innerConfig.IPEndPoint);
Game.Scene.AddComponent<LocationComponent>();
Game.Scene.AddComponent<ActorManagerComponent>();
break;
case AppType.Map:
Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(innerConfig.IPEndPoint);
......@@ -84,7 +80,6 @@ namespace App
Game.Scene.AddComponent<ActorProxyComponent>();
Game.Scene.AddComponent<ActorMessageDispatherComponent>();
Game.Scene.AddComponent<ServerFrameComponent>();
Game.Scene.AddComponent<ActorManagerComponent>();
break;
case AppType.AllServer:
Game.Scene.AddComponent<ActorProxyComponent>();
......@@ -103,7 +98,6 @@ namespace App
Game.Scene.AddComponent<GateSessionKeyComponent>();
Game.Scene.AddComponent<ConfigComponent>();
Game.Scene.AddComponent<ServerFrameComponent>();
Game.Scene.AddComponent<ActorManagerComponent>();
// Game.Scene.AddComponent<HttpComponent>();
break;
case AppType.Benchmark:
......
......@@ -16,12 +16,13 @@ namespace ETHotfix
{
long unitId = unit.Id;
// 先在location锁住unit的地址
await Game.Scene.GetComponent<LocationProxyComponent>().Lock(unitId);
await Game.Scene.GetComponent<LocationProxyComponent>().Lock(unitId, unit.InstanceId);
// 删除unit actorcomponent,让其它进程发送过来的消息找不到actor,重发
unit.RemoveComponent<ActorComponent>();
// 删除unit,让其它进程发送过来的消息找不到actor,重发
Game.EventSystem.Remove(unitId);
long instanceId = unit.InstanceId;
int mapIndex = message.MapIndex;
......@@ -40,11 +41,11 @@ namespace ETHotfix
// 只删除不disponse否则M2M_TrasferUnitRequest无法序列化Unit
Game.Scene.GetComponent<UnitComponent>().RemoveNoDispose(unitId);
await session.Call(new M2M_TrasferUnitRequest() { Unit = unit });
M2M_TrasferUnitResponse m2m_TrasferUnitResponse = (M2M_TrasferUnitResponse)await session.Call(new M2M_TrasferUnitRequest() { Unit = unit });
unit.Dispose();
// 解锁unit的地址,并且更新unit的地址
await Game.Scene.GetComponent<LocationProxyComponent>().UnLock(unitId, mapConfig.AppId);
// 解锁unit的地址,并且更新unit的instanceId
await Game.Scene.GetComponent<LocationProxyComponent>().UnLock(unitId, instanceId, m2m_TrasferUnitResponse.InstanceId);
reply(response);
}
......
......@@ -12,10 +12,13 @@ namespace ETHotfix
try
{
Unit unit = message.Unit;
// 将unit加入事件系统
Game.EventSystem.Add(unit);
Log.Debug(MongoHelper.ToJson(message.Unit));
// 这里不需要注册location,因为unlock会更新位置
unit.AddComponent<ActorComponent>();
Game.Scene.GetComponent<UnitComponent>().Add(unit);
response.InstanceId = unit.InstanceId;
reply(response);
}
catch (Exception e)
......
......@@ -12,7 +12,6 @@ namespace ETHotfix
{
self.ActorType = ActorType.Common;
self.Queue.Clear();
Game.Scene.GetComponent<ActorManagerComponent>().Add(self.Entity);
}
}
......@@ -23,7 +22,6 @@ namespace ETHotfix
{
self.ActorType = actorType;
self.Queue.Clear();
Game.Scene.GetComponent<ActorManagerComponent>().Add(self.Entity);
}
}
......@@ -41,7 +39,6 @@ namespace ETHotfix
{
public override void Destroy(ActorComponent self)
{
Game.Scene.GetComponent<ActorManagerComponent>().Remove(self.Entity.Id);
}
}
......@@ -52,7 +49,7 @@ namespace ETHotfix
{
public static async Task AddLocation(this ActorComponent self)
{
await Game.Scene.GetComponent<LocationProxyComponent>().Add(self.Entity.Id);
await Game.Scene.GetComponent<LocationProxyComponent>().Add(self.Entity.Id, self.Entity.InstanceId);
}
public static async Task RemoveLocation(this ActorComponent self)
......
......@@ -20,8 +20,10 @@ namespace ETHotfix
{
public override async void Start(ActorProxy self)
{
int appId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
self.Address = Game.Scene.GetComponent<StartConfigComponent>().Get(appId).GetComponent<InnerConfig>().IPEndPoint;
self.ActorInstanceId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
self.Address = Game.Scene.GetComponent<StartConfigComponent>()
.Get(IdGenerater.GetAppIdFromId(self.ActorInstanceId))
.GetComponent<InnerConfig>().IPEndPoint;
self.UpdateAsync();
}
......@@ -144,8 +146,10 @@ namespace ETHotfix
// 等待1s再发送
await Game.Scene.GetComponent<TimerComponent>().WaitAsync(1000);
int appId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
self.Address = Game.Scene.GetComponent<StartConfigComponent>().Get(appId).GetComponent<InnerConfig>().IPEndPoint;
self.ActorInstanceId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
self.Address = Game.Scene.GetComponent<StartConfigComponent>()
.Get(IdGenerater.GetAppIdFromId(self.ActorInstanceId))
.GetComponent<InnerConfig>().IPEndPoint;
self.CancellationTokenSource = new CancellationTokenSource();
self.AllowGet();
return;
......
......@@ -23,22 +23,22 @@ namespace ETHotfix
self.LocationAddress = startConfig.GetComponent<InnerConfig>().IPEndPoint;
}
public static async Task Add(this LocationProxyComponent self, long key)
public static async Task Add(this LocationProxyComponent self, long key, long instanceId)
{
Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
await session.Call(new ObjectAddRequest() { Key = key, AppId = self.AppId });
await session.Call(new ObjectAddRequest() { Key = key, InstanceId = instanceId });
}
public static async Task Lock(this LocationProxyComponent self, long key, int time = 1000)
public static async Task Lock(this LocationProxyComponent self, long key, long instanceId, int time = 1000)
{
Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
await session.Call(new ObjectLockRequest() { Key = key, LockAppId = self.AppId, Time = time });
await session.Call(new ObjectLockRequest() { Key = key, InstanceId = instanceId, Time = time });
}
public static async Task UnLock(this LocationProxyComponent self, long key, int value)
public static async Task UnLock(this LocationProxyComponent self, long key, long oldInstanceId, long instanceId)
{
Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
await session.Call(new ObjectUnLockRequest() { Key = key, UnLockAppId = self.AppId, AppId = value});
await session.Call(new ObjectUnLockRequest() { Key = key, OldInstanceId = oldInstanceId, InstanceId = instanceId});
}
public static async Task Remove(this LocationProxyComponent self, long key)
......@@ -47,11 +47,11 @@ namespace ETHotfix
await session.Call(new ObjectRemoveRequest() { Key = key });
}
public static async Task<int> Get(this LocationProxyComponent self, long key)
public static async Task<long> Get(this LocationProxyComponent self, long key)
{
Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
ObjectGetResponse response = (ObjectGetResponse)await session.Call(new ObjectGetRequest() { Key = key });
return response.AppId;
return response.InstanceId;
}
}
}
\ No newline at end of file
......@@ -11,7 +11,7 @@ namespace ETHotfix
ObjectAddResponse response = new ObjectAddResponse();
try
{
Game.Scene.GetComponent<LocationComponent>().Add(message.Key, message.AppId);
Game.Scene.GetComponent<LocationComponent>().Add(message.Key, message.InstanceId);
reply(response);
}
catch (Exception e)
......
......@@ -11,12 +11,12 @@ namespace ETHotfix
ObjectGetResponse response = new ObjectGetResponse();
try
{
int appId = await Game.Scene.GetComponent<LocationComponent>().GetAsync(message.Key);
if (appId == 0)
long instanceId = await Game.Scene.GetComponent<LocationComponent>().GetAsync(message.Key);
if (instanceId == 0)
{
response.Error = ErrorCode.ERR_ActorLocationNotFound;
}
response.AppId = appId;
response.InstanceId = instanceId;
reply(response);
}
catch (Exception e)
......
......@@ -11,7 +11,7 @@ namespace ETHotfix
ObjectLockResponse response = new ObjectLockResponse();
try
{
Game.Scene.GetComponent<LocationComponent>().LockAsync(message.Key, message.LockAppId, message.Time);
Game.Scene.GetComponent<LocationComponent>().Lock(message.Key, message.InstanceId, message.Time);
reply(response);
}
catch (Exception e)
......
......@@ -11,7 +11,7 @@ namespace ETHotfix
ObjectUnLockResponse response = new ObjectUnLockResponse();
try
{
Game.Scene.GetComponent<LocationComponent>().UpdateAndUnLock(message.Key, message.UnLockAppId, message.AppId);
Game.Scene.GetComponent<LocationComponent>().UnLockAndUpdate(message.Key, message.OldInstanceId, message.InstanceId);
reply(response);
}
catch (Exception e)
......
......@@ -32,6 +32,9 @@ namespace ETHotfix
[ProtoMember(92, IsRequired = true)]
public string Message { get; set; }
[ProtoMember(1, IsRequired = true)]
public long InstanceId;
}
[Message(InnerOpcode.M2A_Reload)]
......@@ -300,7 +303,7 @@ namespace ETHotfix
public long Key;
[ProtoMember(2, IsRequired = true)]
public int AppId;
public long InstanceId;
}
......@@ -357,7 +360,7 @@ namespace ETHotfix
public long Key;
[ProtoMember(2, IsRequired = true)]
public int LockAppId;
public long InstanceId;
[ProtoMember(3, IsRequired = true)]
public int Time;
......@@ -390,10 +393,10 @@ namespace ETHotfix
public long Key;
[ProtoMember(2, IsRequired = true)]
public int UnLockAppId;
public long OldInstanceId;
[ProtoMember(3, IsRequired = true)]
public int AppId;
public long InstanceId;
}
......@@ -438,7 +441,7 @@ namespace ETHotfix
public string Message { get; set; }
[ProtoMember(1, IsRequired = true)]
public int AppId;
public long InstanceId;
}
......
......@@ -14,7 +14,7 @@ namespace ETHotfix
// 收到actor消息,放入actor队列
if (message is IActorMessage iActorMessage)
{
Entity entity = Game.Scene.GetComponent<ActorManagerComponent>().Get(iActorMessage.ActorId);
Entity entity = (Entity)Game.EventSystem.Get(iActorMessage.ActorId);
if (entity == null)
{
Log.Warning($"not found actor: {iActorMessage.ActorId}");
......
using System.Collections.Generic;
namespace ETModel
{
/// <summary>
/// 用来管理该服务器上所有的Actor对象
/// </summary>
public class ActorManagerComponent : Component
{
private readonly Dictionary<long, Entity> dictionary = new Dictionary<long, Entity>();
public void Add(Entity entity)
{
Log.Info($"add actor: {entity.Id} {entity.GetType().Name}");
dictionary[entity.Id] = entity;
}
public void Remove(long id)
{
Entity entity;
if (!this.dictionary.TryGetValue(id, out entity))
{
return;
}
Log.Info($"remove actor: {entity.Id} {entity.GetType().Name}");
this.dictionary.Remove(id);
}
public Entity Get(long id)
{
Entity entity = null;
this.dictionary.TryGetValue(id, out entity);
return entity;
}
public override void Dispose()
{
if (this.IsDisposed)
{
return;
}
base.Dispose();
}
}
}
\ No newline at end of file
......@@ -9,6 +9,8 @@ namespace ETModel
{
// actor的地址
public IPEndPoint Address;
public long ActorInstanceId;
// 还没发送的消息
public Queue<ActorTask> WaitingTasks = new Queue<ActorTask>();
......
......@@ -14,7 +14,7 @@ namespace ETModel
{
Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.proxy.Address);
this.message.ActorId = this.proxy.Id;
this.message.ActorId = this.proxy.ActorInstanceId;
IResponse response = await session.Call(message, this.proxy.CancellationTokenSource.Token);
if (response.Error != ErrorCode.ERR_NotFoundActor)
......
......@@ -7,67 +7,30 @@ namespace ETModel
{
public abstract class LocationTask: Component
{
[BsonIgnore]
public Scene Scene { get; set; }
public abstract void Run();
}
public sealed class LocationLockTask : LocationTask
[ObjectSystem]
public class LocationQueryTaskAwakeSystem : AwakeSystem<LocationQueryTask, long>
{
private readonly long key;
private readonly int lockAppId;
private readonly int time;
private readonly TaskCompletionSource<bool> tcs;
public LocationLockTask(long key, int lockAppId, int time)
{
this.key = key;
this.lockAppId = lockAppId;
this.time = time;
this.tcs = new TaskCompletionSource<bool>();
}
public Task<bool> Task
public override void Awake(LocationQueryTask self, long key)
{
get
{
return this.tcs.Task;
}
}
public override void Run()
{
try
{
Scene.GetComponent<LocationComponent>().Lock(this.key, this.lockAppId, this.time);
this.tcs.SetResult(true);
}
catch (Exception e)
{
this.tcs.SetException(e);
}
self.Key = key;
self.Tcs = new TaskCompletionSource<long>();
}
}
public sealed class LocationQueryTask : LocationTask
{
private readonly long key;
public long Key;
private readonly TaskCompletionSource<int> tcs;
public TaskCompletionSource<long> Tcs;
public LocationQueryTask(long key)
{
this.key = key;
this.tcs = new TaskCompletionSource<int>();
}
public Task<int> Task
public Task<long> Task
{
get
{
return this.tcs.Task;
return this.Tcs.Task;
}
}
......@@ -75,29 +38,30 @@ namespace ETModel
{
try
{
int location = Scene.GetComponent<LocationComponent>().Get(key);
this.tcs.SetResult(location);
LocationComponent locationComponent = this.GetParent<LocationComponent>();
long location = locationComponent.Get(this.Key);
this.Tcs.SetResult(location);
}
catch (Exception e)
{
this.tcs.SetException(e);
this.Tcs.SetException(e);
}
}
}
public class LocationComponent : Component
{
private readonly Dictionary<long, int> locations = new Dictionary<long, int>();
private readonly Dictionary<long, long> locations = new Dictionary<long, long>();
private readonly Dictionary<long, int> lockDict = new Dictionary<long, int>();
private readonly Dictionary<long, long> lockDict = new Dictionary<long, long>();
private readonly Dictionary<long, Queue<LocationTask>> taskQueues = new Dictionary<long, Queue<LocationTask>>();
public void Add(long key, int appId)
public void Add(long key, long instanceId)
{
this.locations[key] = appId;
this.locations[key] = instanceId;
Log.Info($"location add key: {key} appid: {appId}");
Log.Info($"location add key: {key} instanceId: {instanceId}");
// 更新db
//await Game.Scene.GetComponent<DBProxyComponent>().Save(new Location(key, address));
......@@ -109,37 +73,43 @@ namespace ETModel
this.locations.Remove(key);
}
public int Get(long key)
public long Get(long key)
{
this.locations.TryGetValue(key, out int location);
return location;
this.locations.TryGetValue(key, out long instanceId);
return instanceId;
}
public async void Lock(long key, int lockAppId, int time = 0)
public async void Lock(long key, long instanceId, int time = 0)
{
if (this.lockDict.ContainsKey(key))
{
Log.Error($"不可能同时存在两次lock, key: {key} lockAppId: {lockAppId}");
Log.Error($"不可能同时存在两次lock, key: {key} InstanceId: {instanceId}");
return;
}
Log.Info($"location lock key: {key} InstanceId: {instanceId}");
if (!this.locations.TryGetValue(key, out long saveInstanceId))
{
Log.Error($"actor没有注册, key: {key} InstanceId: {instanceId}");
return;
}
Log.Info($"location lock key: {key} lockAppId: {lockAppId}");
if (saveInstanceId != instanceId)
{
Log.Error($"actor注册的instanceId与lock的不一致, key: {key} InstanceId: {instanceId} saveInstanceId: {saveInstanceId}");
return;
}
this.lockDict.Add(key, lockAppId);
this.lockDict.Add(key, instanceId);
// 超时则解锁
if (time > 0)
{
await Game.Scene.GetComponent<TimerComponent>().WaitAsync(time);
int saveAppId = 0;
if (!this.lockDict.TryGetValue(key, out saveAppId))
{
return;
}
if (saveAppId != lockAppId)
if (!this.lockDict.ContainsKey(key))
{
Log.Error($"timeout unlock appid is different {saveAppId} {lockAppId}");
return;
}
Log.Info($"location timeout unlock key: {key} time: {time}");
......@@ -147,16 +117,15 @@ namespace ETModel
}
}
public void UpdateAndUnLock(long key, int unLockAppId, int value)
public void UnLockAndUpdate(long key, long oldInstanceId, long instanceId)
{
int lockAppId = 0;
this.lockDict.TryGetValue(key, out lockAppId);
if (lockAppId != unLockAppId)
this.lockDict.TryGetValue(key, out long lockInstanceId);
if (lockInstanceId != oldInstanceId)
{
Log.Error($"unlock appid is different {lockAppId} {unLockAppId}" );
Log.Error($"unlock appid is different {lockInstanceId} {oldInstanceId}" );
}
Log.Info($"location unlock key: {key} unLockAppId: {unLockAppId} new: {value}");
this.locations[key] = value;
Log.Info($"location unlock key: {key} oldInstanceId: {oldInstanceId} new: {instanceId}");
this.locations[key] = instanceId;
this.UnLock(key);
}
......@@ -182,33 +151,28 @@ namespace ETModel
}
LocationTask task = tasks.Dequeue();
task.Run();
}
}
public Task<bool> LockAsync(long key, int appId, int time)
{
if (!this.lockDict.ContainsKey(key))
{
this.Lock(key, appId, time);
return Task.FromResult(true);
try
{
task.Run();
}
catch (Exception e)
{
Log.Error(e);
}
task.Dispose();
}
LocationLockTask task = new LocationLockTask(key, appId, time);
this.AddTask(key, task);
return task.Task;
}
public Task<int> GetAsync(long key)
public Task<long> GetAsync(long key)
{
if (!this.lockDict.ContainsKey(key))
{
this.locations.TryGetValue(key, out int location);
Log.Info($"location get key: {key} {location}");
return Task.FromResult(location);
this.locations.TryGetValue(key, out long instanceId);
Log.Info($"location get key: {key} {instanceId}");
return Task.FromResult(instanceId);
}
LocationQueryTask task = new LocationQueryTask(key);
LocationQueryTask task = ComponentFactory.CreateWithParent<LocationQueryTask, long>(this, key);
this.AddTask(key, task);
return task.Task;
}
......@@ -220,7 +184,6 @@ namespace ETModel
tasks = new Queue<LocationTask>();
this.taskQueues[key] = tasks;
}
task.Scene = this.GetParent<Scene>();
tasks.Enqueue(task);
}
......@@ -231,6 +194,10 @@ namespace ETModel
return;
}
base.Dispose();
this.locations.Clear();
this.lockDict.Clear();
this.taskQueues.Clear();
}
}
}
\ No newline at end of file
......@@ -113,7 +113,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Component\Config\" />
<Folder Include="Component\Unit" />
<Folder Include="Module\Message\Network\KCP\" />
<Folder Include="Module\Message\Network\TCP\" />
<Folder Include="Module\Numeric\" />
......
......@@ -12,5 +12,10 @@
return (AppId << 48) + (time << 16) + ++value;
}
public static int GetAppIdFromId(long id)
{
return (int)(id >> 48);
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册