# ricks-core **Repository Path**: king_jobs/ricks-core ## Basic Information - **Project Name**: ricks-core - **Description**: 游戏核心 网络层 支持 tcp kcp udp http orm 自动创建表,异步db - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 13 - **Forks**: 4 - **Created**: 2022-12-20 - **Last Updated**: 2025-06-28 ## Categories & Tags **Categories**: game-dev **Tags**: 游戏, Java, 游戏开发 ## README # ricks-core # 项目已经迁移至ricks-main [ricks-main项目gitee地址](https://gitee.com/king_jobs/ricks-main) #### 介绍 游戏核心 业务层面 游戏协议一般使用 protobuffer ,虽然玛娜项目用了flatbuff 但是前端肯定是准备弃用 转而使用pb 而且pb 确实是游戏目前主流 2.0版本核心目的,业务层面不再自己写pb 而是操作对象底层自己生成 包括参数 如果使用传统的路由,当业务功能多了,通常路由的声名是见缝插针式的,哪里有空位的数字就往哪里定义该路由值,这在多人开发的的项目中,很容易被重复定义;【遇到了这种问题】 cmd subcmd 【权限控制优势】 比如要想控制某个模块的访问权限,即玩家不能直接的访问某个模块的相关功能。 这在传统路由是很难做到的,或者说要做到这些控制会相对的麻烦很多,但在 ioGame 中却是非常简单的。比如我们定义一个内部功能模块的主路由为 10,我们只需要在游戏对外服中判断这个主路由就可以了,这样一来,外界将访问不到我们内部模块主路由为 10 的所有方法了; POJO 生成 proto buffer 文化 【目的】 后端程序猿只需要关注业务,数据操作。而不需要写创建协议 处理道具 排行榜 以排行榜为例,业务开发程序猿只需要调用函数,带入排行榜需要的数据。不用考虑集群 并发 锁。 新增轻量小部件 light-jprotobuf 简化 jprotobuf 的编写方式 不在需要 @Protobuf(description = "xxx") 来生成注释了 【感觉没必要,可以直接注解上面加注释 】 现在 jprotobuf 的类中,注释既文档 可将多个 jprotobuf 类 合并生成为一个原生的 .proto 文件, 不使用 jprotobuf 提供的生成插件, 因为 jprotobuf 生成的 .proto 文件太乱(会有重复的文件类),在阅读时也不方便 2.0版本 reflectasm 反射替代 asm生成 Dispater class 动态加载进jvm 方式。 其一 如果不生产class文件直接加载进jvm 就需要在进程启动参数 --add-opens java.base/jdk.internal.access=ALL-UNNAMED --illegal-access=warn 加上不然模块之间无法直接调用 其二 其它模块反射机制都可以使用reflectasm 替代,比如事件模块 其三 可以直接封装在底层jar中,业务开发者就不用关心调用 app stop 暴露给业务层,底层统一处理 @agent 注解方式 简化代码 class data 热更 #### 软件架构 ASM 如果生成class 字节码文件 直接加载进jvm 内存中,如何调用 难道用反射,使用ASM就是避免使用反射 ASM 自定义一个类 方法,然后修改这个类的方法 最后重新加载进内存中。 产生的问题就是自定义了一个无效的类 ASM 自定义接口ASM实现这个接口,然后就可以接口调用。。。。 这个方法只需要定义接口即可 如果在游戏启动的时候,使用反射实例化一次之后仅仅是调用 ,如果class字节码文件不生产直接加载进内存中 就无法使用路径反射,所以说反射无法实现这种 ASM 动态生成字节码加载进jvm 代替反射,来实现网络请求分发 架构层面 1、测试kcp + tcp 同时支持 ,压测kcp ,现在是实时update 消息(kcp 还有一种定时器10-100毫秒 update 优化点) 2、事件重写以及测试 支持同步和异步 ,方便业务的任务 成就。。。。等功能 【搞定,事件是反射调用。这点后期进行优化 最好像网络消息一样直接调用】 3、http协议支持,方便登录服 和 充值服 使用 【支持,后期优化压测】 4、web层架可以暂时不加,自己的博客可以使用web 5、ORM 优化以及压测 支持读写分离 【读写分离支持】 6、log 优化 【优化LOG】 7、网络回调,不然会阻塞线程、初步设想 mysql redis 数据操作创建线程等待拿到结果后投递给玩家actor 最后销毁临时线程,这样就可以尽情的使用redis 单片10wQPS ,不会阻塞业务线程 ,不然即使开了线程池大量的redis mysql 操作也会被阻塞 8、定时器 9、分表 业务层面 1、道具系统重写,避免新增道具类型就要堆积代码的情况 2、邮件系统可以单独进程处理 3、网关的必要性,client -> 网关服务 客户端只和网关保持连接 然后网关转发其它服务 匹配服 游戏服 邮件服 ...... 4、成就系统的重新构思,目前成就 版本迭代过程中新增成就,只能登录全局校验增加 2022年12月5日 18:55:41 ORM还需要时间持续优化 比如 单个线程处理db同步情况下 吞吐量才220/s ,InnoDB引擎应该有一定影响。明天先把读写分离处理了 读写分离可以使用aop 进行处理,判断方法名称进而使用不同的 数据库 db 压测 增删改查耗时情况 2022年12月6日 18:49:15 ORM 读写分离基本完成,ORM 代码看看如何重构以及优化 排行榜 内存级别操作 是不是可以搭建一个排行榜服务器,启动服务器的时候加载db进jvm 然后信息变动内存操作返回。异步操作db 异步db 两种方式 角色分配db线程 数据库表分配db线程 角色分配db线程,每个db线程干的事情都差不多。表分配db线程,可能有的db线程会出现很忙的情况 如果角色分配db线程,角色之间的数据互相操作 角色ID 分配db线程 操作增删操作 , 定时任务 x分钟 对数据表进行更新操作 角色ID 分配的业务线程 处理业务逻辑 & 查询操作 db代理进程 从db load 数据 增删改 ,db线程定时操作 缺点:进程崩溃 ,一段时间数据丢失风险 2022年12月12日 18:57:17 ORM 进一步优化 ,支持map list 转json 存储 ,支持 Array[Byte] 字节数组存储 。这块有一点需要进一步优化List[Bean] 从db load内存 转回List 写法不优化,因为到了转换那一步 无法知道Bean 的 class 道具系统 1、频繁增加删除 2、道具类型 道具ID 数量 ,基础字段 网关构思 1、消息转发不同服务,维护玩家连接 2。多节点网关,如果其中一个节点崩溃。客户端重连其它正常网关节点 3、网关节点需不需要互联,【不需要】 信息进入不同服务节点 必然会带上网关ID,不同服务网关ID和玩家ID进行绑定,如果其它网关节点挂了,玩家重连其它的网关节点。更新所有服务绑定关系 4、网关必然启动 kcp + tcp 或者 tcp server,其它服务只需要 clent 连上所有的 network server , 网关 和 服务都维护之间的映射 5、网关的列表如何获取,必然动态列表 峰值动态拓展网关,优先读取web GM网关信息配置 存储redis or mysql #### 构建环境 1. jdk17 2. maven3+ 3. mysql8+ #### 启动方式 ``` //启动容器 AppContext.run(AppMain.class); RestfulBootstrap restfulBootstrap = RestfulBootstrap.getInstance(); restfulBootstrap.controller(HttpController.class); //启动httpserver restfulBootstrap.start(); ``` #### class热更 ![class热更](image.png) ![class load](class-load-1.png) @Agent 注解方式简化开启热更新开启 默认目录 classes/ricks ![调用方式对比](https://foruda.gitee.com/images/1672934175686268755/4c893774_628156.png "屏幕截图") ### 机器人压测,内部通信协议选择思考【5000个机器人 200ms一次消息发送】 ![输入图片说明](picture%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8E%8B%E6%B5%8B-1.png) 机器人监控 ![输入图片说明](picture%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8E%8B%E6%B5%8B-2.png) 网关监控 ![输入图片说明](picture%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8E%8B%E6%B5%8B-3.png) 业务监控 ![输入图片说明](picture%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8E%8B%E6%B5%8B-4.png) 5000机器人压测情况下,可以正常登录无延迟感受 因为内部通信改成了KCP,如果机器人超出5000会出现消息堆积在待发送队列中, 待发送窗口转移至 已发送待确认队列 需要判断窗口大小(已发送待确认下标 + 窗口大小 大于 下次发送下标 ) ![输入图片说明](picture%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8E%8B%E6%B5%8B-5.png) 如果一端发送效率慢了,就会出现发送队列堆积的情况 ![输入图片说明](picture%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8E%8B%E6%B5%8B-6.png) TCP是基于流的方式通信,所以可以充分利用带宽。 KCP 是基于报文的方式通信 ![输入图片说明](picture%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8E%8B%E6%B5%8B-7.png) 对外协议可以使用KCP ,因为每个会话都是一个客户端。服务端对应每个客户端都是一个KCP对象。如果对内也使用KCP 就意味5000个玩家的数据都涌入一个内部KCP会话中,压测中必然会导致消息堆积 结论:内部通信本来延迟就很低,外部网络才会存在很多不确定性网络波动大 选择使用KCP毫无争议。内部通信需要充分利用内网带宽。 **内部通信走TCP** ### http压测 100并发请求1000w ![输入图片说明](http%E5%8E%8B%E6%B5%8B-1.png) 吞吐量在12w+/s ![输入图片说明](web%E5%8E%8B%E6%B5%8B-2.png) 响应时间都在1ms以内 **gitee blade框架 同样100并发请求1000w压测** ![输入图片说明](web%E5%8E%8B%E6%B5%8B-3.png) 实际压测QPS 7.5w,当时作者在文档中写的14w QPS ![输入图片说明](web%E5%8E%8B%E6%B5%8B-4.png) ![输入图片说明](web%E5%8E%8B%E6%B5%8B-5.png) 有时间再压测下Hserver web框架