别让正则拖垮服务:识别 ReDoS 与输入防线

正则表达式的安全审查

正则表达式很适合做格式校验和文本提取,却也可能把一次普通请求放大成数秒甚至更久的 CPU 计算。问题通常不在“用了正则”,而在回溯型引擎遇到含糊模式和恶意输入时,必须反复尝试大量失败路径。这类正则拒绝服务(ReDoS)值得像数据库查询一样被审查和限额。

Read More

把 SSE 接稳:断线续传、心跳与代理缓冲

稳定的 SSE 事件流

订单状态、构建日志和后台任务进度这类信息,往往只需要服务端持续推给页面。Server-Sent Events(SSE)比双向协议更轻:一个普通 HTTP 响应保持打开,浏览器的 EventSource 会在连接中断后尝试重连。但“能收到消息”不等于“稳定送达”。代理缓冲、空闲超时和重连窗口里的事件缺口,都会让页面看起来偶发失效。

Read More

别让 API 静默覆盖:用 ETag 与 If-Match 实现乐观并发控制

ETag 与条件更新保护 API 资源

两位用户同时编辑同一份资料,是后台系统里非常常见的场景。若接口只接受一个普通的 PUTPATCH,后提交的请求会悄悄覆盖先提交的修改:两次都返回 200,数据却已经丢失。数据库事务能保护单条 SQL 的原子性,却不会替 HTTP 客户端判断“我编辑的还是不是刚才看到的版本”。

Read More

前端卡顿别靠感觉:用 PerformanceObserver 定位浏览器长任务

浏览器长任务阻塞主线程

页面已经打开,接口也很快,但点击筛选、展开弹窗或输入搜索词时仍会“顿一下”。这类问题经常不在服务端,而是某段同步 JavaScript 长时间占住了浏览器主线程:输入无法处理,样式和布局不能提交,下一帧也画不出来。与其凭感觉删代码,不如先记录长任务发生的时间、持续时间和业务动作,再做有证据的优化。

Read More

软删除不是加个 deleted_at:把可恢复数据的生命周期做完整

软删除数据生命周期示意图

业务常把“删除”理解为暂时不让用户看见,于是给表加上 deleted_at 就上线。几个月后,重复注册被唯一索引拦住、后台统计混入已删除数据、关联记录变成孤儿,恢复操作又覆盖了新数据。软删除不是一个字段,而是一套从可见性、约束到最终清理的生命周期协议。

Read More

ORM 查询别悄悄放大:识别 N+1、批量加载与回归验证

用批量加载收拢查询路径

列表接口在测试数据上很快,上线后却随着分页条数变大而变慢,常见原因不是少了索引,而是 ORM 在循环里偷偷访问关联对象:先查一页主记录,再为每条记录各发一次查询。这类 N+1 问题的危险在于单条 SQL 很快,却会放大网络往返、连接占用和数据库解析成本。治理它的重点不是“多写一个 include”,而是让一次请求的查询数量可见、可预测、可回归。

Read More