ET6.0服务器框架学习笔记(一、启动配置)
最近ET6.0框架越发趋于完善,剩下的基本上都是小改动,ET6.0相比5.0新增了机器人框架,简易AI框架,协程锁(超时处理),更加精简的ETTASK等等。
之前都是读源码的方式来解读5.0,6.0打算从使用的角度来解读(当然也会附带说下核心的代码)
文章目录
从配置表开始
ET6.0服务器启动,需要依靠几个默认的配置表,如下图:
每个表的作用:
- StartMachineConfig:启动的物理机器配置,每一条代表一台物理机,包括id,内外网地址,以及一个守护进程端口
- StartZoneConfig:相关游戏区的配置,现在里面已经写好的配置,每一条代表一个区连接的数据库配置
- StartProcessConfig:启动的进程配置,当启动一个ET6.0的服务器时,会根据传入的数据读取这个配置确定服务器应该以什么样的配置运行当前进程
- StartSceneConfig:启动服务器时,这个表里面的配置,决定了给这个服务器添加什么类型的服务功能(暂且理解为,其中的一个场景就是一种服务,对应有:Realm服(用于认证玩家),Gate服(经过认证后所有与客户端通信),Location服(用于提供查找Actor定位服),Map服(用于管理玩家游戏实体,互相通信))。注意Process字段表示所属的进程,Zone字段表示游戏区的概念。如果这里的Process填的进程id与StartProcessConfig对不上,那么没有任何服务功能会在启动的服务器里。
一、启动ET服务器
1.编译生成所有代码
按照ETBOOK以及论坛里面的方法,对Client-Server.sln解决方案,重新生成解决方案,如下图:
出现下图提示,则代表生成成功:
2.改动配置表
为了验证功能,我们增加一个进程配置:
然后把所有StartSceneConfig表里面的配置改成2,这样所有服务都在2号进程启动。
切换配置表导出工具,跑一下:
备注:最新ET6.0已经去掉下面的项目,需要用命令行方式,或修改启动参数为:
–AppType=ExcelExporter 才能正确启动导出配置工程
出现下面情况,则导表成功。
备注:如果导表失败,可能由于EXCEL的备份文件存在,把隐藏文件夹打开删除那些备份的,或者改代码去掉~开头的文件。
3.启动App
切换回Server.App项目,配置启动参数(我这里用的Visual Studio)。也可以通过命令行的方式启动,并传入参数。
我们看看有哪些参数可以传,直接打开Options类,可以看到里面带有Option特性的都是可以解析出来的参数,且使用的长名称,且有默认值,所以不配置走默认的,也可以启动APP,但是为了理解ET6.0我们需要配置参数。
这里我们假设启动的是2号进程,所以传入参数 --Process 2
配置好后,直接启动,没有报错,启动成功。
查看日志文件启动成功,都启动成功,说明启动的2号进程,里面配置的所有服都启动成功:
为了测试,我们把Gate2配置为1号进程,再次启动看看日志如下,只有Gate1启动了:
二、ET启动核心代码解析
1.启动类Server.App项目Program类
这个类主要功能:
- 设置线程同步上下文,用于将异步方法全都能通过Post方法回到主线程调用:
SynchronizationContext.SetSynchronizationContext(ThreadSynchronizationContext.Instance);
- 给Event类注册Server.Model工程与Server.Hotfix工程的程序集信息。主要用于将各类特性标签与类型信息注册到Event类中进行管理,同时还包括:注册各个组件的生命周期事件系统(Load,Awake,Update,LateUpdate,Destroy等);各个事件监听的注册等。
- 初始化protobufHelper类:用于序列化Protobuff用,MongoHelper类:用于序列化Mongo用,虽然两个init现在没啥用。
- 解析启动传入的命令行参数,初始化服务器启动参数Option。
- 派发一个服务器启动事件:
Game.EventSystem.Publish(new EventType.AppStart());
- 驱动整个游戏循环,包括:Update();LateUpdate();FrameFinish();
2.Server.Hotfix项目AppStart_Init类
这个类继承了AEvent<EventType.AppStart>,并传入了事件类型结构体EventType.AppStart。因此在上一步Event中初始化时,就实例化了AppStart_Init类,且监听了事件EventType.AppStart。因此上面第5步,派发事件EventType.AppStart时,会进入到AppStart_Init类的Run方法中。
- 初始化第一个服务器Scene,Game.Scene,然后给这个Scene添加各种组件:
TimerComponent:定时器
OpcodeTypeComponent:协议管理
MessageDispatcherComponent:普通消息派发处理
CoroutineLockComponent:协程锁
ActorMessageSenderComponent:普通Actor消息发送
ActorLocationSenderComponent:带定位的Location Actor消息发送
LocationProxyComponent:定位服处理
ActorMessageDispatcherComponent:Actor消息派发处理
NumericWatcherComponent:数值变化订阅处理
NetThreadComponent:网络服务管理(注意不是处理只是管理) - 根据服务类型,创建不同服务,暂且不管监听服务,只管游戏服务。增加内网组件,用于处理来自服务器各个服务之间的通信(包括不同进程之间的)`Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(processConfig.InnerIPPort);
- 在游戏服类型下,按照配置的StartScene配置,创建对应属于这个服进程号的子Scene。`
2.Server.Hotfix项目SceneFactory类
用于创建各个Scene实体类,核心代码如下:
public static async ETTask<Scene> Create(Entity parent, long id, long instanceId, int zone, string name, SceneType sceneType, StartSceneConfig startSceneConfig = null)
{
await ETTask.CompletedTask;
Scene scene = EntitySceneFactory.CreateScene(id, instanceId, zone, sceneType, name, parent);
scene.AddComponent<MailBoxComponent, MailboxType>(MailboxType.UnOrderMessageDispatcher);
switch (scene.SceneType)
{
case SceneType.Realm:
scene.AddComponent<NetKcpComponent, IPEndPoint>(startSceneConfig.OuterIPPort);
break;
case SceneType.Gate:
scene.AddComponent<NetKcpComponent, IPEndPoint>(startSceneConfig.OuterIPPort);
scene.AddComponent<PlayerComponent>();
scene.AddComponent<GateSessionKeyComponent>();
break;
case SceneType.Map:
scene.AddComponent<UnitComponent>();
scene.AddComponent<RecastPathComponent>();
break;
case SceneType.Location:
scene.AddComponent<LocationComponent>();
break;
}
return scene;
}
- 根据传入的服务类型,startScene配置ID,InstanceId(这个很重要,它是由生成对应StartSceneConfig单条配置时,由进程号与配置ID组合成的实体ID,通过这个实体ID可以找到对应的进程IP与端口用于通信),服务区号,服务器类型等信息,创建一个服务Scene。
- 对Scene挂载MailBoxComponent组件,用于处理Actor请求,并且区分是否需要按顺序处理收到的请求。(备注:挂在了MailBoxComponent的Entity类就可以处理Actor消息,且可以有顺序处理的功能,Scene也是Entity的一种)
- 针对服务器类型,给上面生成的服务Scene挂载各类功能组件:
NetKcpComponent:网外通信组件,用于监听来自客户端的通信处理
PlayerComponent:用于管理生成的Player实体
GateSessionKeyComponent:用于管理玩家认证的凭据(主要用于Gate认证玩家连接是否被允许)
UnitComponent:用于管理Map中的Unit实体
RecastPathComponent:寻路组件
LocationComponent:用于管理实体对象ID与InstanceID之间的关系,提供了通过ID查询InstanceID的功能。
猫大已经在ET6.0中组合好各个服务类型Scene,应该具备的功能组件。当所有服配置在一个进程中时,就相当于5.0的All Server模式了。
现在服务器已经启动好了,剩下的只需要,定义好协议,注册好协议处理类,进行逻辑开发就可以愉快的开发下去了。
总结
本篇只针对服务器启动如何配置启动,且记录了几个核心启动相关的类,进行了说明,下一篇从第一个登录协议讲解开始。
补充说明:猫大增加了守护进程的方式启动各个服务器,需要增加–AppType Watcher启动参数,用于通过守护进程来启动所有服务进程,同时也可以增加其他功能