国内首个基于蚂蚁金服 SOFABolt 的 java 网络游戏服务器框架;无锁异步化、事件驱动的架构设计
通过 ioGame 可以很容易的搭建出一个集群无中心节点、有状态多进程的分步式游戏服务器
无中间件依赖、代码即文档、JSR380、断言 + 异常机制 = 更少的维护成本、开发成本
同样的一套业务代码无需变更,可以支持多种协议:protobuf、json,并且可扩展
同样一套业务代码无需变更,可以支持多种通信协议:websocket、socket
轻量级、启动快、更节约、简单、开箱即用、无配置文件、超高性能
近原生的快、业务框架平均每秒可以执行 1152 万次业务逻辑
在业务开发中自带神级特性:业务代码访问定位与跳转
架构部署多样性:即可相互独立,又可相互融合
各个逻辑服之间可以相互的进行跨进程通信
可同时与同类型多个游戏逻辑服通信
支持玩家动态绑定逻辑服节点
对webMVC开发者友好
无 spring 强依赖
https://www.yuque.com/iohao/game
过去、现在、将来都不会有商业版本,所有功能全部开源!
只做真的完全式开源,拒绝虚假开源,售卖商业版,不搞短暂维护!
承诺项目的维护周期是十年起步, 2022-03-01起,至少十年维护期!
提供高质量的使用文档!
如果您觉得还不错,帮忙给个 star 关注
附加授权许可协议 -- 点我展开
在许多项目开发用例中也是免费使用的,只有当你的作品营收超过600万人民币时,才需要就超出部分支付3%的分成费用。
如果你对分成费用反感的,那么可以通过以下方式进一步减少分成费用,通常可以减少到0%的分成费用;
减少分成费用的方式一:
1.企业白金赞助商将减少到 3% - 1.5% = 1.5% ;即1.5%的分成费用;
2.企业黄金赞助商将减少 3% - 1% = 2% ;即2%的分成费用;
在减少分成费用的方式一中,减少分成费用的方式之间不叠加;
减少分成费用的方式二:
1.个人开发赞助支持者 3% - 2% = 1% ;即1%的分成费用;
减少分成费用的方式三:
1.在本协议项下开发的产品包含来源,您必须在来源中发布以下声明,[产品名称]使用了游戏服务器框架(ioGame),将减少1.5%的分成费用;
2.通过邮箱申请产品登记(发到 262610965@qq.com),通常需要提前3个月登记才会申请成功,以产品发布日期起算,将减少0.5%的分成费用;
在减少分成费用的方式三中,两种减少分成费用的方式可叠加;
减少分成费用的方式四:
1.一年内参与过 ioGame 代码贡献,代码大于50行的PR贡献者,将减少0.5%的分成费用;
2.一年内参与过 ioGame 的代码贡献的认证成员,将减少1.5%的分成费用;
在减少分成费用的方式四中,两种减少分成费用的方式之间不叠加;
减少分成费用的方式说明一:
方式一、方式三、方式四之间可做叠加,多种减少分成费用的方式叠加后,小于0%的,则最小值为0%;
减少分成费用的方式说明二:
方式二、方式三、方式四之间可做叠加,多种减少分成费用的方式叠加后,小于0%的,则最小值为0%;
如何选择?
在框架开发者的角度,当然是希望有一些赞助商可以给予 ioGame 一些赞助;
但是如果企业或个人开发者对这种赞助反感的,可以通过结合减少分成费用方式三和减少分成费用方式四,进一步减少分成费用,通常可以来规避分成费用。
以下行业或产品不可以使用减少分成费用的方式,如有需要请提前沟通:
基于 ioGame 的商业化视频、围绕 ioGame 的商业化售卖产品;
围绕 ioGame 的商业化产品指的是售卖相关的商业产品;
大家对于以上附加不必过于担心,通常 99% 的项目都难以触发分成费用许可,如果能成为那 1% 那么先恭喜你们已经盈利了;
ioGame 依然遵循过去、现在、将来都不会有商业版本,所有功能全部开源;
github | gitee | |
---|---|---|
源码地址 | ioGame 网络游戏框架-源码 | ioGame 网络游戏框架-源码 |
示例地址 | ioGame 示例集合 | ioGame 示例集合 |
游戏前端示例
地址 | 描述 |
---|---|
u3d 连接示例文档 | 已经与 ioGame 的综合示例联调成功 |
cocosCreator 连接示例文档 | 已经与 ioGame 的综合示例联调成功 |
UE5 连接示例文档 | 已经与 ioGame 的综合示例联调成功 |
效率
地址 | 描述 |
---|---|
idea-ioGame-插件 | 通过该 idea 插件,可以进一步提高生产力,减少工作量。 |
ioGame 快速理解篇 | 快速掌握 ioGame 的概念 |
ioGame 综合示例介绍 | 示例中有功能特性的实践、打包部署(docker、ks8)等介绍 |
技术栈推荐与其它参考文档 | 游戏开发的技术栈建议,大家可以参考一下。 |
更多游戏服务器框架推荐 | 如果 ioGame 不能很好的满足你的需要,请别担心,这里还有更多的 java 游戏服务器框架推荐给你。 |
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>17.1.28</version>
</dependency>
如果有需要加群的,在线文档的简单介绍部分中可以找到;群号特意没放在 README 中,希望的是大家先对框架有个大概的了解。
在线文档::ioGame 网络游戏框架-文档
推荐大家看在线文档,排版相对好一些,README 上看有点乱!
关注 ioGame 的游戏服务器开发者持续增多,2022-09 ~ 2022-12 月统计数据;这里的统计信息是关于开发者关注 ioGame 框架相关的,从统计数据中可以看出,由于 ioGame 上手简单,功能强大等优点,得到了众多开发者的关注。
如果你想知道 ioGame 有没有人在使用,可以先到这里看下统计数据、开发者的评价与讨论。
https://www.yuque.com/iohao/game/gpxk93#TwVa8
这里展示了每月的统计数据,统计数据来源于语雀后台,这些数据都是真实的、客观存在的。
通过统计数据,我们可以看到每天会有很多开发者在访问 ioGame 的在线文档,并且这些统计数据不是来源于口嗨的,也不是主观创造的。
所以,还在犹豫要不要使用 ioGame 的开发者们,更应该讨论的是“为什么这些开发者会选择使用 ioGame”,而不是 ioGame 有没有人在使用的问题。
ioGame 已经接入 OSCS 墨菲安全扫描,框架的安全质量近乎100%,游戏开发者们可放心使用。更详细的可以到 ioGame 框架的安全质量、代码质量、性能 来了解。
实践产品的计划 -- 点我展开
ioGame 除了让网络游戏服务器的编程变得轻松简单,减轻游戏开发者的工作量外;还可以帮助一些对网络游戏开发感兴趣的,但又没有人带入行的潜在游戏开发者;
但目前提供的示例还是难以满足的,所以未来会提供一些实践类型的产品,在实践中学习,可以更好的辅助大家进入游戏行业;对于实践类型的产品,计划用 ioGame 做游戏服务端,前端使用 cocos、u3d、ue ... ...等;
实践类型的产品基本都是基于网络交互的,这些产品计划中的类型大概有:回合制网络游戏、即时战斗网络游戏、桌游类的网络游戏;实践产品会包含源码和视频教程,手把手从零系列。
通过这些实践产品,可以助力大家独立开发或与自己的小伙伴们,合作开发一款网络游戏;有兴趣的小伙伴可以提前关注一下 ioGame 的动态!
目前首款实践产品计划中,很大机率是多人回合制网络游戏,暂定模块功能:战斗、组队、奖励、场景切换、背包、对话系统、商店交易系统、宝宝;(会包含游戏前端)
回合制的战斗核心逻辑是步骤表设计**,掌握了步骤表这一设计**,几乎可以做任意的步骤逻辑游戏,如牌类的(象棋、斗地主)、桌游类的(炉石、三国杀、大富翁)、各种回合制的战斗 .... 等,简单点说就是可以适应所有那种,你动一轮、我动一轮、他动一轮的轮流制游戏。
预计 star 到 1700+ 开始动工,以便确定开发者有这方面的需要,同时也可以让更多的开发者在实践中学习;
如果 ioGame 给你的工作带来了便利,或许可以来支持一下星球。如果公开使用文档及框架使用的过程中能让你有所收获的,通常在星球内的收获则会是公开文档的几倍甚至更多,收益也是巨大的。如果觉得公开自愿付费的使用文档质量还可以,那么星球里的内容质量则会更高。
ioGame 的星球是纯原创性的内容,不是知识点资料收集类型的星球。运作与维护的过程也不会像这类星球那样的轻松,因为 ioGame 大部分的内容是没有地方可以 copy 和收集的,全是原创性的内容,所以付出的精力也会相对的多。
为了保证加入了星球人员的利益,之后群内或私下的提问,如果涉及到了星球内容的,将不会在做详细的解答,对此深表歉意。
星球计划内容会有多个系列,每个系列有多个大篇章,每个大篇章下会有多个小章节。使用图文的方式做讲解,首个系列是框架源码及其高级扩展玩法相关的。
每个系列的内容产出类似一本书籍,当然这些书籍不会出现水篇章的情况,比如安装环境和配置就给你水了几百页的内容。由于每个系列会类似一本书籍,所以会使用循序渐进的方式来引导学习者,这种方式也适合初级开发者人员来学习。
首个系列内容包括:业务框架建构时阶段,业务框架处理时阶段,业务框架个性化定制扩展,业务框架设计过程中的思考,利用好线程编排特性、规避并发,游戏对外服分析、扩展及未来的计划,游戏网关分析、扩展及未来的计划,项目开发中的注意事项与技巧。
首个系列内容的讲解会比较详细,大概有多个大篇章和几十个小章节,涉及的都是实践中的设计技巧,以上内容会根据实际情况及星球用户交流的过程中来做增加与调整。
如果只是负责业务编码的人员不建议加入星球,因为通过公开使用文档的阅读与使用示例已经足够了。
各位开发者不必担心,ioGame 新特性的开发、公开自愿付费文档、使用示例等,都会持续的维护与修正。只是在星球中内容会更加的丰富,帮助开发者节约更多的时间,相当与进一步的提高你的生产力。
详细可以关注:ioGame 星球计划
让网络游戏服务器的编程变得轻松简单!
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 提供了游戏文档生成的辅助,通过该辅助可以做到代码即对接文档。简单的说,当开发者的业务代码编写完后,不需要额外的去编写业务对接文档了,框架会自动的生成最新的文档。如果没有游戏文档的生成,那么你将要抽出一些时间来维护对接文档的工作,而且当团队人数多了,就会很乱(文档不同步、不是最新的、或是忘记更新等等情况就会出现)。
ioGame 可以很方便的与 spring 集成(5 行代码)。
综上,ioGame 屏蔽了很多复杂且重复性的工作;超棒的开发体验,使用简单,无中间件依赖,只需一个依赖即可获得整个框架;减少了学习成本、减少了使用成本、减少了开发者的工作量、减少了项目的运维成本。并可为项目中的功能模块结构、开发流程等进行清晰的组织定义,减少了后续的项目维护成本。从而让开发团队更方便快捷高效的开发游戏项目。
ioGame 是国内首个基于蚂蚁金服 sofa-bolt 的网络游戏框架,游戏框架由 [网络通信框架] 和 [业务框架] 组成。
- 网络通信框架:职责是各服务器之间的网络通信
- 业务框架:职责是业务逻辑的处理方式和编写方式
SOFABolt 是蚂蚁金融服务集团开发的一套基于 Netty 实现的网络通信框架。
- 为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上,而不是过多的纠结于网络底层 NIO 的实现以及处理难以调试的网络问题,Netty 应运而生。
- 为了让中间件开发者能将更多的精力放在产品功能特性实现上,而不是重复地一遍遍制造通信框架的轮子,SOFABolt 应运而生。
Bolt 名字取自迪士尼动画-闪电狗,是一个基于 Netty 最佳实践的轻量、易用、高性能、易扩展的通信框架。
如果说 sofa-bolt 是为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上。而业务框架正是解决业务逻辑如何方便实现这一问题上。业务框架是游戏框架的一部分,职责是简化程序员的业务逻辑实现,业务框架使程序员能够快速的开始编写游戏业务。
业务框架对于每个 action (即业务的处理类) 都是通过 asm 与 Singleton、Flyweight 、Command 等设计模式结合,对 action 的获取上通过 array 来得到,是一种近原生的方式。
业务框架平均每秒可以执行 1152 万次业务逻辑。
业务框架性能报告JMH--点我展开
Iteration 1: 11439916.980 ops/s
Iteration 2: 11521457.838 ops/s
Iteration 3: 11560843.725 ops/s
Iteration 4: 11535277.025 ops/s
Iteration 5: 11564838.596 ops/s
Result "com.iohao.game.example.benchmark.BarSkeletonBenchmark.handle1":
11524466.833 ±(99.9%) 194712.309 ops/s [Average]
(min, avg, max) = (11439916.980, 11524466.833, 11564838.596), stdev = 50566.168
CI (99.9%): [11329754.524, 11719179.141] (assumes normal distribution)
# Run complete. Total time: 00:01:20
上面是在单线程中的测试数据,业务框架平均每秒执行 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 支持 3 种类型的通讯方式,分别是单次请求处理、推送、逻辑服间的相互通信;下面分别对这 3 种类型的通讯方式相关的应用场景举几个例子。
框架对这 3 种类型的通讯方式提供了代码调用点的日志,简单点说就是框架可以让开发者知道,是在哪一行代码中触发的业务逻辑。
我们可以想象一下,假如框架没有提供代码调用点的日志会是什么样的;比如,游戏前端发送一个业务请求到游戏服务器中,但是处理这个请求的业务方法,会触发多个响应(通常是推送、广播)给游戏前端。一但时间久了,开发者是很难知道分别响应了哪些业务数据给游戏前端,特别是一些二手项目;所以这将是一个灾难性的问题,因为这会耗费大量的时间来寻找这些相关的业务代码。
3 种类型的通讯方式的详细内容--点我展开
1.单次请求处理
1.1 请求、无响应
当请求端发起请求后,逻辑服不会发送任何响应给请求端。可以用在在网络通讯中,存在着不需要接收方回执确认的调用模型,如数据采集的场景: 打点采集、日志传输、metrics上报等。
在写 action 时,将方法返回值声名为 void 就表示处理 请求、无响应的。
1.2 请求、响应
请求、响应是在游戏开发中常见的通讯模式,也就是通讯的一方发出请求,而远程通讯的对方做出响应,也就是常说的请求/响应模式。
比如:装备的升级、人物的升级、玩家的移动、抽奖、游戏前端到某一个场景时需要从游戏服务端获取一些对应的场景配置等;
在写 action 时,方法有返回值的就表示处理 请求、响应的,框架会将这个返回值给到请求端。
2.推送
2.1 指定单个或多个用户广播(推送)
向一个或多个指定的用户(玩家)主动发送一些数据。比如:
- 给指定的在线玩家发送一些奖励。
- 给在同一个房间内的玩家广播一些数据,如某一个玩家射击子弹,把这子弹的数据广播给房间内的其他玩家。如几个玩家在同一个房间内打牌,某个玩家出牌后,把这张牌的数据广播给房间内的其他玩家。
2.2 全服广播(推送)
给全服的所有在线玩家广播消息,如广播公告、即将停服维护等。
详细示例可参考:广播示例
3.逻辑服间的相互通信
3.1 游戏逻辑服与单个游戏逻辑服通信请求 - 有返回值(可跨进程)
逻辑服与逻辑服之间的相互请求通信,有返回值
比如:我们有两个游戏逻辑服,分别是:a.天气预报逻辑服、b.战斗逻辑服。现在我们设想一个回合制游戏的战斗场景,需要配合天气,根据天气来增强或者减弱某个英雄的能力。那么在战斗开始前,战斗逻辑服只需要向游戏网关发起一个获取当前天气的请求,就可以得到当前的天气信息了,在根据当前的天气数据来增强或减弱该英雄的能力。
又比如:a.大厅逻辑服、b.奖励发放逻辑服。大厅记录着一些数据(房间总数),奖励发放逻辑服根据当前的房间数量,来生成不同奖品,随机发放给在线用户。
详细示例可参考:逻辑服与逻辑服之间的交互示例
3.2 游戏逻辑服与单个游戏逻辑服通信请求 - 无返回值(可跨进程)
逻辑服与逻辑服之间的相互请求通信,无返回值
比如:我们有两个游戏逻辑服,分别是:a.匹配逻辑服、b.房间逻辑服。
业务场景如下,多个玩家在开始游戏前需要匹配。这里假设有两个玩家,当匹配完成后,给这两个玩家返回所匹配到的房间信息。
具体实现如下,两个玩家分别向匹配逻辑服发送匹配请求,匹配逻辑服收到玩家的请求后进行逻辑处理,并成功的把这两个玩家匹配到一起,此时我们把两个匹配到一起的玩家先称为匹配结果。匹配逻辑服只负责匹配相关的算法逻辑,所以在匹配逻辑服中,我们可以把匹配结果给到房间逻辑服,因为与匹配相关的工作已经完成了。
在匹配逻辑服中,我们可以向房间逻辑服发起一个(单个逻辑服与单个逻辑服通信请求 - 无返回值)的请求,当房间逻辑服拿到匹配结果,根据匹配结果来创建房间。房间创建完成后把结果用推送(广播)给这两名玩家。
为什么要用无返回值的通信请求呢,因为匹配逻辑服并不关心房间的创建。
详细说明可参考:逻辑服与逻辑服之间的交互-无返回值
3.3 游戏逻辑服与同类型多个游戏逻辑服通信请求(可跨进程)
如: 【象棋逻辑服】有 3 台,分别是:《象棋逻辑服-1》、《象棋逻辑服-2》、《象棋逻辑服-3》,这些逻辑服可以在不同有进程中。
我们可以在大厅逻辑服中向【同类型】的多个游戏逻辑服请求,意思是大厅发起一个向这 3 台象棋逻辑服的请求,框架会收集这 3 个结果集(假设结果是:当前服务器房间数)。
当大厅得到这个结果集,可以统计房间的总数,又或者说根据这些信息做一些其他的业务逻辑;这里只是举个例子。实际当中可以发挥大伙的想象力。
详细示例可参考:请求同类型多个逻辑服通信结果
其中配合动态绑定逻辑服节点;可以实现LOL、王者荣耀匹配后动态分配房间
3.4 游戏逻辑服与多个游戏对外服通信请求(可跨进程)
可以向游戏对外服拿一些玩家数据,或者是其他的一些操作。框架在游戏对外服中提供了 ExternalBizRegion 接口,可以使得开发者在游戏对外服中的扩展变得很简单。
框架利用这一通讯特性与 ExternalBizRegion 扩展,在不到 15 行的有效代码中,就实现了,如:查询用户(玩家)是否在线、强制用户(玩家)下线....等功能,从而实现了登录功能的增强:重复登录、顶号这些业务。
具体扩展与使用可以参考 获取游戏对外服的数据与扩展 文档
最后,发挥你的想象力,把这 3 类通讯方式用活,可以满足很多业务。
抽象的说,游戏前端与游戏服务器的的交互由上图组成。游戏前端与游戏服务器可以自由的双向交互,交互的业务数据由 .proto 作为载体。协议文件是对业务数据的描述载体,用于游戏前端与游戏服务器的数据交互。
当游戏前端和游戏服务端建立了连接后,就可以开始相互传递业务数据,处理各自的业务了。好了,看完业务交互介绍后,开始编写一个游戏业务处理示例吧,接下来我们先定一个业务数据协议。
协议文件是对业务数据的描述载体,用于游戏前端与游戏服务器的数据交互。Protocol Buffers 是Google公司开发的一种数据描述语言,也简称 PB 。当然协议文件描述还可以是 json、xml或者任意自定义的,因为最后传输时会转换为二进制,但游戏开发中 PB 是目前的最佳。
游戏前端的展现可以是 Unity 、 UE(虚幻) 、 Cocos 或者其他的游戏引擎。这些游戏引擎只是展现游戏画面的一种形式,数据交互则由通信来完成(TCP、UDP 等)。
这里主要介绍游戏服务器相关的,下面这个示例介绍了服务器编程可以变得如此简单。
首先我们自定义一个协议文件,这个协议文件作为我们的业务载体描述。这个协议是纯java代码编写的,使用的是 jprotobuf,jprotobuf 是对 google protobuf 的简化使用,性能同等。
可以把这理解成DTO、POJO、业务数据载体等,其主要目的是用于业务数据的传输;
/** 请求 */
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class HelloReq {
String name;
}
游戏服务器的编程,游戏服务器接收业务数据后,对业务数据进行处理;
@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。参数 :
通常是游戏前端传入的值。响应 :
通常是业务方法返回的值 ,业务框架会把这个返回值推送到游戏前端。时间 :
执行业务方法总耗时,我们可根据业务方法总耗时的时长来优化业务。路由信息 :
路由 是唯一的访问地址。
有了以上信息,游戏开发者可以很快的定位问题。如果没有可视化的信息,开发中会浪费很多时间在前后端的沟通上。问题包括:
- 是否传参问题 (游戏前端说传了)
- 是否响应问题(游戏后端说返回了)
- 业务执行时长问题 (游戏前端说没收到响应, 游戏后端说早就响应了)
其中代码导航可以让开发者快速的跳转到业务类对应代码中,在多人合作的项目中,可以快速的知道业务经过了哪些方法的执行,使得我们可以快速的进行阅读或修改;
- 长期从事 web 内部系统开发人员, 想了解游戏的
- 刚从事游戏开发的
- 未从事过游戏开发,但却对其感兴趣的
- 对设计模式在实践中的应用和 sofa-bolt 有兴趣的学习者
- 可以接受新鲜事物的
- 想放弃祖传代码的
推荐实际编程经验一年以上的人员
内置多种可选模块,可按需选择,以方便应用开发:
游戏服务器框架内置功能详细--点我展开
- 领域事件 (轻量级单机最快MQ -- disruptor;可为你的系统实现类似 Guava-EventBus、Spring 事件驱动模型 ApplicationEvent、业务解耦、规避并发、不阻塞主线程... 等,各种浪操作。)
- 任务延时器 (将来某个时间可对任务进行执行、暂停、取消等操作,并不是类似 Quartz 的任务调度)
- 多环境切换 (不同运行环境下的配置支持)
- light-jprotobuf (补足 jprotobuf 不能让多个对象在单个 .proto 源文件中生成的需求,并简化jprotobuf对源文件的注释)
- 分步式锁 (基于Redisson的简单实现)
内置的其他功能:
- 心跳相关
- 用户上线、离线相关的钩子方法
- UserSessions (对所有用户UserSession的管理,统计在线用户等)
- UserSession (与 channel 是 1:1 的关系,可取到对应的 userId、channel 等信息。)
- 登录相关(提供重复登录、顶号等相关增强功能)
- 业务参数自动装箱、拆箱基础类型 (解决协议碎片)
集成相关:
- spring 集成 (业务框架可以方便的与 spring 进行集成,5 行代码)
后续计划:
- 抽象通用的游戏逻辑 (进一步减少开发实践过程中的工作量)
- 步骤表
- 帧同步
- 状态同步
- 框架自带监控
当然每个框架都会给自身打上高性能、使用简单、易学易用、可扩展等各种有调调的标签。这里将从这么几个方面给出一些相关的解释,同是也是开发中接触最多的几个方面,如:
-
性能方面
-
对接方面
-
通讯方式方面
-
开发方面
-
- 开发体验方面
- 参数方面
- 参数的数据验证方面
- 异常机制方面
- 调试方面
ioGame游戏框架由 [网络通信框架] 和 [业务框架] 组成。所以我们只需要关注使用最频繁的两个点,1. 网络传输的性能,2.调用开发者编写的业务代码(action)。
1. 网络传输的性能
网络传输方面的性能上限取决于网络通信框架 sofa-bolt 。
由于 sofa-bolt 基础通信功能中支持:批量解包与批量提交处理器的特性,在理论上会比原生的 netty 会好一些;在就基于 sofa-bolt 开发的产品较多,如:SOFARPC、消息中心、分布式事务、分布式开关、以及配置中心等众多产品上,所以在稳定性与性能上不是一个问题。
2.调用开发者编写的业务代码(action)
业务框架对于每个 action (即业务的处理类) 都是通过 asm 与 Singleton、Flyweight 、Command 等设计模式结合,对 action 的获取上通过 array 来得到,是一种近原生的方式。
业务框架平均每秒可以执行 1152 万次业务逻辑。
日常中,我们编写完成业务需求后,就会与游戏前端的同学进行联调对接的环节。在对接前需要提供相应的对接文档,如:如何访问该需求的业务方法、访问该业务方法需要什么参数、会得的响应是什么、对于该业务方法的描述等等。
对于这方面 ioGame 也提供了一些辅助 游戏文档生成 ,通过该辅助可以做到代码即文档,就是说当你的业务编写完成后,不需要额外的编写业务对接文档了,框架会自动的生成最新的文档。
如果没有游戏文档生成,那么你将要抽出一些时间来维护文档的工作,而且当团队人数多了,就会很乱(文档不同步、不是最新的、或是忘记更新等等情况就会出现)。
框架生成的对接文档预览--点我展开
==================== DemoEndPointRoomAction 动态绑定逻辑服节点-房间相关 ====================
路由: 10 - 0 --- 【统计房间数】 --- 【DemoEndPointRoomAction:44】【countRoom】
方法返回值: com.iohao.game.example.common.msg.RoomNumMsg
路由: 10 - 1 --- 【房间内的操作】 --- 【DemoEndPointRoomAction:64】【operation】
方法参数: com.iohao.game.example.common.msg.DemoOperation
方法返回值: com.iohao.game.example.common.msg.DemoOperation
==================== DemoMatchAction 动态绑定逻辑服节点-匹配相关 ====================
路由: 11 - 0 --- 【开始匹配】 --- 【DemoMatchAction:83】【matching】
方法返回值: com.iohao.game.example.common.msg.MatchResponse
路由: 11 - 1 --- 【登录】 --- 【DemoMatchAction:56】【loginVerify】
方法参数: com.iohao.game.example.common.msg.login.DemoLoginVerify
方法返回值: com.iohao.game.example.common.msg.login.DemoUserInfo
==================== 错误码 ====================
-1005 : class 不存在
-1004 : 请先登录
-1003 : 心跳超时相关
-1002 : 路由错误
-1001 : 参数验错误
-1000 : 系统其它错误
传统的游戏项目通常是单机结构的,即项目在代码都在一个目录中,这样代码是很容易泄漏的,且一但泄漏将会是全部泄漏,因为这些代码都在一个项目中;
这种情况在 ioGame 中是可以做到一些防范与避免的;现在我们知道了,游戏逻辑服可以支持分布式开发方式的,如果项目有多个模块,我们可以将这些模块分配给团队中不同的开发人员,开发人员只能看到自己所负责的模块,而看不到其他成员的模块代码;
在这期间,团队管理员可以在公司的内网服务器中,部署一个游戏网关和游戏对外服,因为这两个是不需要经常重启的和变更的。通常情况下,我们更多的是在游戏逻辑服上进行业务编码,所以可以将游戏逻辑服在我们自己的本机进行编码工作;这样做的好处有:1. 游戏客户端(游戏前端)不会因为游戏逻辑服的业务逻辑变更、重启,而与游戏服务器断开连接;2. 开发人员在自己开发机上只需要启动自己负责的游戏逻辑服;
在涉及到与其他游戏逻辑服的联调时,我们可以查看其他模块提供的对接文档(这些文档是由 ioGame 自动生成的),由于是分工合作的,所以我们可以把代码泄漏风险进一步的降低;
框架提供了 3 类通讯方式:单次请求处理、推送、逻辑服间的相互通信。发挥你的想象力,把这 3 类通讯方式用活,可以满足很多业务。
通讯方式方面--点我展开
1.单次请求处理
- 请求、无响应
- 请求、响应
2.推送
- 指定单个或多个用户广播(推送)
- 全服广播(推送)
3.逻辑服间的相互通信
- 单个逻辑服与单个逻辑服通信请求-有返回值(可跨进程)
- 单个逻辑服与单个逻辑服通信请求-无返回值(可跨进程)
- 单个逻辑服与同类型多个逻辑服通信请求(可跨进程)
ioGame 非常注重开发者的开发体验,学习零成本。在开发方面又包括这几个小方面:开发体验方面、参数方面、参数的数据验证方面、异常机制方面、调试方面。
1.零学习成本,一个普通的 java 方法就是一个 action。
2.方法参数就是请求端给的请求参数。
3.方法返回值(响应结果)会给到请求端。
可以看到,框架屏蔽了通信细节,从而使得开发变得很简单,可以说是学习零成本(因为这是一个普通的 java 方法),同时这种设计方式避免了类爆炸。
参考:快速入门样例
@ActionController(1)
public class DemoAction {
@ActionMethod(1)
public HelloReq jackson(HelloReq helloReq) throws MsgException {
String jacksonName = "jackson";
if (jacksonName.equals(helloReq.name) == false) {
throw new MsgException(101, "名字不正确!");
}
helloReq.name = helloReq.name + ", hello, jackson !";
return helloReq;
}
}
action 有这么几个组成部分:方法名、方法参数、方法体、方法返回值、方法的异常、方法的调用。业务框架关注的有这么几个点
- 方法的调用
- 方法参数的验证
- 方法的异常处理机制
- 方法的返回值
框架对 jprotobuf通信协议的友好支持 ,通信协议这里指游戏端与游戏服务端之间的业务数据传递。例如:登录业务的登录请求(游戏端请求游戏服务端)与登录响应(游戏服务端返回数据给游戏端)。jprotobuf 是对 google protobuf 的简化使用,性能同等。
框架支持 JSR380 相关验证规范,业务参数的验证不在需要写在业务代码里面,可以使得业务代码更干净。若不使用验证框架,常规的做法是不断的在业务代码中疯狂使用 if else 输出,使得业务代码混乱。
参考:开启JSR380验证规范
断言 + 异常机制 = 清晰简洁的代码
业务框架支持异常机制,有了异常机制可以使得业务代码更加的清晰。也正是有了异常机制,才能做到零学习成本(普通的 java 方法成为一个业务动作 action )。
如果有业务上的异常,请直接抛出去,不需要开发者做过多的处理,业务框架会知道如何处理这个业务异常,这些抛出去的业务异常总是能给到游戏的请求端的。
参考:异常机制
在项目开发阶段,框架提供了对于请求访问的一些日志打印和业务代码定位--神级特性 (可以让你知道哪些业务方法被调用了,并能快速的跳转到对应的业务代码中)。
其中代码导航可以让开发者快速的跳转到业务类对应代码中,在多人合作的项目中,可以快速的知道业务经过了哪些方法的执行,使得我们可以快速的进行阅读或修改;
对于这块更详细的说明在 业务日志 中有介绍
开发方面:1.开发体验、2.参数 、3.参数的数据验证方面(方法参数的验证) 、4.异常机制 、5.调试日志(业务日志)
对接方面:1.游戏文档生成
这几个方面是我们开发中最常用的,也是用得最为频繁的。如果满足不了上面最为基础的几个方面,谈不上是一个好用的框架。
源码目录详细
├── common │ ├── common-core (业务框架) │ └── common-kit (工具相关) ├── net-bolt (网络通信框架相关的:对外服、游戏网关、游戏逻辑服) │ ├── bolt-broker-server (游戏网关) │ ├── bolt-client (逻辑服) │ ├── bolt-core (游戏网关和逻辑服 ,bolt 相关 core 包) │ ├── bolt-external (对外服, 也是逻辑服的一种) │ └── bolt-run-one (单体启动辅助,一个进程内可以启动 : 对外服、游戏网关、游戏逻辑服) └── widget (内置多种可选模块) ├── light-domain-event (领域事件) ├── light-jprotobuf (生成 .proto 源文件) ├── light-profile (多环境切换) ├── light-redis-lock (分步式锁 ,基于Redisson的简单实现) ├── light-redis-lock-spring-boot-starter (分步式锁 ,基于Redisson的简单实现) └── light-timer-task (任务延时器)
如果觉得 ioGame 适合你,可以看一下 快速从零编写服务器完整示例 。在这个示例中,你可以用很少的代码实现一个完整的、可运行的、高性能的、稳定的服务器。
ioGame 源码内提供了一个基于 FXGL 游戏引擎的游戏示例 (坦克射击 启动文档),FXGL 是纯 java 开发的一个游戏引擎,可以在项目中直接运行。通过示例,可以快速的掌握网络游戏编程!
运行 TankApp.java 文件就可以启动游戏了。原计划用 U3D 来做游戏示例的,但想到大伙还得安装 u3d 的环境,就用 FXGL 来做游戏示例了。
如果您觉得还不错,帮忙给个 star 关注
什么是 Action 。
坦克示例 (游戏前端)