Skip to content

轻量级游戏服务器框架 ioGame 17.1.38 发布

Compare
Choose a tag to compare
@iohao iohao released this 18 Apr 03:13
· 420 commits to main since this release

主要更新

#46 action 业务参数与返回值增加 List 支持

使用文档 https://www.yuque.com/iohao/game/ieimzn#Aqc1C

action 支持 List 参数与返回值,可以有效的减少协议碎片、减少工作量等。在没有支持 List 之前的代码,如果想要传输一个列表的数据,通常需要将 pb 对象包装到另一个 pb 响应对象中。

让我们先看一个示例,这个示例中 action 方法的的逻辑很简单,将查询到的数据列表给到请求端。由于之前不支持 List 返回值,开发者想要将列表中的数据给到请求端,还需要额外的定义一个与之对应的响应类,只有这样才能将列表数据给到请求端。

我们可以想象一下,如果你的系统中有很多固定的配置数据,比如装备、道具、活动信息、英雄人物介绍、敌人相关信息、地图信息、技能信息、宠物基本信息...等等,通常会有几十、上百个这样的响应对象。

为了将这些固定的配置数据给到请求端,而建立与之对应的响应对象,想想这是一件多么无聊的一件事情。这些多出来的响应对象,就是协议碎片,是一种可有可无的协议;此外还有如下缺点:

  • 将会变成干扰项
  • 增加维护成本
  • 增加工作量(每次有新的配置表都要新建、在每个 action 中,都要创建这个响应对象)

不使用 List 时的写法

@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class Animal {
    /** id */
    int id;
}

@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class AnimalResponse {
    List<Animal> animals;
}

@ActionController(3)
public class HallAction {
    @ActionMethod(10)
    public AnimalResponse listAnimal1() {
        // 查询出列表
        var list = IntStream.range(1, 4).mapToObj(id -> {
            Animal animal = new Animal();
            animal.id = id;
            return animal;
        }).collect(Collectors.toList());

        // 将列表存放到 Animal 的响应对象中
        AnimalResponse animalResponse = new AnimalResponse();
        animalResponse.animals = list;

        return animalResponse;
    }
}

通过上面的介绍,知道协议碎片是多么恐怖的一件事了把。其实我们的需求也很简单,只是想把列表中的数据给到请求端就可以了。此时,我们可以利用 action 将列表数据通过 List 直接返回,这样可以避免上面所说的各种缺点。同时,还可以让我们的代码更加的简洁,这种方式可以使前端与后端都受益。

用更少的代码实现了同样的功能,减少了工作量,避免了协议碎片。这样,开发者就不在需要额外的建立一个与之对应的响应协议了;当使用了框架提供的 List 返回值后,可以帮助你的系统减少几十、上百个类似 xxxResponse 的协议。

来,让我们看看修改后的代码是有多么简洁的吧。这种编码方式,即使你是一个新手,也能快速的看懂;

Action 使用 List 返回数据

@ActionController(3)
public class HallAction {
    @ActionMethod(9)
    public List<Animal> listAnimal() {
        // 查询出列表
        return IntStream.range(1, 4).mapToObj(id -> {
            Animal animal = new Animal();
            animal.id = id;
            return animal;
        }).collect(Collectors.toList());
    }
}

原理
ioGame 在游戏对外服的协议中,提供了一个公共的 message,用于存放 List 数据。

// pb 对象 list 包装类
message ByteValueList {
  // pb 对象 List、pb 对象 Array
  repeated bytes values = 1;
}

游戏对外服协议请看:https://www.yuque.com/iohao/game/zfg3ci

#79 light-jprotobuf 模块支持枚举

生成的 PB 文件

// 动物
message Animal {
  // id
  int32 id = 1;
  // 动物类型 - 枚举测试
  AnimalType animalType = 2;
}

// 动物类型
enum AnimalType {
  // 鸟
  BIRD = 0;
  // 猫
  CAT = 1;
}

#84 生成proto文件时,内容的顺序总是产生变化

