网站访问速度慢得让人想砸键盘
杰奇CMS二次开发实录,从龟速站点到秒开响应的七场硬仗
我盯着后台的“运行时间”报表,CPU峰值飙到98%,MySQL查询队列堵成早高峰,新手站长总以为加带宽就能解决,但真正的问题在代码层,打开/config/config.php,先把$_SC['dbpconnect']从1改成0——持久连接在并发高时反而锁死表,再检查模板里有没有滥用{eval}标签,尤其是循环里套SQL查询的写法,十有八九是它拖垮了数据库。
直接改/lib/init.php,把define('DB_PCONNECT', 1)注释掉,加上:
define('DB_PCONNECT', 0);
define('DB_DEBUG', 0);
然后开启MySQL慢查询日志,定位那些SELECT * FROM jieqi_article_content WHERE articleid = xxx的无脑全表扫,给jieqi_article和jieqi_article_content加上联合索引:
ALTER TABLE jieqi_article ADD INDEX idx_articleid_sort (articleid, sortid); ALTER TABLE jieqi_article_content ADD INDEX idx_articleid_charpid (articleid, charpid);
章节表大得连备份都要半小时
《某本万章小说》的jieqi_article_content已经2.3GB,单表查询动不动卡死,别犹豫,按articleid哈希分表,我写了个迁移脚本,先建12张分表jieqi_content_0到jieqi_content_11,
$table = 'jieqi_content_' . ($articleid % 12); $sql = "SELECT * FROM $table WHERE charpid = $charpid";
在/lib/table/articlecontent.php里改getArticleContent方法的表名映射,同时把jieqi_article表里的lastupdate字段拿来当查询缓存依据,避免频繁跨表JOIN。
阅读页加载卡顿,滑动像PPT
问题出在每章正文一次性输出,3万字的章节DOM节点太多,我采用“分段懒加载”方案:把每章内容按2000字切成块,初始只渲染第一块,滚动到页面底部时通过Ajax请求下一块,在阅读页模板里加:
<div id="content-chunk-0" class="chunk">...</div> <button id="load-more" onclick="loadNextChunk()">加载剩余章节</button>
JS请求/api/readmore.php,返回JSON数据,然后append到容器,同时用IntersectionObserver触发预加载,配合服务端ob_start()加ob_gzhandler压缩输出。
模板标签想改,但官方文档像天书
我需要在书页显示“今日推荐”和“热评榜”,但现有{jieqi:booklist}标签不支持,直接打开/modules/article/templates/book.html,找到渲染函数,写个自定义块:
function smarty_block_daily_hot($params, $content, &$smarty) {
$sql = "SELECT a.articleid, a.articlename, b.chars
FROM jieqi_article a
JOIN (SELECT articleid, COUNT(*) AS chars FROM jieqi_article_content
WHERE lastupdate > UNIX_TIMESTAMP() - 86400 GROUP BY articleid) b
ON a.articleid = b.articleid
ORDER BY b.chars DESC LIMIT 5";
return $content . build_html_from_sql($sql);
}
然后在模板里{daily_hot}调用,最后用Smarty::registerPlugin('block', 'daily_hot', 'smarty_block_daily_hot')注册。
手机端打开乱成一锅粥
旧模板的固定宽度980px在iPhone上直接溢出,我重写了响应式布局,用viewport加媒体查询,核心是改/templates/default/style.css:
@media (max-width: 600px) {
.read-main { padding: 10px; }
.chapter-title { font-size: 18px; }
#content-area { font-size: 16px; line-height: 1.8; }
.pager a { padding: 8px 12px; }
}
并对阅读页的字体按钮做touch事件绑定,防止click300ms延迟,同时确保所有图片加载loading="lazy"。
缓存配置像摆设,Redis一开就报错
我得承认刚开始乱设缓存导致过白屏,正确做法是:在/config/config.php里启用Memcached,并指定key前缀:
$_SC['cache'] = 'memcache';
$_SC['cache_server'] = array('host'=>'127.0.0.1', 'port'=>11211);
$_SC['cache_prefix'] = 'jcms_' . md5($_SERVER['HTTP_HOST']);
然后在/lib/cache.php里改读写函数,对热门书籍列表setex设置600秒过期,但不要缓存用户登录态,把jieqi_rank表的数据每5分钟用cron脚本批量更新到缓存,避免每次用户请求都实时计算点击榜。
数据库三个月没清理,备份文件占满硬盘
我写了一个维护shell脚本,每周日执行:
mysql -u root -pjcms_db -e " DELETE FROM jieqi_online WHERE last_time < NOW() - INTERVAL 1 DAY; DELETE FROM jieqi_logs WHERE log_time < NOW() - INTERVAL 30 DAY; OPTIMIZE TABLE jieqi_article, jieqi_article_content, jieqi_comments; "
同时建议打开MySQL的event_scheduler,定时清理jieqi_lifetime表,注意备份策略:用mysqldump --single-transaction导出,但分表数据用--where="articleid%12=0"分开导出,压缩存储。
我习惯给所有二次开发点加上if (function_exists('hook_xxx'))的钩子函数,这样将来升级杰奇官方版本时,自己的代码不会因为文件覆盖而丢失,每一场优化都不是一次性的事,要持续看慢查询日志和访问日志,现在你的站点能扛住百万级PV了,但记住——代码永远是写给人看的,保持注释清晰,免得三个月后自己都不认识。



发表评论