Giter Club home page Giter Club logo

geekserver's Introduction

GeekServer 介绍:

GeekServer 是一个开源的分区分服的游戏服务器框架,采用 C# .Netcore 开发,开发效率高,性能强,跨平台,并内置不停服热更新机制。可以满足绝大部分游戏类型的需求,特别是和 Unity3D 协同开发更佳。
设计理念:大道至简,以简化繁

GeekServer 功能:

1.跨平台

使用 C# .Netcore 开发(可以跨平台,可以跨平台,可以跨平台),.Netcore 现在功能和性能都已经十分强大和稳健,不管是在 windows 还是 linux 上部署起来都很简便。

2.全面异步编程

全部采用异步编程(async/await),让逻辑代码变得整洁优雅,清晰易懂,让代码写起来行如流水。

3.TPL(Task Parallel Library) Actor 模型

GeekServer 的 Actor 模型构建于强大的 TPL DataFlow 之上,让 Actor 模型如虎添翼。(不了解 Actor 模型,可以搜一下相关资料,Akka,Orleans 都是采用的 Actor 模型)了解更多

4.Actor 入队透明化

GeekServer 内部会自动处理线程上下文, 编译期间会通过Source Generator自动生成入队代码, 开发人员无需关心多线程以及入队逻辑, 只需要像调用普通函数一样书写逻辑。了解更多

5.Actor 死锁检测

Actor 模型本身是存在死锁的情况,且不容易被发现。GeekServer 内部可检测环路死锁(即:A->B->C->A),并采用调用链重入机制消除环路死锁。了解更多

6.支持不停服更新

采用组件+状态的设计,状态只有属性,没有方法,组件只用方法,没有属性,并通过代理的方式全部放到热更 dll 中,运行时重新加载 dll 即可热更所有逻辑。了解更多

7.网络模块

网络模块替换了原来的 DotNetty,采用 Asp.Net 的默认服务器 Kestrel,支持协议多(Tcp,udp,Http123,websocket,signalr 等),而且性能比 dotnetty 高很多了解更多

8.持久化透明

采用 Nosql 作为数据存储,状态的持久化全透明,框架会自动序列化/反序列,让开发人员更加专注于业务逻辑,无需操心数据库。 了解更多

9.Timer/Scheduler/Event

内置线程安全的 Timer,Scheduler,Event 系统,轻松应对游戏服务器常见的定时,任务计划,事件触发等业务需求。了解更多

10.定期释放不活跃内存数据

以功能系统级别的粒度,定期剔除内存中不活跃的玩家数据,尽最大可能减少服务器内存开销。

11.高效的通信协议(基于 MessagePack)

Geek.MsgPackTool [MessagePack]对多态支持不够友好,GeekServer 提供了工具来生成多态注册信息,序列化和反序列化效率极高,同时序列化之后的数据极小,数据传输效率很高。了解更多

12.一键导表工具(GeekConfig)

GeekConfig是一个一键导表工具,将策划配置表,转化为二进制数据,并提供了方便快捷的 API 供游戏调用

运行

  1. 安装.Net 7.x
  2. 安装mongodb
  3. 打开 git clone 本项目https://github.com/leeveel/GeekServer.git
  4. 运行 Tools/ExcelGen/ExcelToCode.exe 点击[服务器-ALL]导出配置表
  5. 用 VisualStudio2022 打开 GeekServer.sln 启动 GeekServer.App
  6. 启动 GeekServer.Test (一个 1000 人登录的 demo)
  7. 打开 UnityDemo 工程,打开 SampleScene,运行查看日志(检查 Main Camera 上是否有脚本丢失,如果有请挂载 GameMain.cs)

文档&例子&Demo

十分钟上手教程
了解更多

群友分享:
快速了解 GeekServer(Space_Dark 写)

代码片段

//采用注解注册Actor组件
[Comp(ActorType.Role)]
public class BagComp : StateComp<BagState>{}

//调用Actor组件函数(就像调用普通函数一样,无需关心多线程或入队)
var serverComp = await EntityMgr.GetCompAgent<ServerCompAgent>(ActorType.Server);
await serverComp.CheckCrossDay();

//定义状态(数据)
public class RoleState : DBState
{
    public string RoleName { get; set; }
    public long RoleId { get; set; }
    ...
}
//绑定组件
public class RoleComp : StateComponent<RoleState>{}
//绑定组件Agent(Agent类逻辑可全部热更新)
public class RoleCompAgent : StateComponentAgent<RoleComp, RoleState>{}

最佳实践

