« 字符串比较用 id 管理策略 | 返回首页 | 法线贴图的压缩格式比较 »

用 skynet 实现 unity 的 cache server

我们公司的一些 Unity 项目,当 cache server 的数据上涨到几百 G 后,经常遇到问题。最近一次是 nodejs 内存使用太多导致进程挂掉。

我不太想的明白,一个几乎不需要在内存中保留什么状态的服务,为啥会吃掉那么多内存。简单看了一下 cache server 的官方实现 感觉实现的挺糟糕的。它的业务很简单,还不如按协议自己实现一个。

Cache server 解决的是 Unity 的 asset 打包问题,一台机器如果把资源从 A 转换为 B ,那么可以把结果 B 提交到 cache server 上;后来的人就不需要重新做这个转换流程,而直接下载 B 。

怎么定义 一个 B 是从 A 转换过来的呢?Unity 的每个资源都有一个唯一的 guid ,如果经过转换,那么转换过程,包括了原始数据的 hash 版本号,平台,转换程序,转换参数等等,可以计算出一个 hash ;任何参数的变更都会导致这个 hash 变化。所以 guid + hash 就可以代表一个唯一资源的唯一版本。在需要做转换时,算出 hash 去服务器上查询,如果不存在,就在本地转换然后上传;如果后来的人重新进行这个过程,就会发现前人上传的结果,直接下载即可。

这个过程中, cache server 对资源如何转换完全不需要了解。它就是一个大的 hash 表,客户端可以用 guid+hash 作 key 读写数据。

官方是用 nodejs 实现的。我前几年看过一次,原来只有几百行一个很小的程序,这次再看发现增加了不少代码,但是基本业务并没有变化。我认为它一直都很糟糕,现在甚至比以前更糟糕。

简单列举一下我认为的问题:

  1. 用 js 实现了一个非常复杂的 cleanup 过程,用于淘汰掉可能不再使用的 cache 文件。这个工作不应该在服务本身的进程做,因为 nodejs 的逻辑是跑在同一线程中,cleanup 的过程很可能影响正常的服务业务。而淘汰 cache ,用一个 crontab 加一个脚本就可以做的更好。实在没必要增加服务的复杂度。

  2. 同时支持了 file cache 和 mem cache 。这可能是内存爆掉的元凶。mem cache 是没有必要的,因为如果进程本身占用内存不多的话,操作系统会把所有闲置内存用于 IO 的 cache 。这个服务可以看成是一个普通的静态文件服务,无非是打开一个硬盘目录中的文件,发送给客户端。自己再做一层 mem cache 实属浪费,它不会提升什么性能,如果提升了,那么一定是原有的东西实现的有问题罢了。

  3. 文件散列在 cache 目录中做的不好。只简单做了一级目录的散列。导致我们的项目同一个目录下有几万个文件。虽然在 linux 下 ext4 对同一目录下放太多文件支持的不错,但是很多 cache server 还是跑在 windows 下,ntfs 支持的就糟糕一些。更重要的是,这对远程管理的负担太大。就算在本地,列目录也会卡住(因为默认的列目录还需要对文件名排序)。

  4. cache server 本身的协议设计的太草率,基本就是能用就凑合。比如我摘取一小段官方文档里对握手协议的描述就可见一斑。

The server reads eight bytes of data from the first package received. If the package contain less than eight bytes, only those are used. Only exception if getting a one-byte package, in which case it should wait for the next package in order go get at least two bytes worth of data.

居然在一个 tcp 流上设计的协议,谈 first package ,又没有怎样区分一个 package 的描述。貌似指 api 的读取调用收到的第一串数据?握手有可能是 8 字节,也有可能是 1 字节。


除了协议之外,我认为用 skynet 实现一个一样的替代物应该没太大工作量。上周花了几个小时试了一下,果然只需要 200 行左右的代码。核心功能 100 行代码就可以了,另外做了不少优化的工作,以更适合管理更大的项目(多人协作的高并发,海量文件)。

