ioGame 源码完全开放、最新文档阅读完全开放;使用完全自由、免费(遵守开源协议)。
ioGame 是一个轻量级的网络编程框架,适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景。
21.9
文档与日志
版本更新汇总
- [core] #294 增加范围内的广播接口 RangeBroadcaster,业务参数支持基础类型(协议碎片)的简化使用
- [core-对接文档] #293 广播文档构建器支持对参数的单独描述
- [light-game-room] #297 模拟系统创建房间,RoomCreateContext 的使用
- [light-game-room] #298 模拟系统创建房间,GameFlowContext 的使用
- [core] #301 FlowContext 更新元信息后,需要立即生效(跨服调用时)
- [内置 kit] 开放 TaskListener 接口
- 为 SimpleRoom aggregationContext 属性提供默认值,移除 RoomCreateContext 接口的 getAggregationContext 方法,以免产生误导。
[light-game-room]
为 SimpleRoom aggregationContext 属性提供默认值
#297,模拟系统创建房间,RoomCreateContext 的使用
移除 RoomCreateContext 接口的 getAggregationContext 方法,以免产生误导。
RoomCreateContext 增加默认重载
RoomCreateContext.of(); // 无房间创建者,通常表示系统创建RoomCreateContext.of(userId); // 房间创建者为 userId
#298 模拟系统创建房间,GameFlowContext 的使用
public void test() { Room room = ...; GameFlowContext context = GameFlowContext.of(room); ... 省略部分代码}
[core]
#294 增加范围内的广播接口 RangeBroadcaster,业务参数支持基础类型(协议碎片)的简化使用
public void testRangeBroadcaster(FlowContext flowContext) { // ------------ object ------------ // 广播 object DemoBroadcastMessage message = new DemoBroadcastMessage(); message.msg = "helloBroadcast --- 1"; RangeBroadcaster.of(flowContext) .setResponseMessage(cmdInfo, message); // 广播 object list List<DemoBroadcastMessage> messageList = List.of(message); RangeBroadcaster.of(flowContext) .setResponseMessageList(cmdInfo, messageList); // ------------ int ------------ // 广播 int int intValue = 1; RangeBroadcaster.of(flowContext) .setResponseMessage(cmdInfo, intValue); // 广播 int list List<Integer> intValueList = List.of(1, 2); RangeBroadcaster.of(flowContext) .setResponseMessageIntList(cmdInfo, intValueList); // ------------ long ------------ // 广播 long long longValue = 1L; RangeBroadcaster.of(flowContext) .setResponseMessage(cmdInfo, longValue); // 广播 long list List<Long> longValueList = List.of(1L, 2L); RangeBroadcaster.of(flowContext) .setResponseMessageLongList(cmdInfo, longValueList); // ------------ String ------------ // 广播 String String stringValue = "1"; RangeBroadcaster.of(flowContext) .setResponseMessage(cmdInfo, stringValue); // 广播 String list List<String> stringValueList = List.of("1L", "2L"); RangeBroadcaster.of(flowContext) .setResponseMessageStringList(cmdInfo, stringValueList); // ------------ boolean ------------ // 广播 boolean boolean boolValue = true; RangeBroadcaster.of(flowContext) .setResponseMessage(cmdInfo, boolValue); // 广播 boolean list List<Boolean> boolValueList = List.of(true, false); RangeBroadcaster.of(flowContext) .setResponseMessageBoolList(cmdInfo, boolValueList);}
#301 FlowContext 更新元信息后,需要立即生效(跨服调用时)
在此之前,更新元信息后,并不会将元信息同步到 FlowContext 中,只会将元信息同步到游戏对外服中;所以在更新元信息后,紧接着执行跨服调用是不能获取新的元信息内容的。
当前 issues 会对这部分做增强,也就是在更新元信息后,会将元信息同步到 FlowContext 中;这样,在后续的跨服调用中也能获取到最新的元信息。
void test1(FlowContext flowContext) { // 获取元信息 MyAttachment attachment = flowContext.getAttachment(MyAttachment.class); attachment.nickname = "渔民小镇"; // [同步]更新 - 将元信息同步到玩家所在的游戏对外服中 flowContext.updateAttachment(attachment); // 跨服请求 CmdInfo helloCmdInfo = CmdInfo.of(1, 1); flowContext.invokeModuleMessage(helloCmdInfo);}@ActionController(1)public class DemoFightAction { @ActionMethod(1) void hello(FlowContext flowContext) { // 可以得到最新的元信息 MyAttachment attachment = flowContext.getAttachment(MyAttachment.class); log.info("{}", attachment.nickname); }}
#293 广播文档构建器支持对参数的单独描述
private void extractedDco(BarSkeletonBuilder builder) { // UserCmd builder.addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.enterSquare)) .setDataClass(SquarePlayer.class) .setDescription("新玩家加入房间,给房间内的其他玩家广播") ).addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.offline)) .setDataClass(LongValue.class, "userId") .setDescription("有玩家下线了") );}
下面是生成后的对接文档预览
==================== 游戏文档格式说明 ====================https://www.yuque.com/iohao/game/irth38#cJLdC==================== FightHallAction 大厅(类似地图) ==================== 路由: 1 - 2 --- 【进入大厅】 --- 【FightHallAction:94】【enterSquare】 方法参数: EnterSquare enterSquare 进入大厅 方法返回值: ByteValueList<SquarePlayer> 所有玩家 广播推送: SquarePlayer ,(新玩家加入房间,给房间内的其他玩家广播) 路由: 1 - 5 --- 【玩家下线】 --- 【FightHallAction:154】【offline】 方法返回值: void 广播推送: LongValue userId,(有玩家下线了)
[内置 kit]
开放 TaskListener 接口,TaskListener 是 TaskKit 相关的任务监听接口。
TaskListener 任务监听回调,使用场景有:一次性延时任务、任务调度、轻量可控的延时任务、轻量的定时入库辅助功能 …等其他扩展场景。这些使用场景都有一个共同特点,即监听回调。接口提供了 4 个方法,如下
- CommonTaskListener.onUpdate(),监听回调
- CommonTaskListener.triggerUpdate(),是否触发 CommonTaskListener.onUpdate() 监听回调方法
- CommonTaskListener.onException(Throwable) ,异常回调。在执行 CommonTaskListener.triggerUpdate() 和 CommonTaskListener.onUpdate() 方法时,如果触发了异常,异常将被该方法捕获。
- CommonTaskListener.getExecutor(),指定执行器来执行上述方法,目的是不占用业务线程。
更多介绍与使用,请阅读 TaskKit (yuque.com)
ioGame 使用趋势数据
关注 ioGame 的游戏服务器开发者持续增多,2022-09 ~ 至今各月的统计数据;
这里的统计信息是关于开发者关注 ioGame 框架相关的,从统计数据中可以看出,由于 ioGame 上手简单,功能强大等优点,得到了众多开发者的关注。如果你想知道 ioGame 有没有人在使用,可以先到这里看下统计数据、开发者的评价与讨论。
https://www.yuque.com/iohao/game/gpxk93#TwVa8
这里展示了每月的统计数据,统计数据来源于语雀后台,这些数据都是真实的、客观存在的、活的。
通过统计数据,我们可以看到每天会有很多开发者在访问 ioGame 的在线文档,并且这些统计数据不是来源于口嗨的,也不是主观创造的。
所以,还在犹豫要不要使用 ioGame 的开发者们,更应该讨论的是 “为什么这些开发者会选择使用 ioGame”,而不是 ioGame 有没有人在使用的问题。
ioGame 网络游戏服务器框架简介
- 无锁异步化、事件驱动的架构设计;轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式
- 通过 ioGame 可以很容易的搭建出一个集群无中心节点、集群自动化、多进程的分布式游戏服务器
- 包体小、启动快、内存占用少、更加的节约、无需配置文件、提供了优雅的路由访问权限控制
- 可同时支持多种连接方式:WS、UDP、TCP… 等;框架已支持全链路调用日志跟踪特性
- 让开发者用一套业务代码,能轻松切换和扩展不同的通信协议:Protobuf、JSON
- 近原生的性能;业务框架在单线程中平均每秒可以执行 1152 万次业务逻辑
- 代码即联调文档、JSR380 验证、断言 + 异常机制 = 更少的维护成本
- 框架具备智能的同进程亲和性;开发中,业务代码可定位与跳转
- 架构部署灵活性与多样性:既可相互独立,又可相互融合
- 可同时与同类型的多个游戏逻辑服通信并得到数据
- 逻辑服之间可相互跨进程、跨机器进行通信
- 支持玩家对游戏逻辑服进行动态绑定
- 能与任何其他框架做融合共存
- 对 webMVC 开发者友好
- 无 spring 强依赖
- 零学习成本
- javaSE
ioGame 的组成
ioGame 由 [网络通信框架] 和 [业务框架] 组成
- 网络通信框架:职责是各服务器之间的网络通信
- 业务框架:职责是业务逻辑的处理方式和编写方式
网络通信框架
SOFABolt 是蚂蚁金融服务集团开发的一套基于 Netty 实现的网络通信框架。
- 为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上,而不是过多的纠结于网络底层 NIO 的实现以及处理难以调试的网络问题,Netty 应运而生。
- 为了让中间件开发者能将更多的精力放在产品功能特性实现上,而不是重复地一遍遍制造通信框架的轮子,SOFABolt 应运而生。
Bolt 名字取自迪士尼动画 – 闪***,是一个基于 Netty 最佳实践的轻量、易用、高性能、易扩展的通信框架。
业务框架
如果说 sofa-bolt 是为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上。而业务框架正是解决业务逻辑如何方便实现这一问题上。业务框架是游戏框架的一部分,职责是简化程序员的业务逻辑实现,业务框架使程序员能够快速的开始编写游戏业务。
业务框架对于每个 action (即业务的处理方法) 都是通过 asm 与 Singleton、Flyweight 、Command 等设计模式结合,对 action 的获取上通过 array 来得到,是一种近原生的方式。
单线程中,业务框架平均每秒可以执行 1152 万次业务逻辑。
无锁异步化与事件驱动的架构设计、集群无中心节点、自带负载均衡、分布式支持、可动态增减机器、避免类爆炸的设计;
名称 |
扩展方式 |
职责 |
游戏对外服 |
分布式 |
与玩家连接、交互 |
游戏逻辑服 |
分布式 |
处理具体业务逻辑 |
Broker(游戏网关) |
集群 |
调度和转发任务; |
通过 ioGame 可以使得游戏编程变得简单,下面是一个业务示例
@ActionController(1)public class DemoAction { @ActionMethod(0) public HelloReq here(HelloReq helloReq) { // 业务数据 var newHelloReq = new HelloReq(); newHelloReq.name = helloReq.name + ", I'm here "; return newHelloReq; } // 注意,这个方法只是为了演示而写的;(ioGame21 开始支持) // 效果与上面的方法一样,只不过是用广播(推送)的方式将数据返回给请求方@ActionMethod(0) public void here(HelloReq helloReq, FlowContext flowContext) { // 业务数据 var newHelloReq = new HelloReq(); newHelloReq.name = helloReq.name + ", I'm here "; flowContext.broadcastMe(newHelloReq); } // 跨服调用示例,下面分别展示了同步与异步回调的写法 void testShowInvokeModule(FlowContext flowContext) { /* * 框架为跨服请求提供了同步、异步、异步回调的编码风格 api。(ioGame21 开始支持) */ var cmdInfo = CmdInfo.of(1,0); var yourData = ... 你的请求参数 // 跨服请求(异步回调 - 无阻塞)-- 路由、请求参数、回调。 flowContext.invokeModuleMessageAsync(cmdInfo, yourData, responseMessage -> { var helloReq = responseMessage.getData(HelloReq.class); // --- 此异步回调,具备全链路调用日志跟踪 --- log.info("异步回调 : {}", helloReq); }); // 跨服请求(同步 - 阻塞)-- 路由、请求参数。 ResponseMessage responseMessage = flowContext.invokeModuleMessage(cmdInfo, yourData); var helloReq = responseMessage.getData(HelloReq.class); log.info("同步调用 : {}", helloReq); }}
有了以上信息,游戏开发者可以很快的定位问题。如果没有可视化的信息,开发中会浪费很多时间在前后端的沟通上。问题包括:
- 是否传参问题 (游戏前端说传了)
- 是否响应问题(游戏后端说返回了)
- 业务执行时长问题 (游戏前端说没收到响应, 游戏后端说早就响应了)
其中代码导航可以让开发者快速的跳转到业务类对应代码中,在多人合作的项目中,可以快速的知道业务经过了哪些方法的执行,使得我们可以快速的进行阅读或修改;
框架内置的其他功能
内置多种可选模块,可按需选择,以方便应用开发:
- 领域事件 (轻量级单机最快 MQ — disruptor;通过领域事件模块,可为你的系统实现类似 Guava-EventBus、Spring 事件驱动模型 ApplicationEvent、业务解耦、规避并发、不阻塞主线程… 等,各种浪操作)
- 任务延时器 (将来某个时间可对任务进行执行、暂停、取消等操作,并不是类似 Quartz 的任务调度)
- 多环境切换 (不同运行环境下的配置支持)
- light-jprotobuf (补足 jprotobuf 不能让多个对象在单个 .proto 源文件中生成的需求,并简化 jprotobuf 对源文件的注释)
- 分布式锁 (基于 Redisson 的简单实现)
- room 桌游、房间类,该模块是桌游类、房间类游戏的解决方案。比较适合桌游类、房间类的游戏基础搭建,基于该模型可以做一些如,炉石传说、三国杀、斗地主、麻将 …等类似的桌游。或者说只要是房间类的游戏,该模型都适用。比如,CS、泡泡堂、飞行棋、坦克大战 …等。
内置的其他功能:
- 心跳相关
- 用户上线、离线相关的钩子方法
- UserSessions (对所有用户 UserSession 的管理,统计在线用户等)
- UserSession (与 channel 是 1:1 的关系,可取到对应的 userId、channel 等信息。)
- 登录相关(提供重复登录、顶号等相关增强功能)
- 业务参数基础类型 自动装箱、拆箱(解决协议碎片)
适合人群?
- 长期从事 web 内部系统开发人员, 想了解游戏的
- 刚从事游戏开发的
- 未从事过游戏开发,但却对其感兴趣的
- 对设计模式在实践中的应用和 sofa-bolt 有兴趣的学习者
- 可以接受新鲜事物的
- 想放弃祖传代码的
推荐实际编程经验一年以上的人员。
ioGame 提供了丰富的在线高质量使用文档,为你的团队助力,带上你们的小伙伴一起,这样就不用手把手的教了。