- 博客(319)
- 收藏
- 关注
原创 Python 代码远程调试
debugpy 是用于远程调试 Python 程序的工具,尤其在 VSCode 中调试时,无法直接附加 Python 进程时,debugpy 提供了解决方案。通过参考官方文档,可以轻松实现远程调试。此外,VSCode 支持通过 Compound 配置一键附加多个进程,方便同时调试多个 Python 程序。需要注意的是,debugpy 与代码覆盖率工具如 coveragepy 都依赖于 sys.settrace,因此两者无法同时使用,存在冲突。
2025-05-10 10:43:59
369
原创 KBEngine 源代码分析(三):组网逻辑
组件收到 onRegisterNewApp 协议的通用实现是 ServerApp::onRegisterNewApp。比如 baseapp basemgr loginapp 等都是不同组件类型的组件(服务)号的,都是 Y ,即有链接)服务发现的方法是其他服务使用 UDP 广播的方式,通知所有 machine 服务。=1 时,会根据组件的连接关系,向 machine 获取这些组件类型的组件信息。machine 服务是 KBEngine 用来做服务治理的。首先 machine 的眼里,维护的都是组件信息。
2025-04-30 11:55:56
66
原创 KBEngine 源代码分析(三):组网逻辑
组件收到 onRegisterNewApp 协议的通用实现是 ServerApp::onRegisterNewApp。比如 baseapp basemgr loginapp 等都是不同组件类型的组件(服务)号的,都是 Y ,即有链接)服务发现的方法是其他服务使用 UDP 广播的方式,通知所有 machine 服务。=1 时,会根据组件的连接关系,向 machine 获取这些组件类型的组件信息。machine 服务是 KBEngine 用来做服务治理的。首先 machine 的眼里,维护的都是组件信息。
2025-04-30 11:53:13
60
原创 KBEngine 源代码分析(二):协议注册和处理
比如我们查看文件说明协议定义。通过宏来表达协议定义。宏展开,即生成真正的宏定义代码与协议定义相关的宏。
2025-04-28 16:01:31
90
原创 KBEngine 源代码分析(一):Python C++ 混合编程
不过不影响学习如何使用 Python 官方库提供的 API ,实现 C++ Python 混合编程。目录提供了 KBEngine 把 C++ 代码中的类注册到 Python 的机制。类也没实质性东西,主要继承了 Python PyObject 类和调用了宏。类和一些列宏,按上述格式填写,就可以把 C++ 类注册进 Python。这 2 个文件,封装了下,在 C++ 中调用 Python 的。相对现在的 C++ 17/20 ,这个目录的分装相对不优雅。具体代码就不详细说明了,问 AI 就能懂啦。
2025-04-23 17:06:32
60
原创 交易行梳理
因此类似 MySQL InnoDB Redo 日志的方式,可以保证已经做到哪一步,或者操作完成了。某些情况,可能重试就是失败,比如下架中进程重启;但是又在其他进程被人买走。订单分布式锁过期处理也可以一定程度上保护因为合理的并发导致重试失败。简单起见,不需要做 Undo 日志,即不做回滚功能。Redo 不要写文件,统一为 DB 读写,作为一张表。交易行查询服(exquery)可以独立出来。注意以上 DB 表设计,主键中首个字段为。因此失败几次,要限制重试次数。需要引入对象池,避免内存分配和碎片问题。
2025-04-17 15:23:44
927
原创 排队系统梳理
概念别名说明承载上限在线人数上限在线人数OnlineNum当前在线人数玩家的票玩家持有的票最新的票号NextTicket下个排队获取的票号放票窗口该区间的票号可以进入游戏单次放票人数避免放票窗口开的过大,让并发登录给服务造成压力逾期放票间隔避免放票窗口停止不动。
2025-04-16 13:43:40
440
原创 状态同步梳理
后端场景主循环 30帧/秒,根据客户端输入(可能有),将场景中的变化状态信息,广播给场景内客户端(也可以是 AOI 内)可以看到 FPS 正好相对奇葩,介于 MMO 与 MOBA 之间。直接使用 MMO 方式状态同步更好?其次,FPS 人数又远小于 MMO ,帧同步游戏技术的一些特性就可以拿来用了。但是假如,项目有 FPS 技术基础,单人本状态同步的流畅性就可以发挥到极致了。即使网络时延几秒(甚至更长),玩家也可以有流畅的体验。一般的用 MMO 方式的状态同步即可。
2025-04-09 17:38:03
511
原创 MMO 架构梳理
每个进程定期拉取 Servers ,对感兴趣的服务信息和本地做 diff,进而知道服务新增或失效。Game 会缓存角色数据、场景数据,玩家下次登录在缓存有效的情况下,应该进原来的 Game。回复 Client OK ,并转发切换场景给 Game ,Game 本地场景切换逻辑。切换的前提是该场景事先已创建,如何实现创建,需要走具体业务逻辑。服务依赖,不是功能,是项目服务间依赖关系的一种客观事实描述。,保证不管任何并发情况,分配的 Game 是一样的。这样每个进程可以对自己感兴趣的服务,收集服务信息。
2025-04-09 12:02:13
1119
原创 游戏赛季和数据处理
在无赛季时,通常标识一条数据所属,会用 [ AccountID, RoleID ] 来标识。提供摘要文档输出,这样就可以方便的判断新赛季是否有哪个功能需要修复数据。赛季通常跨度几个月,新赛季会有很多配置调整,通常以人力无法对比。因为每个功能数据,数据什么级别数据,都是事先已知确定的。即问题 1,功能代码可以几乎不做任何代码修改即可。因此只要 DB 存储层做支持,即可。
2025-04-08 16:24:29
474
原创 看 MySQL InnoDB 和 BoltDB 的事务实现
单写(串行写):写时拷贝当前 B+ 树,构建新 B+ 树,最后原子切 meta 页。MySQL 事务不会锁表,不同行记录的写操作,可以并发(某些不行,注意间隙锁)它的 MVCC 为 N 个版本,粒度是按行可以有多个版本。多读:一致性非锁定读,不同事务隔离级别读取不同行版本数据。它的 MVCC 为 2 个版本,当前版本和正在写的版本。MySQL InnoDB 支持多读多写方式的并发级别。BoltDB 支持多读单写方式的并发级别。多写:不同行的写,可以并发。多读:可以并发读当前版本。
2025-03-25 14:54:32
238
原创 MySQL InnoDB 事务隔离级别和锁
READ COMMITTED(读取已提交)和REPEATABLE READ(可重复读)的读,会根据 MVCC 机制,读历史版本数据(不同的是版本的定义不同)根据锁的粗粒度,还有意向锁(InnoDB事务并发决策用的,可以不用关注)根据事务隔离级别不同,可能为行锁,或升级为间隙锁。非唯一索引的 SQL 语句,均可以升级为间隙锁。
2025-03-20 21:29:23
441
原创 看 MySQL InnoDB 和 BoltDB 如何写磁盘
DB 产品,会 WAL 后再写磁盘;WAL 日志又称 redo 日志,用于失败时的恢复操作。BoltDB 的实现构思巧妙,相当于新建 1 棵 B+ 树,原子切换 meta 页。看下 MySQL InnoDB 存储引擎、 BoltDB 是如何解决该问题。需要写的页数 1 页到 N 页不等(数据少,就在 meta 页)BoltDB 当前 meta 页指向磁盘 B+ 树。因为实际磁盘页未被写坏,因此总能 redo 正确。该页使用 redo 日志文件也无法恢复正确了。
2025-03-11 18:33:24
310
原创 一种日志聚类的方法
比如线上有大类日志,需要一种方法,统计各类日志输出的次数,并排列输出。这样可以比较直观的获取是否存在大量某些错误日志等。一般比较省事的,可以使用某些大数据产品,比如。
2025-02-20 16:16:38
211
原创 Jenkinsfile共享库介绍
类似的,比如获取某个服的 DB 配置等等,也可以在共享库内实现一次, jenkinsfile 中直接从环境变量中获取。jenkinsfile 通常是一些脚本,没有共享库,重复脚本会非常多。可以在 vars 下编写 groovy 文件,比如。每个 jenkinsfile 中,只要调用。比如, resources 目录下有配置。比如,重复的获取配置代码,到后期维护不易。共享库主要用来抽离公共函数。,自动加载对应服的配置。
2025-01-16 19:02:03
722
原创 Percolator 事务模型的理解和梳理
其他各种情况:正常、各种异常,都以 main lock 的情况,进而读取正确数据。根据上述介绍,可以发现, Percolator 对于异常是一种 lazy (懒)处理。这时, A 的值为 hello ( write 字段指示了当前数据是哪个版本)这里主要解释下,为啥这个阶段,只要 main lock 的提交成功即可。对于超时的情况,仅仅根据版本号,其实是不够的,因为数据可能在多台主机上。比较正规(严谨)的是版本号用全局时间戳代替,即版本号也是时间戳。任何一方写失败等,做回滚处理。
2024-07-17 17:39:44
698
原创 【C++】EntityX 的事件模块介绍与代码分析
该库使用 C++11 提供了,函数句柄的订阅与发布。本文不做介绍,以后再介绍,因为还有 C++14 tuple/index sequence 的实现方式。该类作用是内部实现用于包裹使用者自己定义事件,让其具备通过 Event()::family() 内部标识 E。即通过 Event()::family() 赋予 E 自动获得 EventID 的能力。使用者直接是自己定义事件 struct ,比如记为 E。是一个基于 C++11 的 ECS 开源库。这些代码均比较简单,细节,不再一一介绍。
2024-07-11 11:10:10
558
原创 【C++】一种优雅的枚举定义的代替技巧
很多系统,仅程序运行态时用来区分不同的值,这时,如果有不需要额外维护值的方法,自然是更优雅的。枚举值,在如 db 存取、网络传输等,需要关注确定的值,且不能修改。而上述方法,就非常简单、简洁的提供了自动生成不同值的一种方法。比如,做事件触发系统。代码时,发现一种更为优雅的定义方式。然后事件类型,通过继承。
2024-07-09 22:15:23
277
原创 聊天服实现设计
用哈希算法做玩家-聊天服的路由,是最轻量。但是对于聊天服失效、扩容、缩容需要做些而外的处理。这样机制,失效、扩容、缩容时,玩家可能会丢失 1 个心跳期间的消息,但是不重要可以接受。(如果感觉复杂,可以把路由信息所有聊天服同步、全量路由副本)类似还有公会聊天、好友群组聊天。
2024-07-06 15:24:35
539
原创 使用 gdb 脚本捕获 crash 时的 stack
原来我的做法是,用 signal 在程序内注册异常处理句柄,执行 gdb 命令。脚本内容都是 gdb 的命令,很简单,可问 ChatGPT。这段脚本,可以在程序 crash 时,把堆栈信息,存入文件。相比而言,这种方法更轻便、灵活,且无侵入性。
2024-07-03 12:29:15
307
原创 skynet - 多线程 Actor 模型
Actor 模型中, Actor 间通过消息交互。因此 skynet 的 module service 均有自己的消息队列。thread_monitor 每 5 秒检查 1 次,如果版本号不变,打印日志警告,有线程可能死锁了。工作线程,要执行 Actor 消息,首先从全局消息队列摘取 Actor 的消息队列。为了能让 Actor 高性能并发执行, skynet 中设置了全局消息队列。工作线程执行的都是 Actor 消息处理。skynet 给工作线程设置了优先级。工作线程在没消息后,会 sleep。
2024-05-19 23:16:58
1019
原创 skynet - spinlock 简单的自旋锁
atomic_load_relaxed_ 函数内用的是 memory_order_relaxed。memory_order_relaxed 即普通内存访问。memory_order_acquire/memory_order_release 比较好理解,请自行度娘。因此 atomic_load_relaxed_ 性能效果等价于普通内存访问(即性能最高),while 空循环的一种性能优化,度娘了解知道就好。
2024-05-12 21:30:49
461
原创 Lua 协程池
阅读了 skynet 相关使用协程的代码,发现 skynet 使用了协程池。中介绍了 Lua 协程的使用,模仿 golang 封装了下。还可以做进一步的优化。
2024-05-11 14:40:04
620
原创 使用 Lua 协程模拟 Golang 的 go defer 编程模式
由于项目中暂时是一根线程管理一个 lua_state 对象,因此暂时无需求多线程中的协程间的通信需求。因为要对 defer 的函数句柄做保持,以便退出时执行。以上就可以在 Lua 中完全 Golang 的方式编写协程代码了。Lua 协程异常,通过。捕获,并返回错误信息。
2024-04-30 10:44:40
1473
2
原创 使用 Lua 协程处理异步回调函数
通过封装提供 go 函数,可以像 Go 语言一样,提供简易的启动协程界面项目的所有异步均可以封装提供 co_xxx 函数,使得需要回调的 API 均可以顺序编写代码。例如co_sleep等等。
2024-04-14 11:32:14
1044
原创 离线 Linux 开发环境搭建
虚拟机可以使用 Windows 自带的 Hyper-V。内网需要啥软件,外网虚拟机下载好安装包,拷贝至内网安装。思路,内网和外网均创建一个环境一样的虚拟机。通常受限网络,网络模式更为复杂。无法连接外面的内网开发。
2024-04-05 11:06:34
706
原创 一种交易行的设计方案
交易行功能可以划分为 3 块:以上功能实现,主要有 2 个难点:为了解决数据一致性问题,这里引入 + 机制:实现细节如下:Redis 中一个事务,至少包括以下信息:,至少包括以下信息:事务的核心在于提交事务是原子的。即提交的一瞬间,能保证所有数据同时更改生效这里设计提交事务的操作为:该操作可以成功提交事务的原因如下:本地进程,均加个定时器,定期检查:本地进程,均加个定时器,定期检查:缺点,是在事务提交成功后,再应用数据。因此数据可能出现负数解决方案 2 种:优点事务细节分解步骤如下:根据以上步骤,很容易设计
2024-04-02 12:30:30
1058
原创 EmmyLua 远程调试 Lua 代码
项目中用到 LuaJIT ,正常思路静态链接了 LuaJIT 库。这导致了 EmmyLua 不能用。可以设置 export LD_LIBRARY_PATH=/your_so_path。EmmyLua 可以调试 C++ Lua 混合编程的项目。先启动项目要调试的服务;程序动态链接,需要寻找 so。
2024-03-28 18:23:07
855
原创 思考(九十四)跨服跨区消息处理
future 拿到结果,不会阻塞运行它的线程(协程遇到 IO ,先会被切走;这样,1 区 bfserver1 上的某个玩家 PA,它的公会是 GC ,先与它已经被分配在 1 区 bfserver2。这样,remote_call_v2 函数,对逻辑代码隐藏了架构细节。,很多系统,同样需要消息路由,也会有开头的 2 个问题。先有以上功能,且跑稳定后,可以再讨论进一步优化内容。没有什么黑魔法,就是通过路由表,做消息转发。因此,把角色登录中的分配资源的模块抽象出。接下来,顺着这里的思路,继续深挖。
2024-03-23 14:49:20
177
原创 iguana 库 C++ 反射原理
通过定义 REFLECTION 宏,在编译期,生成结构体/类的元数据信息字段名列表字段地址列表将字段地址列表做成 std::tuple将该 std::tuple 做成 std::map , 其 key 为字段名,其值为 std::variant 类型字段地址不同格式的序列化、反序列,最终要通过字段名给对象的字段赋值或取值通过 std::visit - std::variant 编程技巧使用函数类型特化方式,避免 if else 这种类型分支判断以上。
2024-03-16 13:49:19
1746
原创 doctest 中的编程技巧
官方介绍: The fastest feature-rich C++11/14/17/20/23 single-header testing framework。无独有偶, C++ 无栈协程也是一个 if else 分支组成。能多次重入,每次只执行一部分代码。从这个角度看,它们的核心编程技巧一样的。等等,就可以扩展逻辑功能。
2024-03-13 19:33:11
909
原创 进程间传递 SQL 文的方法
这样 2 个进程间传递 SQL 文还可以进一步适配具体项目,做调整。通常进程间传递数据,可以定义协议。因为是字符串 SQL 语句,因此可以方便的从一个进程传递到另外一个进程。有时,生成 SQL 文的进程和处理 SQL 文的进程,可能不是同一个。因为项目中使用 protobuf ,那么可以使用它,减少重复构造轮子。这里就涉及到如何高效的把 SQL 文从一个进程传递给另外一个进程。单步调试了下 go-sql-driver/mysql 的简易例子。结果,go-sql-driver/mysql 库也无。
2024-02-22 12:21:59
1071
原创 简易告警去重设计
方案二:每个服通过 Redis 共享 alarm 信息,自己处理去重。方案一:把告警信息打到 alarm 服,让 alarm 服去重处理。因为 alarm 去重逻辑很简单,方案一显得稍重,需要额外维护服务。粗暴的处理告警,通常会导致刷屏,进而麻木,最后起不到告警的作用。开发环境、生成环境,通常会有很多种告警,用来及时发现问题。这里设计一个简单的去重机制。
2024-02-07 12:27:03
513
原创 protobuf-go pragma.go 文件介绍
自己,其他第 3 方是没办法实现。目录下,对第 3 方不可见。因为第 3 方没有办法实现。接口的第 3 方扩展实现。下面依次说明实现原理。
2024-01-26 23:13:25
711
原创 网络卡问题排查手段
因为遇到这种情况,服务通常是不健康的,线上监控系统通常就已经在告警了。笔者就遇到过这样的问题,最后排查下来,只有韩国棒子用某运营商业务的手机网络出问题。对后端来说,网络卡了问题,本身很难去排查,因为是 App 通过互联网连接服务。如果能让玩家直观的感受到是网络卡而不是其他,这样上报的 bug 就更有针对性。根据这些信息,聚合成图表,对下事发事件,直接就可以排查是否是这个问题。开发过程中,通常就会解决掉了。比如,游戏画面上显示 Ping 延迟,就是一个好方法。特别是出海的游戏,遇到网络问题,首先就是拨测下。
2024-01-20 14:40:53
1055
原创 2D 物理引擎调研及游戏中的应用
关注的功能, 2 个库都有。而 Chipmunk2D 的 Golang 版本,目前还积极维护,因此选择 Chipmunk2D。如果是后端需要经常寻路的玩法(通常非常少),那么需要重新选择引擎了,比如可以选用 recastnavigation。Box2D Chipmunk2D 均不具备寻路功能,因为内部使用 AABB tree 组织数据的,便于高效查询。与场景相关的范围搜索、碰撞检测,理论上自己写也优化不出经典的 2D 物理引擎实作了。它们都是基于 AABB 包围盒的空间搜索优化算法。
2024-01-19 11:10:02
565
原创 Golang 使用 AST 获取方法和参数名以及应用举例
有了方法、参数名,加上反射,那么就可以方便生成胶水代码,自动集成进 HTTP 、 gRPC 等。可以把这些信息写入 map 声明,这样代码里就有类似反射参数的功能了。还是基于上面的获取的方法、参数名的 map 实例信息,就可以展开了。在做一些自动生成的代码工作时,有时需要知道方法以及对应的参数名。可以通过 AST 事先获取方法的参数名。如果仅是方法,利用反射机制就可以解决。而参数名,程序编译后,已经丢失。
2024-01-13 15:15:56
1088
1
原创 Ubuntu 虚拟机挂接 Windows 目录
如果没有这个参数,Ubuntu 下会无法更改文件目录的权限,导致 chmod 命令执行无效。我这里偷懒直接直接 Everyone ,也可以指定用户啥的。这对于 git 库下的文件会导致都有 diff 差异。然后把刚才的 mount 命令写到。首先 Windows 下共享目录。Ubuntu 默认没开启。这里打印的是已开启的。
2024-01-06 15:43:39
759
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人