目前,我自己写的版本在公司内部测试。希望日后可以逐步取代官方 nodejs 版本的服务。这样方便根据实际使用情况做进一步的优化。

Comments

今天也动手写一个,发现一个问题: unity请求cache的协议hash值不会随着源文件的时间变化,但是putting上传的cache文件会因为源文件的时间变化而与request的hash值不同,那么久没变让其他人使用我上传的cache了。 不知道这个问题云大大是怎么解决的
怎么评论跟QQ群一样,都这么low了
在现在云服务当道时代,我觉得用oss或者其他cache等方式都可以通过20-30行代码解决了。既可弹性伸缩,又能科学监控。
风哥威武,坐等skynet wss官方版本
需要 wss 支持的,可以去看看 https://github.com/cloudwu/skynet/pull/1056 这个 pr ,如果没有什么问题,我会合并。
看着看着发现评论风向不对,太欢乐了:) 小游戏爆炸确实让wss越来越热门了,毕竟js是统治宇宙的语言,哈哈哈
skynet支持http(s),官方例子改改就能成一个app+ctx的简便后端框架,原生wss的支持github上也有其它project已经实现= = 但讲真实际操作一定要强行耦合这么多协议吗= =
看到skynet最新提交的版本里已经添加https,相信websocket和websockets也将陆续完善,给云大点个赞
云风是我最想活成的样子
云风大哥,能独立写一篇关于“Skynet的定时器线程工作原理”的博客不? 下面我随便贴段关于定时器的Skynet源码: ------------------------------ static void timer_shift(struct timer *T) { int mask = TIME_NEAR; uint32_t ct = ++T->time; if (ct == 0) { move_list(T, 3, 0); } else { uint32_t time = ct >> TIME_NEAR_SHIFT; int i=0; while ((ct & (mask-1))==0) { int idx=time & TIME_LEVEL_MASK; if (idx!=0) { move_list(T, i, idx); break; } mask >= TIME_LEVEL_SHIFT; ++i; } } } --------------------------------- TIME_NEAR是什么含义?TIME_LEVEL又是什么含义? 原理我是小白,从skynet_main.c文件开始开过来,然后在迷失在“create_thread(&pid[1], thread_timer, m);”创建定时器线程开始,期望云风大哥写篇博客帮我梳理梳理,谢谢了
这里有人在捣乱,但我感觉这种玩法很low
云风大哥你每天是怎么学习的,能传授下方法不?
云风大哥66的
理性追星,风哥的技术确实可以说登峰造极,但也没有你这么夸大“分分钟”干嘛的,你们还是太年轻了!!
年轻人,吹牛吹大点,你丫的咋不把风哥吹出宇宙干外星人去?
想当年云大熬个通宵就把编辑数据配置文件的编辑器开发出来了,并且修复配置bug,skynet框架搞个wss还不是分分钟的事
I will try to learn English well in my lifetime and help CloudWu write English wiki.
Skynet这么优秀为啥wiki不弄个英文版的,争取在国际上提高知名度啊
如果skynet官方支持了ws和wss,那么这个web框架就真的几乎可以包干后端服务器任何开发了,想想skynet介绍上加上:Skynet是一款基于Actor模型、轻量、强大的Web服务器框架,它支持TCP、UDP、HTTP、HTTPS、WEBSOCKET、WEBSOCKETS协议,几乎可以帮助你做你想要开发的任何开发…… 想想就激动!
大神,膜拜一下
我风哥少年成名,一路走来,披荆斩棘,一步一个脚印,实力自然不是盖的。
嘿嘿,不是我吹牛,倘若云风大神真的花时间在skynet支持websockets上,估摸着也就是1天的事,各位兄弟,这“大神”的称号可不是随便盖的
使用skynet两年了,希望它能也来越完备,说到网络传输协议怎么能少了wss呢,强烈推荐云风大哥做官方支持
盖楼盖楼,希望云大重视一下这个问题:skynet官方提供下wss支持!
关于skynet官方是否可以提供wss支持的想法提得好,顶一个,云大好好考虑一下
网上虽然有在skynet框架里实现wss的诸多例子,但网络环境鱼龙混杂,很难分辨哪一个是真的稳定可用,还是skynet发布一个官方版本比较靠谱和省事,大家对云风还是信得过的。
对wss有需求的群众确实不少,希望skynet官方能提供一个稳定的版本。
现在大部分中小型公司都转战小游戏市场,如果skynet支持wss,那么受众面毋庸置疑将更加广泛。
期待skynet下一个版本发布支持ws和wss
skynet框架添加websockets, 路过顶一个 because.. 云大出品,必属精品!
为skynet添加wss打call,风哥加油
风哥,skynet框架wss支持一下
同感,顶楼上
skynet框架添加websockets,我也顶一个。
我还是希望云大能在skynet框架上支持websocket和websockets,虽然github上能搜到相关的解决方法,但这个模块就好比http、https、tcp或者udp传输协议,是框架应该具备的基础设施。
我相信云大,skynet集成wss势在必行
平平无奇古天乐 一无所有王健林 不知妻美刘强东 北大还行撒贝宁 普通家庭马化腾 随便挣钱丁三石 现在加一句,哈哈,风哥别生气 悔创Skynet CloudWu.
http和https都实现了,websocket和websockets还会远吗?兄弟们,云风大神肯定早就有这方面的想法了,只是一直没时间去搞而已。
是风哥兄弟的,就砍楼上的大嘴巴!风哥还在考虑当中,预计今晚会给我们答复,坐等评论区吧,熊蝶们......
你们都不要议论了,风哥已经跟我透露消息了,迫于广大群众的反馈压力,Skynet今年这个大版本更新会加wss这个模块。 兄弟我冒着被风哥指责的风险把命压这给你们透露,就是想跟兄弟们说一声,风哥肯定一言九鼎什么马都难追了,你们就放宽心等着吧。 哦,差点忘了跟你们说一声,今年Skynet大版本更新预计在11月份,大家再咬牙忍忍哈。
楼上滴哥,你这话,我竟无言以对ԅ(ˉ﹃ˉԅ) 云风大哥,What do you see?
云风是我最欣赏的国内程序员。 技术不用说了,稳。 具有崇高的开源精神,为国内编程技术贡献大家有目共睹。 Skynet是我最喜欢的web框架,我自然是希望它能越来越完备。 但云风大哥也是人,虽然说让Skynet集成websocket相关技术对于人家来说不是什么难事,但是大家也要考虑下人家的难处,人家现在也有要忙的工作,开源项目不盈利,既然有需求反馈,有时间人家自然也会去考虑这方面的供应,这也是我认为云风大哥是个good man的原因。 说不定下个版本更新,云风大哥就偷偷把这方面的需求方案commit上去了呢?
兄弟,风神也是常人,开源的目的还是希望牛人能多做技术贡献,利国利民利己
我给风哥讲个故事: ------------------------ 集市的餐厅如云,有一家餐厅冬季开业以来声誉很高,提供的餐饮质量好服务又好,好多顾客闻名而来。 夏季来了,天气炎热,往来的顾客都想来点冰的饮品,餐厅之前没考虑到这方面的需求,没安置冰箱,所以无法提供这方面的供应。 深有体会这家餐厅质量和服务的常客肯定不想因为这点不足就换其他餐厅,于是每每来这家餐厅用餐时都自带冰镇饮品。 但是很多初来这家餐厅的顾客却因为这点不足而选择其他餐厅。 如果这家餐厅一直不加完善这方面需求,那么只要夏季莅临,那么对这方面有需求的顾客流将会流失。 --------------------------
************************************* 大哥罩小弟,义不容辞。 大哥,wss这事,不能再拖了。 大哥,请收下小弟的膝盖~ *************************************
我们公司的skynet也是通过集成网上一些网友提供的wss支持库开发的,虽然集成可用,但我本人也是更希望skynet框架本身能支持这个模块,相信小游戏的兴起,中小公司对这方面的需求不在少数,框架本身添加wss相信对壮大框架的用户群体必然有实质性的意义。 之前框架不支持https,我们公司有些方面的需求,也是网上找方案解决,但现在skynet本身支持了,我们毫不犹豫的抛弃了之前的方案,改用框架本身支持的模块。对比前后还是能明显感觉到框架本身支持的https模块很好用。 我对经过云风大哥之手的东西还是更青睐的。
看来大家主要还是处于对云大技术的信任,如果云大觉得网上的一些对skynet支持wss的方案可以的话,就把它合并到skynet框架主支上去,这样经过云大审核的模块大家用起来还是比较放心的,并且也有理由相信经过云大审核后的代码合并到skynet框架后在性能和稳定性方面肯定也是经得起考验的,毕竟,没有人比云大本人对skynet的认知更全面。 如果有的选,在网上找wss支持库方案和skynet框架本身就支持的wss库方案,每个人肯定都会毫不犹豫的选择后者。 能力越大责任越大,虽然这不是您应尽的责任义务,我们都希望skynet能够在用户群体的反馈中愈加完善,希望您能花些时间把这块完善一下,我不好评估这方面的难度(和你们这些大牛相比,鄙人只是菜鸟一枚),但我相信,如果云大您肯花时间研究的话,肯定花不了多少时间。 Do you know how to define genius? HaHa,put on steam,CloudWu. A god-like man.
https://github.com/search?q=skynet+websocket 这里有一大堆 web sockets 的模块啊。
云风大哥,我这边的项目也有wss的需求,希望您能在skynet框架上提供支持。
云风大大,我也附议。。
我们公司即将从棋牌转型小游戏,到时也免不了网络传输协议要改websockets,希望云风大哥在skynet框架上能尽快提供相关的支持,真心不想换框架开发!
附议附议
对呀,云大,给skynet提供下ws和wss支持呗
附议楼上
.附议楼上
附议楼上
希望skynet支持ws和wss,这话我早就想说了,风哥花点时间实现下吧
If CloudWu wants to implement WSS, for him it was a weekend's work.Do you know how to define genius?
我也很期待skynet提供wss支持,去年小游戏火的时候,tcp给wss,skynet暂时不支持只能换个框架开发,还是怀念skynet开发,用起来舒服多了。
达则兼济天下 气就寻找下家 铁打的SKYNET 累死的CLOUD-WU 阿弥陀佛 贫僧法号--马度腾
Skynet要是提供wss支持那还不得一统web服务器?
在没有做微信小游戏前,我们公司的游戏服务器都是用skynet搭建开发的,后面公司涉及微信小游戏,网络传输协议由tcp转websockets,因为skynet暂时不支持,所以不得不选择其他web框架开发,个人还是比较喜欢skynet的,希望云风大神能早点让skynet提供wss的支持
skynet要是再支持下websocket和websockets那就完美了 期待云大早日完善
skynet 支持 https 。
云大,啥时候让skynet支持下https和websockets,虽然有些网友实现了,但还是对您提供的模块更放心。
云风大哥,lua也有自己的包管理工具(luarocks),为啥您在github上的开源项目不上传到luarocks上去?
看文章提到在缓存几百G时才会出问题,而我在一个大概 50G 左右的项目上就出问题了。 发现 Unity Cache Server 有严重的内存泄露,问题严重到将其所在的服务器卡死,导致 Jira 无法访问,具体信息可以前往:修复 Jira 无法访问 - 狂飙 https://networm.me/2019/03/28/fix-jira-cannot-work/ 最后也没有什么好的解决方案,只能定时重启完事。 在出现内存泄露问题时使用的 Unity Cache Server 是最新版本 v6.3.0,CentOS 也是最新版本 7.6,截止到现在 2019/07/09,这两个版本也是最新的稳定版本。 而这个 6.x 系列版本还是官方花大量时间重写的版本,说实话稳定性实在是不太高。 希望 skynet 实现的 Unity Cache Server 可以早日开源使用。

Post a comment

非这个主题相关的留言请到:留言本