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 个方法,如下

  1. CommonTaskListener.onUpdate(),监听回调
  2. CommonTaskListener.triggerUpdate(),是否触发 CommonTaskListener.onUpdate() 监听回调方法
  3. CommonTaskListener.onException(Throwable) ,异常回调。在执行 CommonTaskListener.triggerUpdate() 和 CommonTaskListener.onUpdate() 方法时,如果触发了异常,异常将被该方法捕获。
  4. 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 的数据

netty 高性能游戏服务器框架;ioGame 21.9 真.轻量级网络编程框架发布插图


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、泡泡堂、飞行棋、坦克大战 …等。

 

内置的其他功能:


适合人群?

  1. 长期从事 web 内部系统开发人员, 想了解游戏的
  2. 刚从事游戏开发的
  3. 未从事过游戏开发,但却对其感兴趣的
  4. 对设计模式在实践中的应用和 sofa-bolt 有兴趣的学习者
  5. 可以接受新鲜事物的
  6. 想放弃祖传代码的

推荐实际编程经验一年以上的人员。

ioGame 提供了丰富的在线高质量使用文档,为你的团队助力,带上你们的小伙伴一起,这样就不用手把手的教了。

免责声明:本文系转载,版权归原作者所有;旨在传递信息,不代表一休教程网的观点和立场。