网站访问速度慢,首屏要5秒,搜索引擎一直不收录
杰奇CMS迁移实战,从卡顿到秒开的性能重构与数据迁移全记录
先别急着换CMS,先用 top 看负载,如果CPU跑满,八成是采集队列或者搜索功能在发疯,直接关掉后台的“实时搜索”和“自动采集”,改到凌晨3点用crontab跑,然后启用OPcache,php.ini 里设置 opcache.enable=1,opcache.memory_consumption=128,opcache.max_accelerated_files=10000,再检查MySQL慢查询日志,如果fulltext_search表膨胀了,立刻把搜索改成WHERE title LIKE '%关键词%',并加FORCE INDEX(primary),虽然糙但快。
章节表超过2000万行,写入慢、备份慢、随便一个ORDER BY id DESC就锁表
别再用一张大表了,立刻停站,执行:
CREATE TABLE chapter_2021 LIKE chapter; ALTER TABLE chapter_2021 ADD PRIMARY KEY(id, chapter_id); INSERT INTO chapter_2021 SELECT * FROM chapter WHERE create_time BETWEEN '2021-01-01' AND '2022-01-01';
然后建立视图或路由函数,在杰奇CMS的/lib/class/db.class.php里,重写get_chapter_content方法,根据novelid判断查哪张分区表,推荐用哈希分表:`$table = 'chapter' . (novel_id % 10),注意,杰奇原版很多SQL硬编码了chapter表名,你得全局搜索from chapter,改成from {$this->chapter_table},同时把chapter`原表删掉,只留一个空壳用于兼容旧索引。
阅读页加载卡顿,一个章节内容要1.2秒才出来,还经常崩
卡顿的根源在于每次翻页都查一次大表,并且没做缓存,直接改/reader.php读取加一层Redis,在/config/config.php里配置:
$memcached_config = array(
'host' => '127.0.0.1',
'port' => 11211,
'prefix' => 'jc_'
);
然后在章节读取函数里,先查$cache->get('content_'.$novel_id.'_'.$chapter_id),如果命中直接输出,没命中再查库并写入缓存,TTL设14400秒,禁止在阅读页执行SELECT *,只要content字段,其他字段一律剔除,还可以把content字段改成MEDIUMBLOB,并设置max_allowed_packet=64M,避免大文本浪费内存。
模板标签调不到数据,或者想改显示逻辑但找不到文件
杰奇CMS的模板标签其实是一堆函数,藏在/lib/template/function.php里,比如你想显示“最近更新”的10本书,直接改这个函数:
function tpl_books($array) {
$sql = "SELECT id,bookname,new_chapter_id FROM jieqi_article WHERE lastupdate>".(time()-86400)." ORDER BY lastupdate DESC LIMIT ".$array['num'];
return $this->db->getAll($sql);
}
模板里调用改成{books num=10},如果模板里用{$volume.volume_name}不生效,检查是不是数组键名是volume_name还是vd_name——杰奇老版本经常改键名,用var_dump($this->tpl->get_vars())调试,别猜。
移动端适配稀烂,字体太小,点击区域不对,想改成自适应
杰奇CMS默认的移动端模板是/templates/mobile/,但很多皮肤没做响应式,直接放弃旧模板,在/reader.php里加一段UA判断:
if (preg_match('/Mobile|Android|iPhone/', $_SERVER['HTTP_USER_AGENT'])) {
$GLOBALS['jieqiModules']['reader']['page_template'] = 'mobile_new';
}
然后新建/templates/mobile_new/chapter.html,用Bootstrap v5或纯Flex布局,关键CSS:body{font-size:16px; padding:10px; },按钮最小高度44px,强制禁用缩放:<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">,Ajax加载上一章/下一章时,用fetch代替XMLHttpRequest,并监听scroll事件做预加载。
缓存配置混乱,Redis和Memcached同时开着,内存爆了
先停掉一个,在/cache/config.php里统一改成Redis:
return array(
'cache_type' => 'redis',
'redis_params' => array(
'host' => '127.0.0.1',
'port' => 6379,
'timeout' => 1.5,
'prefix' => 'jc_',
'database' => 0,
),
);
然后在/includes/cache_func.php里,把get_cache和set_cache函数全部改为redis->get和redis->setex,注意,杰奇CMS有些缓存是用的文件缓存,比如/var/cache/tpl_cache/,把模板编译缓存改到/dev/shm(内存盘),在/config.php里设置$jieqiCache['dir'] = '/dev/shm/jc_tpl/',重启php-fpm,内存占用瞬间降一半。
数据库定期维护,备份文件1TB,导出要40分钟,恢复要1小时
别再mysqldump了,直接用pt-archive工具做在线归档,或者用mysqldump --single-transaction --quick --skip-lock-tables导出,但更重要是分区,每周日凌晨3点执行:
mysql -e "ALTER TABLE chapter_2021 REBUILD PARTITION;" mysqlcheck -o jieqi_chapter -a -m
备份策略改成xtrabackup --backup --stream=xbstream | pigz > backup.qp,恢复时才需要解压,删除5年以上的纯文本章节数据,只保留ID和摘要,真有人想看老书,后台单独跑历史归档脚本导入。
迁移到其他CMS的补丁
如果这些优化还是救不回来,那就换个CMS,别用帝国,帝国那模板机制更坑,用WordPress + LMBlog的书籍插件,或者IPython + Django + DRF重写接口。
数据迁移核心:只导book_info和chapter_content两张表,用INSERT INTO new_chapter SELECT * FROM old_chapter WHERE chapter_id > 0,注意把杰奇里的NEW/OLD字段改成新CMS的draft/published状态,模板完全扔掉,因为杰奇的模板输出是纯HTML拼接,新CMS用Vue或React做SPA,API对接时把杰奇的chapter_content里的内置空格和\r\n全部替换成<br>。
别留恋,写代码的手,永远要比背锅的肩硬。



发表评论