GeekServer 有严格的书写规范检查,如不符合规范编译直接报错
1.CompAgent 不能被二次继承,Agent 继承的需求理论上很少,如果有请采用组合模式
2.为 CompAgent 中需要被外部提供服务的接口,添加【Service】注解
3.CompAgent 中非【Threadsafe】的【Service】接口只能是异步函数
4.CompAgent 中不要书写构造函数,重写 Active 函数来完成初始化工作
5.大部分情况下你都应该使用 await 等待来书写逻辑,不需要等待的方法请加上【Discard】注解,如:通知全服玩家,就没必要等待一个通知完成后再通知下一个。 同时Source Generator在编译期间对标记了【Discard】的函数做了处理,内部直接返回了 Task.CompletedTask,所以外部使用下划线丢弃或是用 await 都是等价的,为了规范统一,可以全部使用 await。这样有个好处,就是可以在编译期间检查所有 Agent 中的代码,如有发现使用了弃元运算符(_ = DoSomething())则提示代码编写不符合规范。

public Task NotifyAllClient()
{
   for(int i=0; i<clients.count; i++)
   {
     //_ = NotifyOneClient(clients[i].roleId);
	 //对于标记了[Discard]的函数,等价于上面一行代码
	 await NotifyOneClient(clients[i].roleId);
   }
}

[Service]
[Discard]
public virtual Task NotifyOneClient(long roleId)
{
   //...
   //...
}

5.CompAgent 中为需要提供给外部访问接口,标记注解,如果不加外部又有访问,则会有线程安全问题,除非此接口本身就是线程安全的(标记了[ThreadSafe]注解)。

public class ServerCompAgent : StateCompAgent<ServerComp, ServerState>
{
    private Task TestScheduleTimer()
    {
        LOGGER.Debug("ServerCompAgent.TestSchedueTimer.延时1秒执行.每隔3秒执行");
        return Task.CompletedTask;
    }

    /// <summary>
    /// 由于此接口会提供给其他Actor访问,所以需要标记为[Service]
    /// </summary>
    /// <returns></returns>
    [Service]
    public virtual Task<int> GetWorldLevel()
    {
        return Task.FromResult(State.WorldLevel);
    }

}

更多异步书写规范请参考微软官方文档AsyncGuidance.md

推荐项目

GeekConfig 一键从 Excel 中导出模板代码和二进制数据

geekserver's People

Contributors

172672672 avatar jnumrc avatar leeveel avatar lixiuzhi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geekserver's Issues

RemoteBackup备份报错

服务器使用内嵌数据库,使用RemoteBackup备份到本地mongo数据库报错,修改app_config.json文件的数据库模式为1能连上mongo数据库。

init NLog config...
2023-05-04 23:31:32.0584 INFO 进入游戏主循环...
进入游戏主循环
2023-05-04 23:31:32.5009 INFO 初始化MongoDB服务完成 Url:mongodb://127.0.0.1:27017/?authSource=admin
2023-05-04 23:31:32.5009 INFO 初始化备份任务完成
2023-05-04 23:31:32.5009 INFO 下次定时回存时间 2023/5/4 23:31:42
2023-05-04 23:31:42.6878 ERROR StartNewTurn Throw Exception:MessagePack.MessagePackSerializationException: Failed to deserialize Geek.Server.Core.Storage.SaveTimestamp value.
---> MessagePack.MessagePackSerializationException: Unexpected msgpack code 146 (fixarray) encountered.
at MessagePack.MessagePackReader.ThrowInvalidCode(Byte code)
at MessagePack.MessagePackReader.TryReadMapHeader(Int32& count)
at MessagePack.MessagePackReader.ReadMapHeader()
at MessagePack.Formatters.Geek_Server_Core_Storage_SaveTimestampFormatter1.Deserialize(MessagePackReader& reader, MessagePackSerializerOptions options)
at MessagePack.MessagePackSerializer.Deserialize[T](MessagePackReader& reader, MessagePackSerializerOptions options)
--- End of inner exception stack trace ---
at MessagePack.MessagePackSerializer.Deserialize[T](MessagePackReader& reader, MessagePackSerializerOptions options)
at MessagePack.MessagePackSerializer.Deserialize[T](ReadOnlyMemory1 buffer, MessagePackSerializerOptions options, CancellationToken cancellationToken) at Geek.Server.Core.Serialize.Serializer.Deserialize[T](Byte[] data) in D:\Project\Unity3D\GeekServer\Geek.Server.Core\Serialize\Serializer.cs:line 13 at Geek.Server.Core.Storage.DB.Table1.Enumerator.MoveNext() in D:\Project\Unity3D\GeekServer\Geek.Server.Core\Storage\DB\Table.cs:line 192
at Geek.Server.RemoteBackup.Logic.Backup.Start() in D:\Project\Unity3D\GeekServer\Geek.Server.RemoteBackup\Logic\Backup.cs:line 46
at Geek.Server.RemoteBackup.Logic.BackupTask.StartNewTurn() in D:\Project\Unity3D\GeekServer\Geek.Server.RemoteBackup\Logic\BackupTask.cs:line 55
2023-05-04 23:31:42.6878 INFO 定时回存完成 耗时: 96.6496ms
2023-05-04 23:31:42.6878 INFO 下次定时回存时间 2023/5/4 23:34:42