实际使用过程中发现一个问题如下:当协议没有任何变化时,生成的协议文件依然会产生顺序变化。
例如:当前的协议定义有 A,B,C 三个类。如果对协议进行多次生成,产生的proto文件内的定义顺序可能是:A,C,B 或者 B,C,A。

标记废弃的
将 IoGameGlobalSetting�.me() 方法标记为废弃的,将 IoGameGlobalSetting 内的方法改为静态的。

其他更新
<netty.version>4.1.91.Final</netty.version>
优化文档生成、控制台打印。
ExternalMessage.proto 新增 message ByteValueList,用于接收与发送 List 类型的数据

... 省略部分代码
// pb 对象 list 包装类
message ByteValueList {
  // pb 对象 List、pb 对象 Array
  repeated bytes values = 1;
}

注意事项
此版本在游戏对外服协议中新增了 message ByteValueList 来支持 action 返回 List 类型,因此需要前端同学同步一下协议文件。
对外服的协议说明: https://www.yuque.com/iohao/game/xeokui


ioGame 简介

你是否想要开发一个高性能、稳定、易用、自带负载均衡、避免类爆炸设计、可跨进程跨机器通信、集群无中心节点、集群自动化、有状态多进程的分步式的网络游戏服务器呢?如果是的话,这里向你推荐一个由 java 语言编写的网络游戏服务器框架 ioGame。下面将会从多个方面来对框架做一些简单的介绍。

ioGame 是一个 java 网络游戏服务器框架,有以下特点:

  • 无锁异步化、事件驱动的架构设计
  • 支持 websocket 和 socket 两种通信协议
  • 支持 protobuf、json 等不同的通信协议
  • 集群无中心节点、集群自动化、分布式的设计
  • 轻量级,不依赖第三方中间件或数据库就能支持集群、分布式
  • 提供多种通讯方式,且逻辑服之间可以相互跨机器通信
  • 与 spring 和其他框架融合方便
  • 学习成本低,开发体验好
  • 支持多服单进程、多服多进程的启动和部署方式
  • 提供游戏文档生成的辅助功能
  • 包体小、启动快、内存占用少
  • 提供优雅的路由访问权限控制
  • 提供了灵活的线程扩展、设置

ioGame 是一个专为网络游戏服务器设计的轻量级框架,它可以帮助你快速地搭建和运行自己的游戏服务器。它适用于各种类型和规模的网络游戏,无论是 H5、手游还是 PC 游戏,无论是简单的聊天室,还是复杂的全球同服、回合制游戏、策略游戏、放置休闲游戏、即时战斗、MMORPG 等,ioGame 都可以满足你的需求。

ioGame 在打包、内存占用、启动速度等方面也是优秀的。打 jar 包后大约 15MB,应用通常会在 0.x 秒内完成启动,内存占用小。详细请看 快速从零编写服务器完整示例

在生态融合方面,ioGame 可以很方便的与 spring 集成(5 行代码);除了 spring 外,还能与任何其他的框架做融合,从而使用其他框架的相关生态。

在轻量级方面,ioGame 不依赖任何第三方中间件或数据库就能支持集群、分布式,只需要 java 环境就可以运行。这意味着在使用上简单了,在部署上也为企业减少了部署成本、维护难度。使用 ioGame 时,只需一个依赖即可获得整个框架,而无需在安装其他服务,如: Nginx、Redis、MQ、Mysql、ZooKeeper、Protobuf协议编译工具 ... ...等。

在通讯方式方面,大部分框架只能支持推送(广播)这一类型的通讯方式;而 ioGame 则提供了 3 种类型的通讯方式,分别是推送、单次请求处理、逻辑服之间相互通信。其中逻辑服之间相互通信,除了可以让我们跨机器通信外,还能与同类型多个游戏逻辑服同时通信并得到结果;

在通信方面,ioGame 让开发者用一套业务代码,同时支持 WebSocket 和 TCP 两种通信协议,无需做任何改动。这意味着一个游戏服务器可以同时接入 WebSocket 和 TCP 的游戏客户端。

在通信协议方面,ioGame 让开发者用一套业务代码,就能轻松切换和扩展不同的通信协议,如 Protobuf、JSON 等。只需一行代码,就可以从 Protobuf 切换到 JSON,无需改变业务方法。

在集群方面,ioGame 的 Broker (游戏网关)采用无中心节点、自动化的集群设计,所有节点平等且自治,不存在单点故障。集群能够自动管理和弹性扩缩,节点加入或退出时,能够自动保证负载均衡和数据一致性,不影响服务可用性。

在分布式方面,ioGame 的逻辑服使用了分布式设计思想,将服务器分为游戏对外服、游戏逻辑服等不同层次,并且每一层都有明确的职责和接口。这样可以提高代码可读性和可维护性,并且方便进行水平扩展

在学习成本方面,ioGame 的学习成本非常低,可以说是零学习成本,即使没有游戏编程经验,也能轻松上手。开发者只需掌握普通的 java 方法或 webMVC 相关知识,就能用框架开发业务。框架不要求开发者改变编码习惯,而是自身适应开发者的需求。

在开发体验方面,ioGame 非常注重开发者的开发体验;框架提供了 JSR380验证、断言 + 异常机制、业务代码定位... ...等诸多丰富的功能,使得开发者的业务代码更加的清晰、简洁;

在业务的并发方面,框架为开发者解决了单个玩家的并发问题,也提供了解决同一房间或业务内多个玩家并发问题的解决方法;框架在线程的扩展性上提供了友好的支持,并不是只能提供呆板的线程数量设置;详细请看 ioGame 线程相关

在分布式开发体验方面,通常在开发分布式应用时是需要启动多个进程的。这会让调试与排查问题变得非常困难,从而降低开发者的效率、增加工作量等,这也是很多框架都解决不了的问题,但 ioGame 做到了!ioGame 支持多服单进程的启动方式,这使得开发者在开发和调试分步式系统时更加简单。

与前端对接联调方面,ioGame 提供了游戏文档生成的辅助功能,可以做到代码即对接文档。简单地说,当业务代码编写完后,框架会自动生成最新的文档。如果没有游戏文档的生成,那么你将要抽出一些时间来编写、维护对接文档的工作,而且当团队人数多了之后,文档就会很乱、不同步、不是最新的、忘记更新等情况就会出现。

在部署方面,ioGame 支持多服单进程的方式部署,也支持多服多进程多机器的方式部署;在部署方式上可以随意的切换而不需要更改代码。日常中我们可以按照单体思维开发,到了生产可以选择使用多进程的方式部署。

开发者基于 ioGame 编写的项目模块,通常是条理清晰的,得益于框架对路由的合理设计,同时也为路由提供了优雅的访问权限控制。当我们整理好这些模块后,对于其他开发者接管项目或后续的维护中,会是一个不错的帮助(模块的整理与建议)。或许现阶段你感受不到这块的威力,随着你深入地使用实践就能体会到这么设计的诸多好处与优势。

开发者基于 ioGame 编写的项目,通常是语法简洁的、高性能的、低延迟的;框架最低要求使用 JDK17,这样即可以让项目享受到 ZGC 带来的改进,还能享受语法上的简洁。从 JDK17 开始 ZGC 远低于其亚毫秒级暂停时间的目标,可以在不影响游戏速度的情况下,清理掉多余的内存。这样就不会出现卡顿或者崩溃的问题了,相当于在项目中变相的引入了一位 JVM 调优大师,详细请看 JDK 17 垃圾回收 GC 性能飞跃提升

综上所述,ioGame 是一个非常适合网络游戏开发的框架。可以让你轻松地创建高性能、低延迟、易扩展的游戏服务器,并且节省时间和资源。如果你想要快速地开发出令人惊艳的网络游戏,请不要犹豫,立即选择 ioGame 吧!框架屏蔽了很多复杂且重复性的工作,并可为项目中的功能模块结构、开发流程等进行清晰的组织定义,减少了后续的项目维护成本。

相信你已经对 ioGame 有了一个初步的了解,虽然还有很多丰富的功能与特性没有介绍到,但你可以通过后续的实践过程中来深入了解。感谢你的阅读,并期待你使用 ioGame 来打造自己的游戏服务器。