当前位置:首页 > 焦点

web项目总结

上线第三天,目总支付回调接口挂了。目总凌晨两点,目总我被运维的目总电话叫醒,打开电脑一看,目总日志里全是目总重复的回调请求。第三方支付平台在五分钟内推了四百多条相同通知,目总我们的目总系统照单全收,数据库里瞬间多出两百多笔重复订单。目总这不是目总什么高深的技术难题,就是目总没做幂等。

项目从立项到上线,目总一共四十七天。目总三个人,目总我负责后端,目总老张管前端,小陈做测试兼产品助理。需求文档只有六页,其中两页还是我后来补的接口说明。老板的原话是“先跑起来,有问题再改”。这话听着不靠谱,但很多小项目就是这么起步的。真按大厂那套流程走,光评审就能耗掉两周。

技术选型没怎么纠结。Spring Boot加MySQL,前端Vue3配Element Plus,部署在一台4核8G的云服务器上。有人建议上微服务,我直接否了。日活预估不到两千的项目,拆成五六个服务纯属自找麻烦。后来证明这个判断是对的——隔壁组同期做的项目拆了七个服务,光联调就花了三周,上线后还因为服务间超时问题频繁报警。

真正花时间的不是写代码,是理清业务逻辑。客户那边对接的人换了三茬,每换一次,需求就微调一点。最开始说订单要支持部分退款,后来改成只支持全额退,再后来又说要加一个“退款审核”状态。每次变更都不大,但数据库表结构改了四次,每次都得写迁移脚本。我养成了一个习惯:任何字段变更先写SQL备份原表,再执行ALTER。这个习惯救了我一次——有回改字段类型时忘了加默认值,导致历史数据全部变成NULL,靠备份表十分钟就恢复了。

接口设计上踩过一个坑。列表查询一开始用的是GET传数组参数,类似?status=1&status=2。本地测试没问题,上了Nginx之后发现只收到最后一个值。查了半天,是Nginx对重复参数的处理方式和Tomcat不一样。后来改成用逗号分隔的字符串,前端拼好再传,省事。这种细节没人会提前告诉你,只有被坑过才知道。

性能方面,上线第一周数据库CPU飙到90%。慢查询日志里全是订单表的联合查询,索引建了但没走对。用EXPLAIN一看,发现查询条件里有个DATE(create_time) = '2024-01-01',函数作用在索引列上导致全表扫描。改成范围查询后,CPU直接降到15%。这事让我重新翻了一遍《高性能MySQL》的索引章节,比看十篇博客管用。

前端那边也不省心。老张用Webpack打包,vendor.js出来1.8M。首屏加载在4G网络下要六秒多。后来换了Vite,按需引入Element Plus组件,又开了gzip压缩,降到420K。没做代码分割之前,用户点任何页面都要等整个包下载完。改完之后,首屏1.2秒。老张说这辈子的优化指标一次用完了。

项目上线两个月,日活稳定在一千三左右。没出过大故障,小问题修了十几个。回头看,最大的教训是接口文档写得太晚。前端联调时经常因为字段类型对不上来回改,一个createTime是字符串还是时间戳,来回折腾了三次。如果一开始就用Swagger把接口定义清楚,至少能省出三天时间。

另一个感受是:别迷信“最佳实践”。什么分库分表、消息队列、Redis缓存,在这个量级下全是过度设计。我们连Redis都没用,查询直接走MySQL,QPS峰值也就一百多,稳稳当当。技术选型要看数据说话,不是看招聘要求上写了什么。

代码review我们做得比较随意,主要靠IDE的静态检查插件顶着。但有个规矩:任何涉及金额的计算必须写单元测试。这条执行得不错,支付相关的测试覆盖率到了85%。事实证明有用——有次改退款逻辑,测试直接报出精度丢失的问题,0.1 + 0.2那种经典坑。

项目还在跑,后续可能要加积分和优惠券。到时候再说吧。先把眼下这版稳住,比什么都强。

分享到: