在 MediaWiki 中使用腾讯云 COS 对象存储存储图像
前言
鄙人是某小MC服的服主,平常为了记录服内的破事和一些基本概念便选用了 MediaWiki 为服务器知识库的框架,陆陆续续用到现在也有2个年头了。
最近在日常维护摸鱼的时候发现空间占用越来越大了。一查发现 wiki 目录下的 /images 文件夹占了 2.6 GB 多。
我用的是腾讯云(香港)的轻量云主机,空间只有 30 GB。一直这样下去 30G 的空间可能会越用越少。于是经过一番资料查阅后,打算把图片数据从 wiki 本体中分离开,迁移到腾讯云的 COS 对象存储。
虽然我自己在建站这方面基本一窍不通,但还是这里写个专栏记录一下(免得以后忘了自己怎么操作的),除了给自己看以为希望能帮到有同样需求的人。感觉中文互联网上关于 MediaWiki 的教程还是偏少(为了搞短链接折腾了大半个月)。

特点
图片如果存在 MediaWiki 默认的附件目录下,用久了以后占用会越来越大,再加上机子上还跑着朋友的网站,肯定不够用,于是果断转用腾讯云 COS 对象存储。
图片加载速度变快(取决于存储桶地域)。我的主机在香港,更换后加载页面图片快了许多(存储桶在上海,访问是福州电信)。
减少空间占用。迁移后站点只有 200 MB 了,比朋友的 XenForo 站点还少了很多。
但是但是,存储桶的费用需要额外支付,你可以购买资源包。
TTFB 会慢一些。使用 MemCached + PHP 操作码缓存能起到优化的效果。


环境
图方便所以用的是宝塔面板,文中以宝塔面板 + CentOS 为例示范。
MediaWiki 版本: 1.39.1
宝塔面板版本: 7.9.7
站点 PHP 版本: 8.1
Nginx 版本: 1.22.1
MySQL 版本: 5.6.50
系统: CentOS 7.6
主机: 腾讯云 轻量应用服务器 香港(2C2G 30M)

开始安装
使用腾讯云 COS 实现外部存储需要使用到一款 MediaWiki 扩展。GitHub 链接见下,根据页面信息来看,支持 1.35 及以上的版本。我在 1.39.1 下实测一切正常。
https://github.com/RazeSoldier/MediaWiki-extension-QCloudStorage
有经验的站长可以直接进入 GitHub 页面安装并配置。
但无论如何,操作前请备份!操作前请备份!操作前请备份!

插件安装
这一步是下载扩展本体。进入宝塔面板的“文件”页,切换路径到你的 wiki 扩展目录下(/extensions),点击“终端”按钮。克隆仓库,并等待命令执行完成即可。
git clone https://github.com/RazeSoldier/MediaWiki-extension-QCloudStorage.git


1、这一步是重命名。命令执行完成后关闭临时终端窗口。刷新页面,扩展目录(/extensions)下会出现名为 mediaWiki-extension-QCloudStorage 的文件夹,将它重命名为 QCloudStorage。
2、这一步是安装 PHP 依赖包,这一步很重要。扩展除了本体以外还需要其他的 PHP 依赖包。切换至宝塔面板的“网站”页,点击你的站点。进入“站点修改”窗口后,选择 Composer 选项卡。
如果提示缺少 Composer 管理器,请安装后继续。选项卡内的 PHP 版本根据你主机的实际情况选择(我安装了 2 个版本的 PHP),执行用户切换为 root 以避免权限不足。执行目录切换到 /extensions/QCloudStorage 下。也就是我们刚刚重命名的文件夹。
以上步骤都操作后,点击绿色的“执行按钮”,开始安装依赖,如果下载速度很慢可以切换为阿里源。安装完成后宝塔会出现“安装完成”的提示。安装完成后,重启 PHP。

3、这一步是加载扩展。进入宝塔面板的“文件页”,对 wiki 目录下的 LocalSettings.php 文件进行编辑。在其中添加以下内容。
wfLoadExtension( 'QCloudStorage' );
加载扩展后可在 wiki 的“特殊:版本”页面中验证是否安装。


COS 配置
安装步骤完成后,我们需要腾出手来确定 COS 的基本信息。请确保你了解以下关于 COS 的信息。
存储桶名称(如 bucket-114514)
存储桶地域(如 上海、北京)
腾讯云 SecretID
腾讯云 SecretKey
存储桶的权限模式不能是“私有读写”,“公有读私有写”或“公有读写”可以。此外,存储桶最好离主机近一点。
存储桶信息可在腾讯云控制台内查询,SecretID 和 SecretKey 为腾讯云账号 API 密钥管理中的信息。可以使用主账户也可以新建子账号。