ActorID定义询问

/// <summary>
/// 范围约定[为配合ActorID进行ID规则运算,请严格遵循该规则]
///            [此ID规则完全足够使用,当然你可以制定你自己规则]
///            
/// Actor类型有三种:
/// 1.ID全服唯一类型 [0,127]   [生成的ID合服之后也要保持唯一,这种理论上不会太多(角色,公会,一般为数据库的key),预留了128种类型]            
/// 2.ID仅需要单服唯一的Actor类型 [GeekServer为了方便统一使用了0-127这个范围,可自己根据情况调整]
/// 3.ID固定,每个服只会有一个的Actor类型 [129, 999] [这种ActorID会通过固定的规则生成serverId*1000 + actortype]
/// 非Actor类型的ID可以使用IdGenerator
/// </summary>

我是不是可以认为只有两种,一种是合服后保持不变,一种是跟随服务器id变化,上文提及的第二点其实是第三点,后方中阔号是说的第一点。
对第一种合服保持不变的,是不是要对数据库进行处理,保证多个服务器运行时生成ID不会冲突,请问这方面有什么技巧

动态模拟

1.大量用户登录,打开测试连接程序吧连接数量设置成一千
2.关闭测试连接程序,此时系统需要释放大量资源
3.这个时候再打开测试程序发现服务器有点处理不过来
不知道是不是可以通过设置Kestrel服务的相关配置解决,希望大佬解答
如果不是希望可以优化
1677654454215

如何对接websocket

作者你好,我想用于cocos creator小游戏的服务器框架,想实现一下ws协议,但苦于找不到入口,作者是否能提供一下修改建议,感激不尽

作者你好,我想问一下应该怎么操作数据?

我在现有的背包基础上,新加了一个Gm获得物品的协议,然后调用在BagCompAgent新增的方法 AddItems 对 State.ItemMap 进行数据操作, 但是发现返回的 ReqBagInfo 协议里只有新增的数据? 难道要像 PlayerInfo 那样 新增一个 state 去管理背包数据吗?那样的话怎么对背包数据进行存储呢?
另外,希望能出一个教程,这样用的人也会多起来!感谢!

Unity2021打开报错

Assets\Scripts\Framework\Bedrock\Protocal\ProtocolReader.cs(10,35): error CS0433: The type 'IAsyncDisposable' exists in both 'Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'

Assets\Scripts\Framework\Bedrock\Protocal\ProtocolWriter.cs(10,35): error CS0433: The type 'IAsyncDisposable' exists in both 'Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'

同类游戏服务器太多,建议出一个完整教程

我看你的更新日志,基本每隔几天就更新维护一下,真算得上是劳模,但也只积累了这些星星。如果用这些时间中的一部分,出个教程,从零开始写个游戏,这项目分分钟升到千星。关注使用的人多了,更利于解决实际问题,更利于这个项目的发展。

个人建议哈!

【Discard】注释生成的Warpper报错问题

1679598673554

不知道是配置问题,还是包没有更新问题,生成的Warpper代买报错的3个错误
8>D:\Project\ProjectD\Server\Geek.Server.Hotfix\Geek.Server.CodeGenerator\Geek.Server.CodeGenerator.Agent.AgentGenerator\ServerCompAgentWrapper.g.cs(19,51,19,78): error CS0029: 无法将类型“System.Threading.Tasks.ValueTask”隐式转换为“System.Threading.Tasks.Task”
8>D:\Project\ProjectD\Server\Geek.Server.Hotfix\Geek.Server.CodeGenerator\Geek.Server.CodeGenerator.Agent.AgentGenerator\ServerCompAgentWrapper.g.cs(19,51,19,78): error CS1662: 无法将 lambda 表达式 转换为预期委托类型,因为块中的某些返回类型不可隐式转换为委托返回类型
8>D:\Project\ProjectD\Server\Geek.Server.Hotfix\Geek.Server.CodeGenerator\Geek.Server.CodeGenerator.Agent.AgentGenerator\ServerCompAgentWrapper.g.cs(19,44,19,50): error CS8030: 转换为 void 返回委托的匿名函数不能返回值

客户端安卓真机接收消息问题

请求登录服务器会同时返回两条消息:1.客户端请求返回。2.错误码消息。当在编辑器下,完美收到2条消息返回。但是在安卓真机上,却只能收到一条消息。无法收到错误码消息。导致MsgWaiter无限等待中。

部署失败

在docker 中部署时,运行失败。报错找不到librocksdb.so

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.