之前 docker compose 安装好 PicHome 个人版 之后,在后台捣鼓了很久,尤其是那个发布很抽象,发布完也就是换一个地方显示,前台的页面上依然什么都没有。后面问了 deepseek 才知道要从「栏目管理」(站点导航设置)里添加,可以选择顶部导航或者底部导航,但正常都在顶部导航添加吧。添加完之后,页面顶部多了一个导航菜单,就是自己定义的名称。当然,这主要是我没有深度使用过吧,文档里介绍的 文件共享功能,可以有很多种方式去构建页面显示。

使用了几天发现一些小问题吧:

  • 几百兆的视频播放卡顿,无法播放;
  • 后台存储管理目前只支持腾讯云QCOS,而我是阿里云的;
  • 首页加载默认会很慢(一开始是十几秒,现在四秒多),看了就一个接口返回列表;
  • 个人版只支持一个人使用,没有办法添加其他用户。

前两条问题属于同一类型的,如果支持阿里云的对象存储,就可以买一个 CDN 加速服务解决。或者像正常的视频网站一样,对上传的视频进行切片再播放。看了大视频访问状态代码 206 Partial Content,进入详情页之后就一直在缓存,但几十 k 的速度杯水车薪。

最后一条也可以理解吧,毕竟要赚钱的,个人版自己一个人用用得了,影响不是很大。所以主要需要解决或者可能解决的问题,就是首页的加载优化了。

Pichome 有图片处理和媒体处理的功能,开启后就是给图片生成三种缩略图,给视频生成缩略图,实现在线预览(就是鼠标 hover 上去可以拉动看到一些视频截图)。但这不是一个接口加载很慢的理由,理解相关的数据应该是直接存在 mariadb 数据库了,直接获取接口应该是在毫秒级别的,而一些缩略图(几k)异步加载也不会影响到接口。

浏览器看了一下三个接口,一个是获取页面设置,导航之类的,一个是获取屏幕信息,就是导航下的筛选项。前两个返回都是毫秒级别的,最后一个是获取文件列表,获取 60 条数据,等待时间 3.9 秒。文件地址都完整给出来了,所以那个控制是否可以下载的权限感觉没什么用。

从返回数据来看,它是直接返回了所有字段了,但也不应该反应这么久。拿到链接 URL /index.php?mod=banner&op=app&do=filelist 给到 deepseek 分析一下,结果出现幻觉,之后给了一个指令获取包含参数的文件:

grep -rn "mod=banner" ./ --include="*.php"

将输出内容给它后,它分析是 /dzz/banner/bannerinterfcae.php 内,虽然没有找到 do=filelist 的部分。我看了一下 if-else 压根没有,同目录下倒是 list.php 比较符合要求。然后让它给我出方案,如何优化。结果它回复说读不到源代码,干脆把文件直接上传。

它给的建议都比较符合我的预期的,首先是解决 N+1 查询,就是常说的循环里面套查询;之后是优化 count 查询,一般是根据筛选条件去掉关联语句,或者缓存总记录数;还有降低每页返回数据量,添加索引,缓存热点数据...

在我提醒数据只有 63 条之后,给出了最简单的做法:缓存列表数据。结果就是它又产生幻觉了,给了一个看着很像,但执行不了语句:

$cached = C::t('cache')->get($cache_key);
C::t('cache')->set($cache_key, $return, 300);

之后我检查数据库发现是有 cache 这个数据表的,里面的数据结构 key 值 pichome_xxx 也符合对缓存表的预期。然后使用上面的 grep 指令查询使用方法,之后找到了这样的写法:

$cachetime = 3600;
$hotdatas = C::t('cache')->fetch_cachedata_by_cachename($cachename,$cachetime);

$setarr = ['cachekey' => $cachename, 'cachevalue' => serialize($hotdatas), 'dateline' => time()];
C::t('cache')->insert_cachedata_by_cachename($setarr,$cachetime,1);

替换上去,发现不生效。干脆 exit() 输出内容,还是没用。这让我怀疑是不是找错接口文件了,虽然输入输出参数之类的都比较符合预期。然后看着 mod=banner&op=app&do=filelist,这不就是 thinkphp 等框架显式带参的形式嘛!banner 是模块名,op 是文件名,那么 do 可以是方法名,也可以是文件中做的路由转发参数。当前 dzz/banner 目录符合模块,然后目录下还真找到了 app.php 文件...

找到对应位置,添加缓存语句,刷新页面两次,OK生效了!