Java Netty 游戏服务器框架 ioGame 17.1.26,业务框架与网络通信框架解耦
主要更新
业务框架与网络通信框架解耦
新增 ChannelContext 通信通道接口,用于对 bolt AsyncContext、netty Channel 的包装,这样可以使得业务框架与网络通信框架解耦,为将来 ioGame 实现绳量级架构的使用做准备。
移除 FlowAttr.asyncContext 动态属性,由 FlowAttr.channelContext 代替。
业务框架模块移除网络相关的依赖 bolt、netty 等。
游戏对外服 netty 编排业务钩子接口
新增 ChannelPipelineHook netty 业务编排的处理器钩子接口,用于游戏对外服。
ExternalServerBuilder 新增 channelPipelineHook ,用于自定义 netty 业务编排的处理器。
废弃标记 ExternalServerBuilder.channelHandlerProcessors 属性及其相关地方为过期,由 ChannelPipelineHook 来代替,使用示例如下。
使用示例代码
public class ExternalServerBuilderApplication { public static void main(String[] args) { // netty ChannelHandler 编排 var myChannelPipelineHook = new ChannelPipelineHook() { @Override public void initChannelPipeline(ChannelPipeline pipeline) { pipeline.addLast("ExternalBizHandler", new ExternalBizHandler()); // pipeline.addFirst("ssl", ssl) } }; // 游戏对外服构建器 ExternalServerBuilder builder = ExternalServer.newBuilder(10100); builder.channelPipelineHook(myChannelPipelineHook); } }
通常情况下,这样的编排方式也会更加清晰,因为代码统一在这里做编排了。开发者在自定义业务编排时,可以通过这个钩子接口,比如添加一个 SSL。
注意事项:在调用 hook 前,会经过 ExternalChannelInitializerCallback.initChannelPipeline(SocketChannel) ,
ExternalChannelInitializerCallback 接口的实现类有
- ExternalChannelInitializerCallbackWebsocket
- ExternalChannelInitializerCallbackTcp
这些实现类中,会给 ChannelPipeline 添加上一些默认的处理器,通常是编解码相关的。
其他
移除扩展相关模块 borker-starter-ext
maven pom
ioGame 已经上传到中央仓库,如果无法下载最新的,请暂时注释阿里云代理。
https://search.maven.org/search?q=a:bolt-run-one
ioGame 是轻量级的网络游戏服务器框架,ioGame 没有中间件的强依赖,即无需安装任何其他的中间件产品;此时,你只需一个依赖即可获得整个框架,并同时支持开头介绍的全部功能特性。
<dependency> <groupId>com.iohao.game</groupId> <artifactId>bolt-run-one</artifactId> <version>${ioGame.version}</version> </dependency>
ioGame 网络游戏服务器框架简介
- 国内首个基于蚂蚁金服 SOFABolt 的 java 网络游戏服务器框架;无锁异步化、事件驱动的架构设计
- 通过 ioGame 可以很容易的搭建出一个集群无中心节点、有状态多进程的分步式游戏服务器
- 无中间件依赖、代码即文档、JSR380、断言 + 异常机制 = 更少的维护成本、开发成本
- 同样的一套业务代码无需变更,可以支持多种协议:protobuf、json,并且可扩展
- 同样一套业务代码无需变更,可以支持多种通信协议:websocket、socket
- 轻量级、启动快、更节约、简单、开箱即用、无配置文件、超高性能
- 近原生的快、业务框架平均每秒可以执行 1152 万次业务逻辑
- 在业务开发中自带神级特性:业务代码访问定位与跳转
- 架构部署多样性:即可相互独立,又可相互融合
- 各个逻辑服之间可以相互的进行跨进程通信
- 可同时与同类型多个游戏逻辑服通信
- 支持玩家动态绑定逻辑服节点
- 对 webMVC 开发者友好
- 无 spring 强依赖
ioGame 是一个由 java 语言编写的网络游戏服务器框架。支持 websocket、tcp ,适用于全球同服、回合制游戏、策略游戏、即时战斗等游戏服务器的开发。具有高性能、稳定、易用易扩展、超好编程体验等特点。可做为 H5、手游、端游的 java 游戏服务器。
ioGame 是轻量级的网络游戏服务器框架,在使用 ioGame 时,只需一个依赖即可获得整个框架,而无需在安装其他服务,如: Nginx、Redis、MQ、Mysql、ZooKeeper、Protobuf协议编译工具 ... ...等。简单点说,就是无需安装其他产品,就能支持开头介绍的内容特性;这意味着在使用上简单了,在部署上也为企业节约了成本。
通过 ioGame 你可以很容易的搭建出一个稳定、高性能、集群无中心节点、分步式、自带负载均衡、跨进程通信、避免类爆炸设计的网络游戏服务器。游戏框架借助于蚂蚁金服 sofa-bolt 通信框架来提供通信方面的稳定与高性能。
在 ioGame 中能让你遗忘 Netty,你几乎没有机会能直接的接触到 Netty 的复杂,但却能享受 Netty 带来的高性能。对开发者要求极低,为开发者节约开发时间。
即使之前没有游戏编程的经验,也能参与到游戏编程中。如果你之前具备一些游戏开发或者 webMVC 相关的知识,则会更容易上手游戏服务器的开发。
ioGame 可以做到同样的一套业务代码,无需开发者做代码的变更,就能同时支持多种通信协议:websocket、socket。简单点说,就是一个游戏服务端的项目,具有同时对接 socket 和 websocket 游戏客户端的能力。
ioGame 可以做到同样的一套业务代码,无需开发者做代码的变更,就能支持多种协议的切换,如:protobuf、json。协议的切换是简单的,只需要一行代码。简单点说,如果开发者的项目之前使用的是 json 数据来传输的,以后想改用 protobuf 来传输,是不需要改变业务方法的。框架除了内置支持的 protobuf、json 协议外,开发者还可以对协议进行扩展。
开发者基于 ioGame 编写的项目、模块通常是条理清晰的,得益于框架对路由的合理设计。当我们整理好这些模块后,对于其他开发者接管项目或后续的维护中,会是一个不错的帮助(模块的整理与建议)。
基于 ioGame 编写的项目,通常是语法简洁的、高性能的、低延迟的。框架最低要求使用 JDK17,这样即可以让项目享受到 ZGC 带来的改进,还能享受语法上的简洁。从 JDK17 开始 GC 已经处理得越来越好了,JDK17 中的 ZGC 远低于其亚毫秒级暂停时间的目标;当开发者使用 JDK17 时,相当于在你们的项目中变相的引入了一位 JVM 调优大师,详细请看 JDK17 垃圾回收GC性能飞跃提升。
在部署上,支持多服单进程的方式部署(类似单体应用、在分步式开发时,调试更加方便)、也支持多服多进程多机器的方式部署。在部署方式上可以随意切换,而不需要更改代码;日常中按照单体思维开发,在生产上可以使用多进程的方式部署;当然,也可以使用单进程的方式部署。
ioGame 框架职责清晰、业务开发几乎零学习成本、源码有高质量注释、示例多、使用文档多,开发体验最佳、业务代码自动生成与游戏前端对接的文档、逻辑服之间可跨进程跨机器通信、业务代码定位--神级特性、异常机制。提供了丰富的在线高质量使用文档,为你的团队助力,带上你们的小伙伴一起,这样就不用手把手的教了。
ioGame 可以很方便的与 spring 集成(5 行代码)。
综上,ioGame 屏蔽了很多复杂且重复性的工作;超棒的开发体验,使用简单,无中间件依赖,只需一个依赖即可获得整个框架;减少了学习成本、减少了使用成本、减少了开发者的工作量、减少了项目的运维成本。并可为项目中的功能模块结构、开发流程等进行清晰的组织定义,减少了后续的项目维护成本。从而让开发团队更方便快捷高效的开发游戏项目。
ioGame 是国内首个基于蚂蚁金服 sofa-bolt 的网络游戏框架,游戏框架由 [网络通信框架] 和 [业务框架] 组成。
- 网络通信框架:职责是各服务器之间的网络通信
- 业务框架:职责是业务逻辑的处理方式和编写方式
网络通信框架 - SOFABolt
SOFABolt 是蚂蚁金融服务集团开发的一套基于 Netty 实现的网络通信框架。
- 为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上,而不是过多的纠结于网络底层 NIO 的实现以及处理难以调试的网络问题,Netty 应运而生。
- 为了让中间件开发者能将更多的精力放在产品功能特性实现上,而不是重复地一遍遍制造通信框架的轮子,SOFABolt 应运而生。
Bolt 名字取自迪士尼动画 - 闪电狗,是一个基于 Netty 最佳实践的轻量、易用、高性能、易扩展的通信框架。
业务框架
如果说 sofa-bolt 是为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上。而业务框架正是解决业务逻辑如何方便实现这一问题上。业务框架是游戏框架的一部分,职责是简化程序员的业务逻辑实现,业务框架使程序员能够快速的开始编写游戏业务。
业务框架对于每个 action (即业务的处理方法) 都是通过 asm 与 Singleton、Flyweight 、Command 等设计模式结合,对 action 的获取上通过 array 来得到,是一种近原生的方式。
单线程下,业务框架平均每秒可以执行 1152 万次业务逻辑。
架构简图
通过 ioGame 你可以很容易的搭建出一个集群、分步式的网络游戏服务器!
无锁异步化与事件驱动的架构设计、集群无中心节点、自带负载均衡、分布式支持、可动态增减机器、避免类爆炸的设计;
图中的每个对外服、每个游戏逻辑服、每个 broker (游戏网关)都可以在单独的进程中部署,逻辑服之间可以跨进程通信(对外服也是逻辑服的一种)。
游戏网关集群
broker (游戏网关)支持集群的方式部署,集群的使用是简单的,集群无中心节点、自带负载均衡。ioGame 本身就包含服务注册,你不需要外接一个服务注册中心,如 Eureka,ZooKeeper 等(变相的节约服务器成本)。
通过 broker (游戏网关) 的介入,之前非常复杂的负载均衡设计,如服务注册、健康度检查(后续版本提供)、到服务端的连接维护等这些问题,在 ioGame 中都不需要了,结构也简单了很多。实际上单台 broker (游戏网关) 性能已经能够满足了,因为游戏网关只做了转发。
逻辑服
逻辑服通常说的是游戏对外服和游戏逻辑服。逻辑服可以有很多个,逻辑服扩展数量的理论上限是 netty 的连接上限。
游戏对外服
对外服保持与用户(玩家)的长连接。先来个假设,假如我们的一台硬件支持我们建立用户连接的上限是 5000 人,当用户量达到 7000 人时,我们可以多加一个对外服务器来进行分流减压。由于游戏对外服扩展的简单性,意味着支持同时在线玩家可以轻松的达到百万、千万甚至更多。
即使我们启动了多个游戏对外服,开发者也不需要关心这些玩家连接到了哪个游戏对外服的问题,这些玩家总是能接收到广播(推送)消息的,因为框架已经把这些事情给做了;在玩家的角度我们只有“一个”服务器,同样的,在开发者的角度我们只有“一个”游戏对外服;
在结构组合上(部署多样性)
在部署上,支持多服单进程的方式部署(类似单体应用、在分步式开发时,调试更加方便)、也支持多服多进程多机器的方式部署。
架构由三部分组成:1. 游戏对外服、2.Broker(游戏网关)、3. 游戏逻辑服;三者既是相互独立的,又是可以相互融合的,如:
- 游戏对外服、Broker(游戏网关)、游戏逻辑服这三部分,在一个进程中;【单体应用;在开发分步式时,调试更加方便】
- 游戏对外服、Broker(游戏网关)、游戏逻辑服这三部分,在多个进程中;【分布式】
- 游戏对外服、Broker(游戏网关)这两部分在一个进程中;而游戏逻辑服在多个进程中;【类似之前游戏的传统架构】
- 甚至可以不需要游戏对外服,只使用 Broker(游戏网关)和游戏逻辑服这两部分,用于其他系统业务;
因为 ioGame 遵循面向对象的设计原则(单一职责原则、开闭原则、里式替换原则、依赖倒置原则、接口隔离原则、迪米特法则)等,所以使得架构的职责分明,可以灵活的进行组合;
游戏对外服是架构的三部分之一,默认的游戏对外服是基于 netty 实现的。如果有需要,将来我们还可以使用基于 mina、smart-socket 等通信框架编写,额外提供一个游戏对外服的实现;即使是使用 mina、smart-socket 提供的游戏对外服,也并不会影响现有的游戏逻辑服业务逻辑,因为游戏对外服满足单一职责原则,只维护用户(玩家)长连接相关的。
开发人员几乎都遇见过这么一种情况;在项目初期阶段,通常是以单体项目的方式进行开发,随着需求不断的增加与迭代,会演变成一个臃肿的项目;此时在对一个整体进行拆分是困难的,成本是极高的。甚至是不可完成的,最后导致完全的重新重构;
ioGame 提供了在结构组合上的部署多样性,通过组合的方式,在项目初期就可以避免这些拆分问题。在开发阶段中,我们可以使用单体应用开发思维,降低了开发成本。通过单体应用的开发方式,在开发分步式项目时,调试更加的方便;这既能兼顾分步式开发、项目模块的拆分,又能降低团队的开发成本;
架构优点
架构有很高程度的抽象,让设计者更加关注于业务,而无需考虑底层的实现、通信参数等问题。
逻辑服的位置透明性;同时,由于模块化、抽象化,使得整个架构各服务器之间耦合度很低,逻辑服注册即可用,大大增加了可伸缩性、可维护性,动态扩展变得简单而高效。由于逻辑服是注册到 Broker(游戏网关) 上的,所以逻辑服可以动态的增加、删除、改变;由于逻辑服之间耦合度较小,调试和测试的工作也是可控的;
架构比较清晰的就是,游戏对外服负责维护客户端的接入(用户、玩家的连接),游戏逻辑服专心负责业务逻辑,他们之间的调度由 Broker(游戏网关)来负责;因为架构拆分的合理,所以特别方便用 k8s 来自由伸缩部署这三种服,哪个服水位高就扩容哪个,水位过去了又可以缩容。
通过 ioGame 可以使得游戏编程变得简单,下面是一个业务示例
Proto 协议文件定义
首先我们自定义一个协议文件,这个协议文件作为我们的业务载体描述。这个协议是纯 java 代码编写的,使用的是 jprotobuf,jprotobuf 是对 google protobuf 的简化使用,性能同等。
可以把这理解成 DTO、POJO、业务数据载体等,其主要目的是用于业务数据的传输;
/** 请求 */ @ProtobufClass @FieldDefaults(level = AccessLevel.PUBLIC) public class HelloReq { String name; }
Action
游戏服务器的编程,游戏服务器接收业务数据后,对业务数据进行处理
@ActionController(1) public class DemoAction { @ActionMethod(0) public HelloReq here(HelloReq helloReq) { HelloReq newHelloReq = new HelloReq(); newHelloReq.name = helloReq.name + ", I'm here "; return newHelloReq; } }
一个方法在业务框架中表示一个 Action(即一个业务动作)。
方法声名的参数是用于接收前端传入的业务数据,在方法 return 时,数据就可以被游戏前端接收到。程序员可以不需要关心业务框架的内部细节。
从上面的示例可以看出,这和普通的 java 类并无区别,同时这种设计方式避免了类爆炸。如果只负责编写游戏业务,那么对于业务框架的学习可以到此为止了。
游戏编程就是如此简单!
问:我可以开始游戏服务器的编程了吗?
是的,你已经可以开始游戏服务器的编程了。
访问示例(控制台)
当我们访问 here 方法时(通常由游戏前端来请求),控制台将会打印
┏━━━━━ Debug. [(DemoAction.java:4).here] ━━━ [cmd:1 - subCmd:0 - cmdMerge:65536] ┣ userId : 888 ┣ 参数: helloReq : HelloReq(name=塔姆) ┣ 响应: HelloReq(name=塔姆, I'm here ) ┣ 时间: 0 ms (业务方法总耗时) ┗━━━━━ Debug [DemoAction.java] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
控制台打印说明
Debug. [(DemoAction.java:4).here]: 表示执行业务的是 DemoAction 类下的 here 方法,4 表示业务方法所在的代码行数。 在工具中点击控制台的 DemoAction.java:4 这条信息,就可以跳转到对应的代码中(快速导航到对应的代码),这是一个开发良好体验的开始! userId : 当前发起请求的 用户 id。 参数 : 通常是游戏前端传入的值。 响应: 通常是业务方法返回的值 ,业务框架会把这个返回值推送到游戏前端。 时间: 执行业务方法总耗时,我们可根据业务方法总耗时的时长来优化业务。 路由信息:[cmd - subCmd] 路由是唯一的访问地址。
有了以上信息,游戏开发者可以很快的定位问题。如果没有可视化的信息,开发中会浪费很多时间在前后端的沟通上。问题包括:
- 是否传参问题 (游戏前端说传了)
- 是否响应问题(游戏后端说返回了)
- 业务执行时长问题 (游戏前端说没收到响应, 游戏后端说早就响应了)
其中代码导航可以让开发者快速的跳转到业务类对应代码中,在多人合作的项目中,可以快速的知道业务经过了哪些方法的执行,使得我们可以快速的进行阅读或修改;
框架内置功
内置多种可选模块,可按需选择,以方便应用开发:
- 领域事件 (轻量级单机最快 MQ -- disruptor;通过领域事件模块,可为你的系统实现类似 Guava-EventBus、Spring 事件驱动模型 ApplicationEvent、业务解耦、规避并发、不阻塞主线程... 等,各种浪操作)
- 任务延时器 (将来某个时间可对任务进行执行、暂停、取消等操作,并不是类似 Quartz 的任务调度)
- 多环境切换 (不同运行环境下的配置支持)
- light-jprotobuf (补足 jprotobuf 不能让多个对象在单个 .proto 源文件中生成的需求,并简化 jprotobuf 对源文件的注释)
- 分步式锁 (基于 Redisson 的简单实现)
内置的其他功能:
- 心跳相关
- 用户上线、离线相关的钩子方法
- UserSessions (对所有用户 UserSession 的管理,统计在线用户等)
- UserSession (与 channel 是 1:1 的关系,可取到对应的 userId、channel 等信息。)
- 登录相关(提供重复登录、顶号等相关增强功能)
- 业务参数基础类型 自动装箱、拆箱(解决协议碎片)
适合人群?
- 长期从事 web 内部系统开发人员, 想了解游戏的
- 刚从事游戏开发的
- 未从事过游戏开发,但却对其感兴趣的
- 对设计模式在实践中的应用和 sofa-bolt 有兴趣的学习者
- 可以接受新鲜事物的
- 想放弃祖传代码的
推荐实际编程经验一年以上的人员
ioGame 提供了丰富的在线高质量使用文档,为你的团队助力,带上你们的小伙伴一起,这样就不用手把手的教了。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
MiniFramework 2.9.5 版本发布,轻量级的 PHP 开发框架
2022年12月6日,MiniFramework 发布了 2.9.5 版本,主要变化如下: 新增 Mini\Base\Request 类的 getHost() 方法,用于获取当前请求的 HOST 地址。 新增 Mini\Base\Request 类的 getUserAgent() 方法,用于获取当前请求的客户端 User-Agent 信息。 改进 Mini\Base\Request 类的 getHeaders() 方法,支持获取指定名称的 Header 信息。 改进 Mini\Base\Model 类的 regDb() 方法,当注册的数据库对象已经存在时会抛出异常。 改进 Mini\Base\Model 类的 useDb() 方法,当无法正常使用数据库对象时会抛出异常。 改进 Mini\Base\Layout 类的 setLayoutPath() 方法,增加针对参数的类型约束。 修复 Mini\Db\Mysql 类在某些特定场景下无法正常加载 PDO 扩展的问题。 优化 Mini\Db\Mysql 类的异常报错信息。 (了解详情:https://gitee.com/jasonwei/m...
- 下一篇
Newsletter 2022-11|HStreamDB 0.11 发布
11月我们发布了 HStreamDB 0.11,修复了多项已知问题。同时也在继续推进 HStream Platform 的开发,并计划于本月底上线首个 Alpha 版本。 v0.11 发布 随着云原生流数据库 HStreamDB 项目的日益成熟,为了更好地适应项目发展,我们决定逐渐缩短发版周期,以更快的速度进行迭代。因此,继10月底我们发布 v0.10 之后,11月我们又发布了 v0.11,主要带来了以下更新和问题修复: 调整 HServer 的启动参数 host 和 address 为 bind-address 和 advertised-address ,使它们更容易被理解和使用 移除 HServer 端的压缩选项,目前推荐使用端到端压缩功能 统一内部资源命名规则并改进了相应的资源命名校验 支持获取 stream 和 subscription 的创建时间 修复对部分 Client 的 RPC 请求的路由校验 HStream CLI 新增 subscription 子命令 修复提交 subscripton 进度可能失败的问题 修复 query 的 join 可能产生错误结果的问题 修复...
相关文章
文章评论
共有0条评论来说两句吧...