这里是全站文章的归档入口,下面是按时间倒序排列的全部文章。若想按主题浏览,请从首页的专题分类进入。
《MMO 服务器开发》5.2 热重载的边界
热更不是「什么都能改」:数值、开关、掉落表可以热更,协议结构、数据模型与需要重建运行态的部分必须重启。本节给出 hot/warm/cold 三类边界判定,用双缓冲加原子指针交换实现无锁热更,并用「旧读引用不影响新读」的并发断言证明切换是原子的。
posts
这里是全站文章的归档入口,下面是按时间倒序排列的全部文章。若想按主题浏览,请从首页的专题分类进入。
热更不是「什么都能改」:数值、开关、掉落表可以热更,协议结构、数据模型与需要重建运行态的部分必须重启。本节给出 hot/warm/cold 三类边界判定,用双缓冲加原子指针交换实现无锁热更,并用「旧读引用不影响新读」的并发断言证明切换是原子的。
配置不能只靠重启生效:一个能长期运营的配置中心要有版本号、只推变化的差量、按服与按玩家百分比的灰度,以及节点应用后的 ack 回执。本节用本机 etcd 从零实现版本化存储与差量分发,把「配置写入 → watch 到变更 → 差量应用 → ack」整条链路真跑一遍。
优雅停服不是收到信号就退出,而是四步:停收新连接、排空在途请求、落库、退出。这一节先讲这四步的次序与跳过代价,再用一个真起子进程、真发 SIGTERM 的测试,断言在途请求不丢、账本落盘;最后讲有状态服务的代次交接,用单调递增的 epoch 挡住脑裂。
蓝绿、灰度、滚动是三种不同的取舍,不是三种写法。这一节先把四个维度——切换速度、资源占用、回滚难度、状态兼容——摊开对照,再把每种策略编码成一个可回放的发布计划,用一份能跑的 Go 代码,把「蓝绿一次切换、灰度分档爬升、滚动逐台替换」变成可断言的发布过程与回滚路径。
容器化与编排是把 aegis 从一堆进程变成可交付形态的第一步。这一节先讲镜像怎么分层、多阶段构建怎么把编译器和运行时拆开,再给出无状态网关的 Deployment 与有状态场景的 StatefulSet 两份清单,最后用一份能跑的校验代码,把「哪种角色能当 Deployment、排空预算必须小于宽限期」这些编排不变量钉成断言。
日志看得见单点、指标看得见全局,但「这次请求到底走了哪几个节点、卡在哪一段」只有链路追踪答得上来。这一节讲清 trace/span 的传播(trace_id 怎么跟着帧走)、跨服务链路怎么拼装,再讲告警规则的两种判据——阈值告警与变化率告警——以及抖动抑制与抑制关系。
日志能还原一次请求,但要回答「现在系统健康吗」就得靠指标。这一节讲清 Counter、Gauge、Histogram 三种类型的语义与最常见误用,重点剖析标签基数这个能把 Prometheus 拖垮的坑,再用 client_golang 真起一个 HTTP server 暴露 /metrics,并用 HTTP 真拉取断言关键指标存在。
日志不是越多越好。这一节先把一条请求日志该带的最小字段集钉死——trace_id、player_id、cmd、seq、cost_ms、result——再用 log/slog 写出一个能跑的实现,讲清日志分级、错误不采样的采样策略、手机号与邮箱的写盘前脱敏,最后给出一张该记与不该记的清单。
无界队列把「慢」变成「OOM」,热区不隔离让一段慢拖垮整帧。本节把 AOI、战斗等 CPU 热点拆到各自的有界队列与独立 worker 上,用三种溢出策略——拒绝、丢弃最旧、降级——显式决定「满了怎么办」,并用可跑的测试断言慢 AOI 不会阻塞移动、战斗事件永不被静默丢弃。
2.1 的剖析显示一帧的时间大头是分配与回收,不是算法。这一节把双栈项目的隐藏成本摊开:用同一份「分配 N 个对象并触发 GC」的工作负载,Go 侧读 runtime.MemStats 与 debug.GCStats,Java 侧读 ManagementFactory 的 MemoryMXBean 与 GarbageCollectorMXBean,在同机上真跑并对照,最后给出选型结论。
30Hz 的 MMO 服务端每帧只有 33ms,一 tick 里 AOI 广播、移动、战斗、定时器各占多少必须先量化再谈优化。本节把帧预算写成一张可断言的表,用 runtime/pprof 与 net/http/pprof 真跑一次剖析,并给出本机实测的相位占比与火焰图读法。
对照三个主流游戏服务端框架——Lua Actor 的 skynet、Go 分布式的 pitaya、轻量单进程的 leaf——各自的定位、适用规模与 aegis 的差异;再做全书收官:回顾四卷从网络内核到工程化运营的贯穿线,汇总可运行产物与实测数字,给出下一步建议,附一个能跑的全书产物清单校验器。
把全书四处双栈对照的实测收进一张跨栈矩阵:并发模型、内存与 GC、序列化、网络栈、部署形态、生态与招聘、开发效率与可维护性逐维度对照,再给出可判定的选型结论,并附一个能跑的选型打分器——输入团队与场景特征,输出推荐栈与逐条理由,权重可改可测。
压测器就位,接下来回答那个最初的问题:一台机器到底能扛多少。本节先设计两条扫描——连接扫描逼出单进程的连接天花板,负载扫描逼出吞吐与延迟曲线,再把本机实测数字(约两千连接、每秒数千消息、P99 分档)套进容量公式,算出集群要几台、留多少余量,以及瓶颈究竟落在连接数、CPU、内存还是带宽上。
站内没有 k6、wrk,压测器只能自己写。本节从零搭一个可编排的机器人压测平台:机器人状态机走完连接→登录→进场景→移动→心跳,并发编排用错峰建连绕开 macOS 的 accept 队列上限、用起跑线屏障把建连爬坡挤出测量窗口,最后真起一个本地回环服务端加五十个机器人跑通,并把结果落成 JSON。
「在线五千人」从来不是一句承载结论。本节先把承载指标的定义钉死——要有单位、要有变坏的方向、要能说出超标后怎么坏,再列出连接数、消息吞吐、P50/P90/P99、错误率、内存、GC 暂停这张表,最后拆穿只看在线人数、只看平均值、不看错误率、忽略慢连接这四种最常见的自欺欺人。
回到 library 的领域对象:类把字段(状态)和方法(行为)放在一起,new 创建独立实例,this 指向当前接收者;再分清实例字段与静态字段、默认 toString/equals 的真实行为,以及字段默认值带来的静默错误,为 7.2 的构造器和 7.3 的封装打底。
埋点质量决定端上观测的上限。本节把事件命名、必填字段、类型校验、时间戳与 session 规则写成可运行的注册表与校验器,解释如何用发送数与接收数检测丢失,并用 schema 对比管理口径变更,避免一次字段改动静默破坏历史数据与下游报表口径。
崩溃与卡顿的难点不是采集,而是把海量原始样本收敛成可行动的少数分组。本节给出崩溃消息归一化与签名聚合、卡顿阈值与样本字段设计、归因顺序(布局抖动、主线程阻塞、长任务),以及上报事件应携带的最小证据字段,并用可运行的 TypeScript 与真实测试输出验证每一步判断与取舍。
卷一收口最后一步,把性能、可用性、安全与可维护性写成刺激-响应-度量的可测场景,再把未验证项整理成带概率、影响、owner 与可执行关闭条件的风险台账。本篇给出 Go 数据结构、属性覆盖与逾期校验测试,并明确所有阈值只是口径,不是压测结果。