{"id":21358866,"url":"https://github.com/gameframex/gameframex.server","last_synced_at":"2026-02-24T08:43:11.505Z","repository":{"id":229133820,"uuid":"775849694","full_name":"GameFrameX/GameFrameX.Server","owner":"GameFrameX","description":"GameFrameX的Server部分","archived":false,"fork":false,"pushed_at":"2026-01-05T08:50:05.000Z","size":32195,"stargazers_count":54,"open_issues_count":6,"forks_count":30,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-01-09T00:53:23.260Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GameFrameX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-03-22T06:58:59.000Z","updated_at":"2025-12-24T07:57:24.000Z","dependencies_parsed_at":"2024-03-25T11:42:06.695Z","dependency_job_id":"257e9ac0-da72-4630-801d-9c1bbe5e3e9f","html_url":"https://github.com/GameFrameX/GameFrameX.Server","commit_stats":null,"previous_names":["alianblank/gameframex.server","gameframex/gameframex.server"],"tags_count":159,"template":false,"template_full_name":null,"purl":"pkg:github/GameFrameX/GameFrameX.Server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GameFrameX%2FGameFrameX.Server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GameFrameX%2FGameFrameX.Server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GameFrameX%2FGameFrameX.Server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GameFrameX%2FGameFrameX.Server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GameFrameX","download_url":"https://codeload.github.com/GameFrameX/GameFrameX.Server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GameFrameX%2FGameFrameX.Server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29776799,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-24T04:54:30.205Z","status":"ssl_error","status_checked_at":"2026-02-24T04:53:58.628Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-22T05:22:41.442Z","updated_at":"2026-02-24T08:43:11.452Z","avatar_url":"https://github.com/GameFrameX.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GameFrameX介绍：\r\n\r\nGameFrameX 是基于 `GeekServer` 是一个开源的[分区分服](https://mp.weixin.qq.com/s?__biz=MzI3MTQ1NzU2NA==\u0026mid=2247483884\u0026idx=1\u0026sn=3547c769a300f1d82cc04e9b1852c6d5\u0026chksm=eac0cd9fddb7448997e38a74e2d26bde259cd2127583e31bc488511bc1fdcd9f35caff27d4a3\u0026scene=21#wechat_redirect)\r\n的游戏服务器框架，采用C# .Netcore开发，开发效率高，性能强，跨平台，并内置不停服热更新机制。可以满足绝大部分游戏类型的需求，特别是和Unity3D协同开发更佳。\r\n\r\n__设计理念:大道至简，以简化繁__\r\n\r\n# GameFrameX功能：\r\n\r\n## 1.跨平台\r\n\r\n使用C# .Netcore开发（可以跨平台，可以跨平台，可以跨平台），.Netcore现在功能和性能都已经十分强大和稳健，不管是在windows还是linux上部署起来都很简便。\r\n\r\n## 2.全面异步编程\r\n\r\n全部采用异步编程（async/await），让逻辑代码变得整洁优雅，清晰易懂，让代码写起来行如流水。\r\n\r\n## 3.TPL(Task Parallel Library) Actor模型\r\n\r\nActor模型构建于强大的TPL DataFlow之上，让Actor模型如虎添翼。（不了解Actor模型，可以搜一下相关资料，Akka，Orleans都是采用的Actor模型）\r\n\r\n## 4.Actor入队透明化\r\n\r\n内部会自动处理线程上下文, 编译期间会通过[Source Generator](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview)自动生成入队代码, 开发人员无需关心多线程以及入队逻辑,\r\n只需要像调用普通函数一样书写逻辑。\r\n\r\n#### Actor入队透明\r\n\r\n`GameFrameX` 编译期间会自动注入入队代码(**AgentWeaver**), 开发人员无需入队逻辑, 只需要像调用普通函数一样书写逻辑。\r\n\r\n```c#\r\n//编译期间会注入一个继承自xxxCompAgent的wrapper类,来实现自动入队\r\n//同时SendAsync内部自动处理了线程上下文,开发者只需要像调用普通函数一样书写逻辑\r\npublic class ServerComponentAgentWrapper : ServerComponentAgent\r\n{\r\n\tpublic override Task CheckCrossDay()\r\n\t{\r\n\t\treturn base.Actor.SendAsync((Func\u003cTask\u003e)base.CheckCrossDay, isAwait: false, 10000);\r\n\t}\r\n\r\n\tpublic override Task\u003cint\u003e GetDaysFromOpenServer()\r\n\t{\r\n\t\treturn base.Actor.SendAsync((Func\u003cTask\u003cint\u003e\u003e)base.GetDaysFromOpenServer, isAwait: true, 10000);\r\n\t}\r\n}\r\n\r\nvar serverComp = await EntityMgr.GetCompAgent\u003cServerComponentAgent\u003e(ActorType.Server);\r\n//使用方式(就像调用普通函数一样,无需关心多线程或入队)\r\n_ = serverComp.CheckCrossDay();\r\n\r\n```\r\n\r\n#### 线程上下文\r\n\r\n`GameFrameX` 内部会自动处理线程上下文，由RuntimeContext实现，主要用于环路调用检测，以及判断是否需要入队，其内部使用**AsyncLocal**实现\r\n\r\n```c#\r\ninternal class RuntimeContext\r\n{\r\n    internal static long Current =\u003e callCtx.Value;\r\n    internal static AsyncLocal\u003clong\u003e callCtx = new AsyncLocal\u003clong\u003e();\r\n\r\n    [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n    internal static void SetContext(long callChainId)\r\n    {\r\n        callCtx.Value = callChainId;\r\n    }\r\n\r\n    [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n    internal static void ResetContext()\r\n    {\r\n        callCtx.Value = 0;\r\n    }\r\n}\r\n```\r\n\r\n## 5.Actor死锁检测\r\n\r\n#### Actor模型 ##\r\n\r\nactor模型是什么可以自行查阅一下相关资料；actor模型在一定程度可以说是解决并发的最佳方案。\r\n\r\n`GameFrameX` 的actor可以简单理解为一个线程(其实用的是线程池)，一个actor的逻辑只需保证在自己的队列里面执行即保证可线程安全，无需关心锁的问题。 `GameFrameX` 的基础就是actor，一切皆可为actor。 `GameFrameX` 的actor模型构建于强大的TPL DataFlow之上，底层使用内置线程池。 `GameFrameX` 同时使用异步变成（async/await），让逻辑代码更加清晰明了，符合人类的思维方式。\r\n\r\n#### Actor死锁 ##\r\n\r\nActor模型本身是存在死锁的情况，且不容易被发现。 `GameFrameX` 内部可检测环路死锁(即:A-\u003eB-\u003eC-\u003eA)，并采用调用链重入机制消除环路死锁（类似与线程的可重入性）。  \r\n还有另外一种情况（多路死锁），比如有2个actor，A和B，一段逻辑A调用B，同时有另外一段逻辑发起了B调用A，就会出现A等B，B再等A，此时发生死锁。同理 [A-\u003eB-\u003eC，C-\u003eD-\u003eA] [A-\u003eB-\u003eC，B-\u003eC-\u003eA],这样的调用路径都可能会存在死锁。  \r\n这种死锁无法解决，而且不确定，因为它和调用时间节点有关系，只能从设计上去规避。\r\n\r\n```csharp\r\nclass ActorA\r\n{\r\n\tTask A1()\r\n\t{\r\n        await Task.Delay(10); \r\n\t\tvar b = GetActorB();\r\n\t\treturn b.SendAsync(b.B1);\r\n\t}\r\n\t\r\n\tTask A2()\r\n\t{\r\n\t\tvar b = GetActorB();\r\n\t\treturn b.SendAsync(b.B1);\r\n\t}\r\n}\r\n\r\nclass ActorB\r\n{\r\n\tTask B1()\r\n\t{\r\n\t\tawait Task.Delay(5);\r\n\t\tvar a = GetActorA();\r\n\t\treturn a.SendAsync(a.A2);\r\n\t}\r\n}\r\n\r\nTask Call()\r\n{\r\n\tvar a = GetActorA();\r\n\treturn a.SendAsync(a.A1);//这里就会触发死锁\r\n}\r\n```\r\n\r\n如果得到打印日志【执行超时】很有可能就是触发了死锁。由于Actor设定了超时时间，在断点调试的时候需要手动将超时时间改长，默认10秒，在BaseActor.TIME_OUT修改。**（或者用一个Debug模式的宏来控制）**\r\n\r\n#### 多路死锁解决方案 ##\r\n\r\n由以上的分析可以看出，多路死锁其实是由于**Await**引起的，如果所有调用都不Await则永远不会有死锁。  \r\n这里为大家罗列了几种解决方案：(在 `GameFrameX` 中可以通过ActorLimit来定制自己的检测规则)\r\n\r\n1. **跨Actor调用，不能Await**  \r\n   优点：规则简单，统一，绝对不会发生死锁  \r\n   缺点：失去了异步语法的优势，所有需要跨Actor获取返回值的，只能使用回调，代码结构散乱，书写代码不方便。\r\n\r\n2. **为Actor分配等级，只允许低等级await调用高等级（如：Role-\u003eServer 而Server不能等待调用Role, 推荐使用此方案）**  \r\n   案例：公民可以去政府部门排队等待办理业务员，但是政府部门不可能去等待某个人去处理完自己的私事，再帮下一个人办理业务，顶多发短信或者打电话通知某个人做什么事情。  \r\n   在方案1的基础上，给了使用者更多的异步调用空间。\r\n\r\n3. **提供一个注册接口，注册哪些Actor可以Await调用哪些Actor，并在注册时候进行检测看是否可能存在死锁**    \r\n   这是方案2的一个更加灵活的变种。\r\n\r\n4. **允许交错执行** [了解更多](https://blog.csdn.net/uddiqpl/article/details/86294520)    \r\n   如果你的某个组件不会操作数据或者对操作顺序不敏感，交错执行是很有用的。 `GameFrameX` 中的FuncComponent比较符合这个特点，但不绝对，仍需要开发人员自行判断。 （Orleans中有此方案）\r\n\r\n5. **允许存在多路死锁的风险，由开发人员保证不会触发死锁**  \r\n   优点：规则简单，统一，书写代码很方便，全程异步。  \r\n   缺点：有可能发生死锁，对编码人员能力要求较高\r\n\r\n6. **超时规则**  \r\n   如果发生多路死锁，选择一条调用路径并终止，保证其中一条调用路径正确。（Orleans中有此方案）  \r\n   优缺点和方案5一样。\r\n\r\n7. **使用线程安全容器以及lock等**   \r\n   但这与无锁化设计的理念冲突\r\n\r\n## 6.支持不停服更新\r\n\r\n采用组件+状态的分离设计实现不停服热更新:\r\n\r\n1. 架构设计优势\r\n\r\n- 状态与逻辑完全分离,状态类只包含数据属性\r\n- 组件类只包含业务逻辑方法,不持有状态\r\n- 通过代理模式将所有逻辑代码放入热更新dll\r\n- 运行时只需重载dll即可更新全部业务逻辑\r\n\r\n2. 热更新优势\r\n\r\n- 无需停服即可更新游戏逻辑\r\n- 玩家无感知,不会影响游戏体验\r\n- 支持增量更新,只更新修改的逻辑\r\n- 更新过程安全可靠,失败可回滚\r\n\r\n3. 开发效率提升\r\n\r\n- 逻辑bug修复无需重启服务器\r\n- 新功能可以随时发布更新\r\n- 减少维护成本和停机时间\r\n- 便于快速验证和调试\r\n\r\n#### 热更新\r\n\r\n`GameFrameX` 支持不停服热更新逻辑。\r\n\r\n#### 热更思路\r\n\r\n游戏中的所有状态放在App工程中，始终存在于内存，不能热更。Actor和Component的逻辑使用代理模式（Agent）放到Hotfix工程。热更时载入新的dll（ `GameFrameX` .Hotfix.dll），清除所有老的Agent，所有新逻辑重新从Actor/Component获取新的Agent汇入新dll中执行热更后的逻辑，达到热更目的。正在执行老dll逻辑的代码获取的Agent依然来自热更前的老Dll中，等待老dll中的逻辑执行完后清理掉内存中老的dll。底层使用接口驱动热更dll中的逻辑。\r\n需要注意的是，热更时新的dll需要放在新的目录下面，然后再载入内存，因为老的dll可能正在运行，是无法直接覆盖的。\r\n\r\n##### 可以热更部分\r\n\r\n可以热更的逻辑都应该放在 `GameFrameX` .Hotfix工程中\r\n\r\n1. 所有Actor/Component的Agent，Agent中只有逻辑没有状态，状态全部放到Component的State\r\n2. HttpHandler\r\n3. TcpHandler\r\n4. 协议\r\n5. 配置表/配置表代码\r\n\r\n##### 热更新流程\r\n\r\n1. 游戏后台将新的 `GameFrameX` .Hotfix.dll及相关文件（对应pdb，json等）拷贝到游戏服特定目录下\r\n2. 游戏后台向游戏服发送http命令，通知进行热更，并告知dll目录，md5等信息\r\n3. 游戏服中热更HttpHandler根据后台信息，验证热更dll完整性，合法性，修改dllVersion.txt，发起热更调用\r\n\r\n## 7.网络模块\r\n\r\n网络模块采用SuperSocket作为底层网络框架，具有以下优势:\r\n\r\n1. 高性能和可扩展性\r\n\r\n- 基于.NET Core的高性能网络库\r\n- 采用异步IO模型,支持高并发连接\r\n- 内置连接池和内存池优化,减少GC压力\r\n- 可配置的线程模型,支持灵活的扩展\r\n\r\n2. 协议支持全面\r\n\r\n- 支持TCP、UDP、WebSocket等多种传输协议\r\n- 内置HTTP 1.1/2/3协议支持\r\n- 支持SignalR实时通信\r\n- 支持自定义二进制协议\r\n- 支持SSL/TLS加密传输\r\n\r\n3. 功能特性丰富\r\n\r\n- 内置会话管理和心跳检测\r\n- 支持消息过滤和管道处理\r\n- 提供命令过滤器机制\r\n- 支持消息分包和粘包处理\r\n- 支持二进制和文本消息编解码\r\n\r\n4. 开发便捷性\r\n\r\n- 简单易用的API设计\r\n- 完善的文档和示例\r\n- 支持配置化开发\r\n- 提供多种扩展点\r\n- 活跃的社区支持\r\n\r\n[了解更多SuperSocket详情](https://github.com/GameFrameX/GameFrameX.SuperSocket)\r\n\r\n## 8.持久化透明\r\n\r\n采用Nosql作为数据存储，状态的持久化全透明，框架会自动序列化/反序列,让开发人员更加专注于业务逻辑，无需操心数据库。\r\n\r\n#### Entity和Component和State\r\n\r\n`GameFrameX` 的Entity包含1个/多个Component，Component包含0个/1个State，你可以这样理解：Entity=实体，Component=功能系统，State=功能系统的数据。每个Entity都包含一个Actor成员变量，Entity的所有行为调度都有Actor完成，以保证线程安全。\r\n\r\nEntity是 `GameFrameX` 的基础，一切功能都可以作为单独的Entity（比如一个角色，一个公会，一个玩法系统。。。），Component隶属于Entity，State隶属于Component，Component承载各种逻辑，State承载各种数据。Entity拆分方式根据项目的具体需求可以任意规划。\r\n\r\n#### Entity(Actor)拆分\r\n\r\n1. 尽可能独立（一个系统或者玩家的操作尽量不阻塞其他玩家的操作）\r\n2. 在独立的前提下尽可能少（节约管理成本）\r\n3. 一个角色，包含若干个功能系统（背包，宠物，任务。。。）\r\n4. 一个公会，包含多个公会基础系统（基础信息，捐赠，工会副本。。。）\r\n\r\n比如有2个全局玩法，世界boss和工会战，如果这2个系统归于一个Actor，那么当一个玩家挑战世界boss时，挑战逻辑到Actor线程中执行，此时另一个玩家要去报名工会战，报名逻辑也需要到Actor线程中执行，此时报名公会战的逻辑则需要等待前一个玩家挑战世界boss逻辑完成后才能执行，客户端表现可能就是更长时间的网络连接中，在cpu够用的情况下就产生了多余的等待时间，这就有些不合理了；这种功能之间没有任何交集的情况下我们建议将世界boss和工会战分别拆分为Actor，各自的逻辑便可以更加顺畅的执行，客户端等待的时间也越短。\r\n\r\n## 9.Timer/Scheduler/Event\r\n\r\n内置线程安全的Timer，Scheduler，Event系统，轻松应对游戏服务器常见的定时，任务计划，事件触发等业务需求。\r\n\r\n#### 定时器\u0026计划任务\r\n\r\n`GameFrameX` 中没有使用传统意义中的Update，除MMO项目，其他大部分游戏类型的服务器基本没有必要使用Update，需要Update的模块添加一个Timer也可以实现\r\n根据热更新设计方案，定时器和计划任务采用接口方式进行回调，任务使用扩展方法实现，\r\n\r\n定时器支持：1次性delay,周期性timer。\r\n计划任务：指定时间1次性任务，每天任务，每周任务，每周几任务，每月任务。\r\n`GameFrameX` 中没有对定时器\u0026计划任务做持久化，所以你可能需要在开服后、玩家上线或者Component激活时考虑一下计划任务逻辑是否需要被处理了。\r\n回调函数继承TimerHandler\u003c\u003e，重写HandleTimer，里面处理定时器回调逻辑即可。\r\n需要注意的是定时器是接入的Quartz，由于硬件精度问题（windows时间实际精度为10毫秒左右），回调时间可能会提前1-2毫秒，如果对时间依赖特别大的可能需要特殊处理下，比如在Timer回调后延时50毫秒再执行回调逻辑。\r\n\r\n## 10.定期释放不活跃内存数据\r\n\r\n以功能系统级别的粒度，定期剔除内存中不活跃的玩家数据，尽最大可能减少服务器内存开销。\r\n\r\n# 运行\r\n\r\n1. 安装[.NetCore8.0](https://dotnet.microsoft.com/download/dotnet/8.0)\r\n2. 安装[mongodb4.x](https://www.mongodb.com/try/download/community)\r\n3. 打开git clone本项目\r\n4. 用VisualStudio 或者Rider打开Server.sln 启动 `GameFrameX.Launcher`\r\n5. 打开Unity工程，打开Launcher 场景，运行查看日志\r\n\r\n# Doc (已经在写了,别催了!-_-!)\r\n\r\n`所有站点内容一致，不存在内容不一致的情况`\r\n\r\n文档地址 : https://gameframex.doc.alianblank.com\r\n\r\n备用文档地址 : https://gameframex-docs.pages.dev\r\n\r\n备用文档地址 : https://gameframex.doc.cloudflare.alianblank.com\r\n\r\n备用文档地址 : https://gameframex.doc.vercel.alianblank.com\r\n\r\n# 文档\u0026例子\u0026Demo\r\n\r\n[视频教程](https://www.bilibili.com/video/BV1yrpeepEn7)\r\n\r\n[参考文档](https://gameframex.doc.alianblank.com)\r\n\r\n[项目主页](https://github.com/GameFrameX)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgameframex%2Fgameframex.server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgameframex%2Fgameframex.server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgameframex%2Fgameframex.server/lists"}