本文将同步发布于 Yeecord 部落格 欢迎各位来朝圣ww,转载等需求请参照我们的 授权说明
前言
还记得刚开始摸索的时候是在 2019 年的样子,那时候 Google 上压根没什么中文的 Discord 机器人教学,乱翻看到了一篇在讲 discord.js 的文章,就此掉入了这个大坑里面,
后来机器龙在疫情线上上课那时候大爆炸才开始意识到这些严重性,每天跟稳定性战斗,还好在那时候也有救星的出现,我们最下面的章节将会谈到除了 discord.js 还有 其他的选择。
所以是为什么?
以下是我踩坑了挺多次总结出来的问题点,看完了再来决定要不要使用 discord.js,或是也可以直接跳去看 我该继续用 discord.js 吗?:
大更新像是抄家一样
人都是有惰性存在的,而使用 discord.js 绝对可以让你改掉这个坏习惯,我们知道这个套件有许多贴心帮你包好的如 avatarURL
、awaitMessageComponent
函式,好用归好用,不过遇到 discord.js 大更新时你就得开始忙起来了,
到文章撰写的时候 discord.js 已经更新到了 v14,我们可以翻阅一下从 v13 更新到 v14、v12 更新到 v13 的文件,看到侧边栏的目录超过整个页面的长度,我觉得我还是去躺好好了...
虽然开发团队在 Discord 伺服器中提及到 v13 版将会继续支援,并且还没有订定该版本的结束週期 EOL (End-of-life),但可以确定的是,这个版本终将会被弃用,还是必须要进行痛苦的转移过程。
如果你很喜欢 discord.js 并且想要避免每次大更新都要重写一次,可以将大量使用的函式包一个自己的版本,我们拿 User#avatarURL
来举个例子:
/*** @param {import("discord.js").User} user*/function avatarUrl(user) {return user.avatarURL()}
这样每当大更新时只需要更改自己包的版本就好了,剩下的时间拿来多打点 APEX 也不过分。
快取无法更动
discord.js 完善的快取系统在普通的小量使用上确实是挺方便的,不过在规模越来越成长下,越需要去注意到记忆体的控管,是不是可以努力减少一些不必要的快取,
而 discord.js 的快取在预设都是无法更动的,虽然有提供了 Options#makeCache
的选项,不过在文档中说明到 GuildManager
、ChannelManager
等核心的功能还是不能被覆写,像是频道、身分组及表情符号是最占用记忆体的前几名,这样还是令人堪忧。
discord.js-light
幸好有人发现了这个问题并製作出 discord.js-light 套件,可以直接覆盖掉几乎所有的 Manager 设定,不过因为还是第三方软体,并不是 discord.js 自带功能,最好在使用之前注意会不会让程式崩坏。
我自己有发现了一个神奇但是挺好用的解法,可以直接使用 JavaScript 神奇的 ProtoType 特性,
举个例子:若你发现你真的不会使用到 ChannelManager#cache
里的东西,先将 bot.channels
的 set
函式清空,需要用到时使用 ChannelManager#cache
的原型 Map
来执行 set
的工作,
详细的使用方式及程式码可以翻阅我们的 原文
机器人规模成长后难维护
当机器人成长到一定的大小后,如何架构将是一个重要的课题,架构层面我们先从如何做解耦 (decouple) 开始,可以把它简单的理解成两个元件要如何做拆解,详细的架构说明可以参考 Day 23: 元件原则 — 耦合性 by JC。
Discord 机器人通常可以拆解为 Gateway 和 Discord 沟通或是接收 Discord 的事件,REST API Proxy 执行发送讯息等操作,而到我最后使用 v13 版本时,所有功能还是都包在一起的,可能他们有在尝试做一些改变不过我不太确定。
紧耦合对维护来说非常困难,机器人在上线时会依照伺服器数量来分配分片 (Sharding) 的数量,每个分片上线都要先等待五秒的冷却时间,若每次更新需要重开时,都需要经过一次这样的上线流程,
而造成的下线时间 (Downtime) 十几分钟可是对稳定性和可靠性非常大的致命伤,可以看我们 Google 搜寻结果都可以被洗成这样了...
那我有其他的选择吗?
在我们部落格的 原文 中将会提及到你该怎么面对这些变革,以及有什么实际执行的办法,欢迎继续过来朝圣