<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Skynet on KK的博客</title><link>https://spin6lock.github.io/tags/skynet/</link><description>Recent content in Skynet on KK的博客</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Wed, 07 Jan 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://spin6lock.github.io/tags/skynet/feed.xml" rel="self" type="application/rss+xml"/><item><title>关于 sharedata 的使用</title><link>https://spin6lock.github.io/2026/01/07/%E5%85%B3%E4%BA%8Esharedata%E7%9A%84%E4%BD%BF%E7%94%A8.html</link><pubDate>Wed, 07 Jan 2026 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2026/01/07/%E5%85%B3%E4%BA%8Esharedata%E7%9A%84%E4%BD%BF%E7%94%A8.html</guid><description>&lt;p&gt;最近上了全节点热更配置表。起因是有一次热更配置表时没有覆盖全节点，导致数据不一致而 traceback，中断了一个重要流程。由于读表服务和目标服务的相关性比较隐蔽，热更 review 时没能发现这个问题，于是决定后续所有配置表都采用全节点热更。&lt;/p&gt;</description></item><item><title>当lua_sharedata碰上上限</title><link>https://spin6lock.github.io/2024/10/14/%E5%BD%93lua_sharedata%E7%A2%B0%E4%B8%8A%E4%B8%8A%E9%99%90.html</link><pubDate>Mon, 14 Oct 2024 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2024/10/14/%E5%BD%93lua_sharedata%E7%A2%B0%E4%B8%8A%E4%B8%8A%E9%99%90.html</guid><description>&lt;p&gt;最近在使用sharedata共享配置表的时候遇到了问题，报了stack overflow，&lt;a href="https://github.com/cloudwu/skynet/issues/1981"&gt;最小复现的例子贴在这里了&lt;/a&gt;。之前因为忙，没有细读过sharedata 的代码，这次事故正好临急抱佛脚读一遍，匆忙记点笔记，以后好回忆起来。sharedata是为了不同服务之间共享配置表而诞生的，通过sharedata接口拿到的是一个 c 的代理对象，并不直接持有配置表本身。正是通过这个代理，实现了配置表的无感热更，以及服务之间的配置内存共享。对于字符串来说，这个C代理持有的并不是字符串本身，而是一个索引，指向lua栈上的一个位置，真正需要的时候，再去lua栈上去拿这个字符串。在初始化的时候，会用一个 table来做字符串的去重，如果是一个新的字符串，则推到栈上并将栈的位置记录下来。以后这个字符串再次出现，也只会用同一个索引来代表，有点类似lua本身的短字符串共享。&lt;/p&gt;</description></item><item><title> 项目上线啦</title><link>https://spin6lock.github.io/2023/09/16/%E9%A1%B9%E7%9B%AE%E4%B8%8A%E7%BA%BF%E5%95%A6.html</link><pubDate>Sat, 16 Sep 2023 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2023/09/16/%E9%A1%B9%E7%9B%AE%E4%B8%8A%E7%BA%BF%E5%95%A6.html</guid><description>&lt;p&gt;历时 3 年半，项目终于上线啦，打开 tig 翻到仓库的开头，看看提交历史，还是有点感慨的，实在没想到要花这么久。简单聊点线上问题吧&lt;/p&gt;&#10;&lt;p&gt;这次上线最刺激的是，开服前半小时，发现昨晚压测的服务器崩掉了，原因是聊天服务内存太大导致 OOM。于是用 memlimit 紧急止血，出问题的方法挂到模块上方便后续线上热更，然后打包，重启，紧赶慢赶在开服前几分钟搞完，提前开服错峰。真的非常非常刺激，当然，线上也没有出现这个问题，我们压测的例子相对比较极端，一大堆人每 30 秒集体跳场景，注册场景聊天的地方又做了锁来保序，平台响应聊天只要有点延迟，就会导致堆积，超时设的 10 秒也有点太长了&lt;/p&gt;</description></item><item><title> 首次付费测</title><link>https://spin6lock.github.io/2023/07/15/%E9%A6%96%E6%AC%A1%E4%BB%98%E8%B4%B9%E6%B5%8B.html</link><pubDate>Sat, 15 Jul 2023 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2023/07/15/%E9%A6%96%E6%AC%A1%E4%BB%98%E8%B4%B9%E6%B5%8B.html</guid><description>&lt;p&gt;游戏终于走到了付费测试阶段啦，头几天遇到了一些奇奇怪怪的问题，记录一下&lt;/p&gt;&#10;&lt;p&gt;首先是内存问题，压测没有测到反复登录的情况，线上发现内存占用逐渐上升，到了一个玩家 40M 的惊人水平。正想着手查哪个模块耗的内存多，涛神下来讨论问题，让我先看一下 uniqtask 的返回，结果好家伙，基本上每个 agent 服务上都挂了 400 多个协程在上面，review 下代码发现每个协程都拿着一个角色，导致内存没法释放。兹事体大，没有立即解决挂起的协程了，先热更修复这个代码的问题，然后降低 agent 的复用次数，等玩家自然退出，销毁 agent 来释放内存试试。这里暴露出几个问题：&lt;/p&gt;</description></item><item><title> 压测周</title><link>https://spin6lock.github.io/2023/07/09/%E5%8E%8B%E6%B5%8B%E5%91%A8.html</link><pubDate>Sun, 09 Jul 2023 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2023/07/09/%E5%8E%8B%E6%B5%8B%E5%91%A8.html</guid><description>&lt;p&gt;最近一周做压测，发现了几个 skynet 使用上的问题，记录一下&lt;/p&gt;&#10;&lt;p&gt;目前的进程大概分成 center、login 和 room 三种，login 用来承接玩家连接，做一些单机玩法，center 做一些玩家间的附带玩法，比如公会、排行榜，room 处理房间相关的战斗逻辑和 aoi 剪裁&lt;/p&gt;</description></item><item><title>Skynet 广播优化小记</title><link>https://spin6lock.github.io/2022/04/05/Skynet%E5%B9%BF%E6%92%AD%E4%BC%98%E5%8C%96%E5%B0%8F%E8%AE%B0.html</link><pubDate>Tue, 05 Apr 2022 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2022/04/05/Skynet%E5%B9%BF%E6%92%AD%E4%BC%98%E5%8C%96%E5%B0%8F%E8%AE%B0.html</guid><description>&lt;p&gt;最近和 QC 同学共建一套自动化压测的框架，希望能够确定游戏的性能基线，通过自动化定期回顾，看看有没有引入性能劣化的代码。压测过程中，发现广播性能不够强，搞的清明假期也在家想问题，写篇博客记录一下&lt;/p&gt;</description></item><item><title> 使用 jemalloc 的潜在问题</title><link>https://spin6lock.github.io/2022/03/06/%E4%BD%BF%E7%94%A8jemalloc%E7%9A%84%E6%BD%9C%E5%9C%A8%E9%97%AE%E9%A2%98.html</link><pubDate>Sun, 06 Mar 2022 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2022/03/06/%E4%BD%BF%E7%94%A8jemalloc%E7%9A%84%E6%BD%9C%E5%9C%A8%E9%97%AE%E9%A2%98.html</guid><description>&lt;p&gt;今天读到一篇 &lt;a href="https://aosabook.org/en/posa/memshrink.html"&gt; 关于 Firefox 内存优化的文章 &lt;/a&gt;，里面提到使用 jemalloc 时遇到的一个小问题，不知道有没有现成的 API 可以统计，回头看看。&lt;/p&gt;&#10;&lt;p&gt;Jemalloc 是用来减少内存碎片化导致的内存损失的。内存碎片化是指可用内存被分成了一片片碎片，虽然总量够用，但是无法按需求分出指定大小的块。操作系统是按页（page）进行内存管理的，每页被浪费的内存会成为空洞；另外，部分释放回来的内存会在已分配内存间形成碎片，比较大的内存申请也塞不进去碎片里，导致内存损失&lt;/p&gt;</description></item><item><title>Skynet require 的更新</title><link>https://spin6lock.github.io/2021/07/18/Skynet-require%E7%9A%84%E6%9B%B4%E6%96%B0.html</link><pubDate>Sun, 18 Jul 2021 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2021/07/18/Skynet-require%E7%9A%84%E6%9B%B4%E6%96%B0.html</guid><description>&lt;p&gt;最近升级项目依赖的中间件，中间件组的同学强力推荐（&lt;del&gt;打发XD&lt;/del&gt;）我去看看 skynet.require 的修改，很有趣，而且是其中一个比较大的不兼容改动，我重新看了 &lt;a href="https://github.com/cloudwu/skynet/commits/master/lualib/skynet/require.lua"&gt;Skynet 的代码 &lt;/a&gt; 确实比以前更好用了，这里简单分享一下&lt;/p&gt;</description></item><item><title> 一些吐槽</title><link>https://spin6lock.github.io/2021/05/22/%E4%B8%80%E4%BA%9B%E5%90%90%E6%A7%BD.html</link><pubDate>Sat, 22 May 2021 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2021/05/22/%E4%B8%80%E4%BA%9B%E5%90%90%E6%A7%BD.html</guid><description>&lt;p&gt;感觉被周六加班榨干了，累的不想写博客。非常佩服其他同事，996 还看不出来有啥异样的，太强了。。3 月 4 月连续加班后，5 月终于可以放松一下，不用加班了。五一假期陪老婆回了老家，过了愉快的 5 天，后面补班就非常累了。。。&lt;/p&gt;</description></item><item><title>skynet.call 调用</title><link>https://spin6lock.github.io/2020/05/30/skynet.call%E8%B0%83%E7%94%A8.html</link><pubDate>Sat, 30 May 2020 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2020/05/30/skynet.call%E8%B0%83%E7%94%A8.html</guid><description>&lt;p&gt;上次 &lt;a href="https://spin6lock.github.io/2020/01/22/skynet%E4%B8%AD%E9%9A%90%E8%97%8F%E7%9A%84%E5%8D%95%E7%82%B9%E6%9C%8D%E5%8A%A1.html"&gt; 写了一篇文章讲 skynet.send&lt;/a&gt;，最近想起一个 call 的问题，流程跟 skynet.send 差不多，再记录一下&lt;/p&gt;&#10;&lt;p&gt;虽然官方 wiki 并没有记录，但是 &lt;code&gt;skynet.call&lt;/code&gt; 一个不存在的服务，并不会报错的，最神奇的是当你真的起了同名的服务，这个服务就真的能收到这条消息。&lt;code&gt;skynet.call&lt;/code&gt; 本质上还是 &lt;code&gt;skynet.send&lt;/code&gt;，只是 send 完以后将 session 号和 coroutine 记下来，然后自己调用 yield 将控制权交还给 skynet。按上篇文章所述，给一个不以 &lt;code&gt;.&lt;/code&gt; 开始的名字发消息，会经过 &lt;code&gt;service_harbor.c&lt;/code&gt; 的 &lt;code&gt;remote_send_name&lt;/code&gt; 函数。该函数先从 harbor 服务记录的名字哈希表里查找，找不到就新建一个 queue，将消息堆在里面。等同名服务起来后，就可以收到这条消息了&lt;/p&gt;</description></item><item><title>skynet 火焰图的新方法</title><link>https://spin6lock.github.io/2020/05/24/skynet%E7%81%AB%E7%84%B0%E5%9B%BE%E7%9A%84%E6%96%B0%E6%96%B9%E6%B3%95.html</link><pubDate>Sun, 24 May 2020 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2020/05/24/skynet%E7%81%AB%E7%84%B0%E5%9B%BE%E7%9A%84%E6%96%B0%E6%96%B9%E6%B3%95.html</guid><description>&lt;p&gt;最近 &lt;a href="https://rainbowcoder.com/"&gt; 子熏同学 &lt;/a&gt; 搞定了新的抓取火焰图的方法，他觉得改动有点多，不方便开源出来，不过我觉得思路很好，写篇文章记录一下&lt;/p&gt;&#10;&lt;p&gt;skynet 自带的魔改版 Lua，即使 Lua 代码在死循环，也能通过 gm 指令让 vm 停下来，看看出事的地方是哪里。这是通过引入 lua_checksig_ 来实现的。在 lvm.c 里，重点的几个 OPCODE: &lt;code&gt;OP_JMP&lt;/code&gt;, &lt;code&gt;OP_CALL&lt;/code&gt;, &lt;code&gt;OP_TAILCALL&lt;/code&gt;, &lt;code&gt;OP_FORLOOP&lt;/code&gt; 都会调用 lua_checksig 进行检查，如果设置了开关，就会通过 lua_error 中止运行。新的火焰图也是用类似方法实现，当目标服务检测到开关打开，就会将当前栈帧到 base_ci 的部分抓取下来，序列化成文本，放进一个全局指针里。然后另一个服务就会去读这个指针，将数据序列化到文件里，后续用 flamegraph.pl 进行火焰图的渲染&lt;/p&gt;</description></item><item><title>skynet 中隐藏的单点服务 : Harbor</title><link>https://spin6lock.github.io/2020/01/22/skynet%E4%B8%AD%E9%9A%90%E8%97%8F%E7%9A%84%E5%8D%95%E7%82%B9%E6%9C%8D%E5%8A%A1.html</link><pubDate>Wed, 22 Jan 2020 00:00:00 +0800</pubDate><guid>https://spin6lock.github.io/2020/01/22/skynet%E4%B8%AD%E9%9A%90%E8%97%8F%E7%9A%84%E5%8D%95%E7%82%B9%E6%9C%8D%E5%8A%A1.html</guid><description>&lt;p&gt;昨晚和同事一起看 skynet 的代码，对于 skynet 实现的按名字发送消息比较好奇，走读了一下代码，特意写篇文章记录一下&lt;/p&gt;&#10;&lt;p&gt;Skynet 服务间通信，比较常用的是 &lt;code&gt;skynet.send&lt;/code&gt;，该接口在 &lt;code&gt;skynet/lualib/skynet.lua&lt;/code&gt; 中，实现则是 &lt;code&gt;skynet.core&lt;/code&gt; 模块的 send 方法。&lt;code&gt;skynet.core&lt;/code&gt; 是 skynet 提供给 lua 的一个 so，代码在 &lt;code&gt;skynet/lualib-src/lua-skynet.c&lt;/code&gt;，它用了一个巧妙的注册办法：&lt;code&gt;luaopen_skynet_core&lt;/code&gt;，将自己注册成 &lt;code&gt;skynet.core&lt;/code&gt; 了。它提供的 send 方法就是 C 代码里的 &lt;code&gt;lsend&lt;/code&gt;，也就是 &lt;code&gt;send_message&lt;/code&gt; 方法。对于目标服务地址是字符串的，就会用 &lt;code&gt;skynet_sendname&lt;/code&gt; 实现发送&lt;/p&gt;</description></item></channel></rss>