主要更新
(#I5PU5R、#I5PFGP、#I5NDEG、#I5Q1AO、#I5Q89K)
#I5PFGP
新增 unity 与 ioGame 综合示例的联调示例,此 unity 连接示例由 licheng 提供。之前赵少提供的 unity 示例,由于我没 fork, 估计项目被删除了(原因是 git 仓库满了,就删除了)
u3d 连接示例语雀在线文档 https://www.yuque.com/iohao/game/syv5mm
#I5Q1AO
语雀在线文档 https://www.yuque.com/iohao/game/gmfy1
领域事件变更默认配置
DomainEventContextParam.producerType 由 ProducerType.SINGLE 改为 ProducerType.MULTI
DomainEventContextParam.waitStrategy 由 BlockingWaitStrategy 改为 LiteBlockingWaitStrategy
Disruptor 是一个开源的并发框架。由英国外汇交易公司LMAX开发的一个高性能队列,并且大大的简化了并发程序开发的难度,获得2011Duke’s程序框架创新奖。可以将 disruptor 理解为单机版本的 MQ(轻量级单机最快MQ -- disruptor)。
领域事件模块是对 disruptor 的封装使用,通过领域事件模块,可为你的系统实现类似 Guava-EventBus、Spring 事件驱动模型 ApplicationEvent、业务解耦、规避并发、不阻塞主线程...等,各种浪操作。
简介 Event Source 领域事件
- 领域驱动设计,基于LMAX架构。
- 单一职责原则,可以给系统的可扩展、高伸缩、低耦合达到极致。
- 异步高并发,线程安全的使用disruptor环形数组来消费业务。可并发执行,性能超高,执行1000W次事件只需要1.1秒左右。
- 使用事件消费的方式编写代码,使得业务在复杂也不会使得代码混乱,维护代码成本更低。
- 可灵活的定制业务线程模型
- 插件形式提供事件领域,做到了可插拔,就像玩乐高积木般有趣。
使用示例-自定义领域消息实体
- 定义领域实体 - 并实现 Eo 接口
- Eo 接口是框架提供, 领域实体类用户随意编写, 建议以Eo结尾.
- 领域消息实体的对象字段随意定制 (根据你的业务)
/** * 领域消息 - 学生 * <pre> * 推荐定义领域事件实体类的时候都使用final 或定义为 record * 避免某个领域事件对该实体进行数据修改 * </pre> */ public record StudentEo(int id) implements Eo { }
使用示例-定义领域事件
用于处理 StudentEo 领域消息实体
// 事件处理类,事件消费, 实现领域事件消费接口。一个事件消费类只处理一件事件(单一职责原则) public final class StudentEmailEventHandler1 implements DomainEventHandler<StudentEo> { @Override public void onEvent(StudentEo studentEo, boolean endOfBatch) { log.debug("给这个学生发送一个email消息: {}", studentEo); } }
使用示例-测试用例
public class StudentDomainEventTest { DomainEventContext domainEventContext; @After public void tearDown() throws Exception { // 事件消费完后 - 事件停止 domainEventContext.stop(); } @Before public void setUp() { // ======项目启动时配置一次(初始化)====== // 领域事件上下文参数 DomainEventContextParam contextParam = new DomainEventContextParam(); // 配置一个学生的领域事件消费 - 给学生发生一封邮件 contextParam.addEventHandler(new StudentEmailEventHandler1()); // 配置一个学生的领域事件消费 - 回家 contextParam.addEventHandler(new StudentGoHomeEventHandler2()); // 配置一个学生的领域事件消费 - 让学生睡觉 contextParam.addEventHandler(new StudentSleepEventHandler3()); // 启动事件驱动 domainEventContext = new DomainEventContext(contextParam); domainEventContext.startup(); } @Test public void testEventSend() { // 这里开始就是你的业务代码 StudentEo studentEo = new StudentEo(1); /* * 发送事件、上面只配置了一个事件。 * 如果将来还需要给学生发送一封email,那么直接配置。(可扩展) * 如果将来还需要记录学生今天上了什么课程,那么也是直接配置 (可扩展) 这里的业务代码无需任何改动(松耦合) * 如果将来又不需要给学生发送email的事件了,直接删除配置即可,这里还是无需改动代码。(高伸缩) */ studentEo.send(); } }
#I5Q89K
关注 ioGame 的游戏服务器开发者持续增多,9 月统计数据
7 日访问统计
我们可以从 9 月初的,7 日访问统计中可以看出,关注 ioGame 的大部分是年轻群体,其中北、上、广、江浙、川、湖南北、福建等地,关注的人最多。
语雀文档阅读统计
ioGame 提供了大量的使用文档与示例代码,这里是使用文档的数据统计。
issu 数量
issu 是提问与交流的好地方,通常在群里遇见有价值的问题,都会让提问者提 issu 进行交流,这样做到了交流的保存。同时,后面来了解 ioGame 的开发者如果遇到相似的问题,可以查找该 issu ,而不用重复的回答这些问题,这也节约了框架开发者的时间。
统计小结
从统计数据上可以看出,由于 ioGame 上手简单,功能强大等优点,得到了众多开发者的关注。
ioGame 只用数据说话!
maven pom
ioGame 已经上传到中央仓库
https://search.maven.org/search?q=a:bolt-run-one
ioGame 是轻量级的网络游戏服务器框架,只需要在 pom 中引入如下就可以使用了,无需在安装任何其他的中间件产品了。
<dependency> <groupId>com.iohao.game</groupId> <artifactId>bolt-run-one</artifactId> <version>x.y.z</version> </dependency>
ioGame 网络游戏服务器框架简介
- 国内首个基于蚂蚁金服 SOFABolt 的 java 网络游戏服务器框架;无锁异步化、事件驱动的架构设计
- 通过 ioGame 可以很容易的搭建出一个集群无中心节点、有状态的分步式网络游戏服务器
- 无中间件依赖、代码即文档、JSR380、断言 + 异常机制 = 更少的维护与开发成本
- 轻量级、启动快、更节约、更简单、开箱即用、无配置文件、超高性能
- 近原生、业务框架平均每秒可以执行 1152 万次业务逻辑
- 神级特性:业务代码访问定位与跳转
- 对 webMVC 开发者友好
- 可跨进程通信
ioGame 是一个由 java 语言编写的网络游戏服务器框架。支持 websocket、tcp ,适用于全球同服、回合制游戏、策略游戏、即时战斗等游戏服务器的开发。具有高性能、稳定、易用易扩展、超好编程体验等特点。可做为 H5、手游、端游的 java 游戏服务器。
ioGame 是轻量级的网络游戏服务器框架,在使用 ioGame 时,无需安装其他服务,如: Nginx、Redis、MQ、Mysql、ZooKeeper、Protobuf协议编译工具 ... ...等。简单点说,就是无需安装其他产品就能使用;这意味着在使用上简单了,在部署上也为企业节约了成本。
通过 ioGame 你可以很容易的搭建出一个稳定、高性能、集群无中心节点、分步式、自带负载均衡、跨进程通信、避免类爆炸设计的网络游戏服务器。游戏框架借助于蚂蚁金服 sofa-bolt 通信框架来提供通信方面的稳定与高性能。
在 ioGame 中能让你遗忘 Netty,你几乎没有机会能直接的接触到 Netty 的复杂,但却能享受 Netty 带来的高性能。对开发者要求极低,为开发者节约开发时间。
即使之前没有游戏编程的经验,也能参与到游戏编程中。如果你之前具备一些游戏开发或者 webMVC 相关的知识,则会更容易上手游戏服务器的开发。
开发者基于 ioGame 编写的项目、模块通常是条理清晰的,得益于框架对路由的合理设计。当我们整理好这些模块后,对于其他开发者接管项目或后续的维护中,会是一个不错的帮助(模块的整理与建议)。
在部署上,支持多服单进程的方式部署(类似单体应用、在分步式开发时,调试更加方便)、也支持多服多进程多机器的方式部署。在部署方式上可以随意切换,而不需要更改代码;日常中按照单体思维开发,在生产上可以使用多进程的方式部署;当然,也可以使用单进程的方式部署。
ioGame 框架职责清晰、业务开发几乎零学习成本、源码有高质量注释、示例多、使用文档多,开发体验最佳、对接文档自动生成、逻辑服之间可跨进程跨机器通信、业务代码定位--神级特性、异常机制。提供了丰富的在线高质量使用文档,为你的团队助力,带上你们的小伙伴一起,这样就不用手把手的教了。
ioGame 可以很方便的与 spring 集成(5 行代码)。
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(游戏网关)在一个进程中;游戏对外服、游戏逻辑服这两部分在多个进程中
- 甚至可以不需要游戏对外服,只使用 Broker(游戏网关)和游戏逻辑服这两部分,其他系统业务;
因为 ioGame 遵循面向对象的设计原则(单一职责原则、开闭原则、里式替换原则、依赖倒置原则、接口隔离原则、迪米特法则)等,所以使得架构的职责分明,可以灵活的进行组合;
架构比较清晰的就是,游戏对外服负责维护客户端的接入(用户、玩家的连接),游戏逻辑服专心负责业务逻辑,他们之间的调度由 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] ━━━
有了以上信息,游戏开发者可以很快的定位问题。如果没有可视化的信息,开发中会浪费很多时间在前后端的沟通上。问题包括:
- 是否传参问题 (游戏前端说传了)
- 是否响应问题(游戏后端说返回了)
- 业务执行时长问题 (游戏前端说没收到响应, 游戏后端说早就响应了)
其中代码导航可以让开发者快速的跳转到业务类对应代码中,在多人合作的项目中,可以快速的知道业务经过了哪些方法的执行,使得我们可以快速的进行阅读或修改;
适合人群?
- 长期从事 web 内部系统开发人员, 想了解游戏的
- 刚从事游戏开发的
- 未从事过游戏开发,但却对其感兴趣的
- 对设计模式在实践中的应用和 sofa-bolt 有兴趣的学习者
- 可以接受新鲜事物的
- 想放弃祖传代码的
推荐实际编程经验一年以上的人员
ioGame 提供了丰富的在线高质量使用文档,为你的团队助力,带上你们的小伙伴一起,这样就不用手把手的教了。
还没有评论,来说两句吧...