配置
安装步骤完成后,我们需要对 QCloudStorage 扩展进行基本的配置。请不要关闭 LocalSettings.php 的编辑窗口。接下来的操作依旧与 LocalSettings.php 相关。
1、在 LocalSettings.php 添加根据你的 COS 配置信息添加信息。只有添加注释的行才能修改,其余的请一个字符也不要修改,注意大小写。
$wgFileBackends[] = [
'name' => 'qcloud',
'class' => \RazeSoldier\MWQCloudStorage\QCloudFileBackend::class,
'wikiId' => 'wiki',
'bucket' => 'bucket-114514', // 你的存储桶名字。格式: `<name>-<appid>`
'lockManager' => 'fsLockManager',
'viewpoint' => 'https://cdn.example.com', // 自定义域名,一般用不到,CDN 或者全球加速之类的才需要。如果不需要不要添加此行。
];
$wgQCloudAuth = [
'region' => 'ap-guangzhou',// 存储桶地域
'secretId' => 'XXX', // 腾讯云 SecretID
'secretKey' => 'XXX', // 腾讯云 SecretKey
];
添加好以上参数后,保持并关闭文件编辑器。在“特殊:版本”页面刷新,刷新没有提示崩溃信息则说明配置无误。
2、开始转移旧图像。进入宝塔面板的“文件页”,切换到 /maintenance 目录下,点击上方的“终端”按钮,在终端窗口内输入以下内容。
php copyFileBackend.php --src local-backend --dst qcloud --containers local-public
也许 PHP 会提示 "syntax error" 和 "PHP warning" 等,无需在意。在这之后出现 "Copying file(s)..." 后就意味着文件开始像 COS 存储桶转移。具体的操作时间取决于你的主机上传速率、已有的图像大小。
如果发生错误,请检查存储桶信息配置、安装 PHP 依赖包是否有误。
我花了6个小时转移。文件夹总大小虽然只有 2.6 GB,但里面的小文件、产生的略缩图很多,建议挂在那。宝塔貌似页面关闭终端也会断开,担心断开的可以用 SSH 操作。


3、再次打开 LocalSettings.php 编辑窗口,在里面添加以下内容。本段的任何文字都不需要修改。
$wgLocalFileRepo = [
'name' => 'local',
'class' => \RazeSoldier\MWQCloudStorage\QCloudRepo::class,
'backend' => 'qcloud',
];
保存并关闭编辑器,刷新页面即可。
4、进入腾讯云存储桶“安全管理”选项卡中的“跨域访问CORS设置”,按照站点信息添加规则。


这一步是为了避免以下情况做的,避免不对跨域进行设置从而导致 MediaViewer 无法加载图片。如果没这个问题可以跳过这步。

验证是否生效的话,在已上传文件里随便找个图片打开看看原链接是不是指向 COS 的就行了。但一般来说只要 $wgLocalFileRepo 添加在 LocalSettings.php 文件中就会立刻生效的,就算有问题你刷新页面后也能发现。
确定一切没问题后就可以删除 /images 文件夹了。删除后空间一下子多了起来,看着舒服多了,就 200 MB 出头。

踩过的坑
配置后提示 MediaWiki internal error 和 QCloud not found 是为什么?
PHP 依赖包安装有误。退回去看看那一步哪里出了问题。如果确定安装后还是报错,重启 PHP 应该能解决。
转移旧图像出错是为什么?
检查 PHP 依赖包安装是否有误。如果无误再检查下输入的命令有没有问题?
转移过程中可以有其他用户编辑吗?
这我还真没试过,但转移时别让用户上传文件,可以暂时禁用。编辑页面和数据库有关,和图库反而没啥关系,编辑页面应该不影响。但还是建议都暂时停一下。
为啥和 GitHub 页面中步骤不一样?
我按照自己经验写的,尽量把踩过的坑写出来。。。按照原文也可以的嘿嘿
为啥我转移完文件后图片都没加载出来?
确定配置文件里的参数都没问题,重启 Nginx 看看。
配置好了,但是访问速度变慢了?
可以配置对象缓存可以缓解速度,使用 MemCached + PHP 操作码缓存后网站的 TTFB 已经与未配置 COS 时的速度接近(我这边 3s~4s 左右,已经是能接受的范围内了,未优化的时候速度能到 15s 甚至更高)。可以参考官方关于性能优化的文档,当然具体为啥我也不太清楚(看 Issues 貌似是腾讯云那边拉取对象耗时的原因)。。。
https://www.mediawiki.org/wiki/Manual:Performance_tuning/zh
如果可以的话,配置 CDN 也许也可以提升加载时间。