最近给自己的影视站做了一次小维护:应用版本升级、数据保全、首页点击卡顿排查,以及一点点前端体验优化。
事情不大,但过程很典型,属于那种看起来“点一下卡住”的问题,背后其实混着部署、缓存、反代、前端 hydration 和交互遮罩。
确认状态
根据我有限的维护经验,这种破站最怕“顺手一重启”,所以第一步不是更新,而是盘点现状
所以先要观察服务器的如下数据:
- 当前有哪些容器在跑
- 哪个容器才是真正对外服务
- Nginx 反代指向哪个本地端口
- 数据是存在容器里,还是通过卷挂载到宿主机
- Redis 是否作为实际存储
- 当前版本是多少
结果发现机器上有两个相似实例,但真正被 Nginx 对外代理的是其中一个。
(主要是之前偷懒没有删除那个废弃的实例)
这个细节很关键,如果只看镜像名或目录名,很容易更新错实例。
确认之后,目标实例的结构大致是:
- 应用容器负责 Web 服务
- Redis 容器负责数据存储
- Redis 数据通过宿主机目录持久化
- Nginx 只代理到应用容器暴露的本地端口
我只能重建应用容器,不动 Redis,不动 Nginx,也不能动其他服务。
备份数据
升级前做了两层保护。
第一层是让 Redis 主动落盘,确保内存里的数据写进持久化文件。
第二层是备份配置和数据目录,包括:
- Compose 配置
- 应用容器 inspect 信息
- Redis 容器 inspect 信息
- Redis 数据目录
- 更新前的容器列表
固定版本
原来我的镜像使用的是 latest。这很方便,但也有一个缺点:下一次重建时,到底跑的是哪个版本并不明显
这次把镜像固定到了目标版本。这样之后看 Compose 文件就能知道线上正在跑什么,也避免未来不小心拉到未知版本。
所以更新动作保持很小:
- 拉取目标版本镜像
- 只重建应用容器
- Redis 容器保持运行
- Nginx 配置不改
重建后通过本地接口验证版本号,确认已经升级成功。再看容器状态、端口映射和日志,确认服务仍然按原来的方式对外。
真正debug卡顿的原因
升级之后发现还是存在左键点击首页上的链接会卡一下,但右键新标签打开同一个链接却很快的现象
这种现象通常说明服务端不慢。因为新标签是一次完整页面请求,如果它很快,说明 Nginx、应用接口和页面 HTML 响应大概率没问题。卡顿更可能发生在当前页面的客户端逻辑里。
实际测下来也是这样:
- 页面服务端响应很快
- 常用接口响应很快
- 静态资源缓存头正常
- Nginx 转发不是瓶颈
经过排查,发现问题有两个。
一、首页公告弹窗。
首页有一个全屏提示遮罩,用户没点“我知道了”之前,它会盖住整个页面。看起来你是在点导航链接,实际上点到的是遮罩。右键新标签打开则绕过了这个交互路径,所以显得更快。
二、首页 Hero Banner。
Hero Banner 会加载预告片,并触发视频代理请求。这个模块本身视觉效果更丰富,但它也会带来额外的前端工作和网络请求。一旦视频资源不可用或者代理超时,就会让首页变得更吵,也更容易放大点击时的卡顿体感。
优化方式:少改代码,优先改配置
我没有直接进容器改源码,而是优先走后台配置。
处理了两项:
- 清空首页公告内容,让全屏遮罩不再挡住导航
- 关闭 Hero Banner 轮播,保留其他首页模块
这两个改动都属于低风险配置变更,不涉及数据结构,也不需要改应用代码。
处理后重新打开首页,导航链接不再被遮罩盖住。左键点击可以正常进入目标页面。
顺手处理一个 hydration 隐患
排查时还看到一个 React hydration 文本不一致的错误。结合页面内容看,比较可疑的是首页问候语这类基于时间的文本。
服务端渲染时用一个时区,浏览器端用另一个时区,就可能出现服务端生成“下午好”,浏览器接管时变成“晚上好”。这种文本不一致不一定导致页面崩,但会影响客户端接管质量,严重时会让交互变得不稳定。
所以顺手给应用容器加了时区环境变量,让应用侧尽量和实际使用时区一致。这个改动同样只重建应用容器,不动 Redis 数据。
这次维护的几个经验
一、先确认真实入口。
同一台机器上可能有多个相似目录、多个相似容器。真正对外的是哪个,要以反代配置和端口映射为准。
二、数据容器不要跟着应用一起乱动。
只要架构允许,升级应用时尽量不重建数据库或缓存存储容器。尤其是 Redis 这种承担实际数据存储的服务,先落盘再备份。
三、latest 适合试验,不适合长期维护。
固定版本能让问题更可追踪,也方便之后回滚。
四、左键慢、右键快,多半不是后端慢。
右键新标签快,说明完整页面加载没问题。左键慢通常要看当前页面的客户端路由、遮罩、事件处理、未完成请求和前端错误。
五、配置能解决的,不急着改源码。
这次最有效的优化不是写代码,而是清掉会挡住点击的公告遮罩,再关掉首页最重的轮播模块。
最后
总结:一定先看清楚,再备份,再只动必要部分,最后用页面、接口、日志和浏览器行为一起验证。
运维很多时候就是这样。真正省心的不是命令多熟,而是知道哪些东西不要碰。