新公司开工的第二天,我比前一天来得还早。
不是我突然热爱上班了,主要是这个 AI 音乐项目现在给我的压迫感,已经不是闹钟能不能叫醒我的问题了,而是我人还没到公司,脑子里的线程池就已经先启动了。
早上八点多的高新园,楼下卖早餐的、拿着咖啡赶路的、背着电脑包冲电梯的,大家看着都很体面。只有我知道,我这副表面平静的样子,其实跟刚上生产的服务差不多——看起来活着,实际上全靠硬撑。
我刷卡进办公室的时候,工位区还没几个人。
灯刚开,空调风有点凉,前排几个空工位安安静静摆在那里,看着跟还没初始化的节点一样,摆设是齐的,就是没人。尤其是我周围这一圈,越看越空,空得我都快怀疑老板是不是想先靠我一个人把后端跑通,再决定要不要给这个项目补副本。
我把电脑一开,昨天新建的那几个文档还躺在桌面上:
《后端架构草案》
《数据库设计v1》
《任务状态流转说明》
《模型调用链路梳理》
《待确认问题清单》
这些文件名一字排开,看着像挺像回事,实际上跟样板房差不多,外面看着完整,里面还没通水通电。
我先给自己接了杯热水,然后盯着白板,把整个 AI 音乐项目的后端链路又过了一遍。
用户提交生成请求。
后端记录任务。
任务入队。
调用模型。
拿结果。
落库。
存文件。
前端查询状态。
按理说,逻辑也不算多复杂。可项目这东西,最怕的不是“看起来难”,而是“看起来能做,实际一落地全是坑”。这玩意儿就像产品在会上说一句“我们先做个 MVP 吧”,听起来轻飘飘,落到后端身上就是:兄弟,你先一个人把地基、管道、电路、消防、门禁都给我补齐。
我本来计划得挺好,今天先把服务拆分思路定下来。
认证鉴权先复用公司现有那套,任务服务单独拎出来,歌曲生成链路独立,文件存储先简单走 OSS,后面再看要不要做中台能力沉淀。至于消息通知、用户资源扣减、失败补偿这些东西,先别想太大,能跑起来再说。
结果 IDE 一打开,我就发现自己还是太乐观了。
先是 CI/CD 这块,几乎等于没搭明白。
代码仓库是有,流水线也不是完全没有,但你真要说它能支撑一个新项目丝滑发布,那属实有点抬举它了。环境配置东一块西一块,测试环境参数还得手动改,脚本倒是写了几个,可看着像前朝遗留下来的文物,能不能跑全靠缘分。
我盯着那几份配置,心里只有一个想法:
这哪是 CI/CD,这更像“Copy / Import / Crash / Debug”。
然后是数据库。
我原本以为最差也就是表没建全,结果一看,迁移规范也不统一,索引策略还停留在“先建出来再说”的阶段。个别历史库表命名风格也是五花八门,有种不同朝代开发者在同一片土地上轮流执政的美感。你很难说它不工作,但你也很难说它看着像一个正常人能维护的系统。
更别提模型接口那边了。
这才是真正的祖宗。
文档里写得很好,什么“支持多风格音乐生成”“支持异步回调”“接口响应稳定”。结果我拿测试参数一调,第一次 500,第二次超时,第三次返回了个格式诡异的成功响应,字段名长得像随手起的,状态值更是抽象得像产品经理的情绪。
我盯着屏幕,沉默了两秒。
那种感觉就像你满怀期待去联调一个号称已经开发完成的接口,结果对面给你返回一个“你猜”。
我只好开始一点点打日志。
请求参数。
响应体。
超时重试。
异常捕获。
状态转换。
不夸张地说,我那一上午的主要工作,不是在开发,而是在跟各种不稳定因素互相试探。像极了刚谈恋爱那会儿,你发一句“在吗”,对面时而秒回,时而失踪,时而发个表情包让你根本判断不了她到底什么状态。只不过这次跟我玩灰度发布的不是小璇,是模型接口。
十点多的时候,我终于把一个任务创建接口勉强打通了。
前端先不管,至少我本地能提交参数、生成任务记录、返回一个任务 ID。那一刻我看着终端里那串成功响应,心里还真小小激动了一下。说起来也挺惨,我现在的快乐阈值已经低到这种程度了——接口正常返回个 200,我都觉得像心跳包终于收到了回应。
结果这种好心情只持续了不到二十分钟。
因为我紧接着去测任务查询接口的时候,缓存没命中,数据库连接又卡了一下,返回直接 500。
我盯着那片红色报错信息,感觉自己太阳穴都跟着跳了一下。
真的,有时候当后端久了,你会发现生活里很多破防瞬间,都没有终端上一片红字来得直接。那玩意儿一出来,比谁跟你吵架都管用。因为吵架你还能嘴硬两句,接口一炸,你连装镇定的资格都没有。
我靠在椅子上,打开微信,给小璇发了条消息:
“接口又炸了,我都想把自己也重启了。”
消息发过去没多久,她回得还挺快:
“别慌,先看日志。你这情况像极了凌晨三点猫踩键盘,不一定是系统的问题,也可能是你哪行代码抽风了。”
我看着手机笑了一下。
这就是小璇说话一贯的风格,不是那种“辛苦啦抱抱你”的安慰路线,她更像是一个高质量 code review,同情不给太多,但每句话都能把人从情绪里往回拽一点。
我回她:
“现在的问题是,代码抽风、接口抽风、环境也抽风。我一个人坐这儿像在看三个服务同时闹脾气。”
她又回:
“那你先别跟着一起崩。服务能重启,你崩了没人给你拉起来。”
这话看着不肉麻,效果倒挺好。
至少我那点快被 500 打散的心态,算是被她这一句给热修回来了点。
我重新坐直,把日志从头拉了一遍,发现问题还真不是缓存本身,而是任务状态回写的时候,事务边界没收住,导致刚写进去的数据查询接口一时拿不到。说白了,不是什么惊天大 bug,但非常恶心,属于那种你单独看每个模块都像没毛病,连起来就开始作妖的分布式小脾气。
我一边改,一边在心里骂自己。
刚来第二天就把自己整得像线上事故责任人,属实有点给这个“AI 项目组长”的 title 丢人。
但换个角度想,这也算正常。新项目搭架子,本来就不可能一把过。谁要是跟你说后端从 0 到 1 的过程很丝滑,那他要么没干过,要么就是负责讲 PPT 的。
午饭我都没怎么认真吃。
食堂里人不少,大家边吃边聊,别的组在聊活动方案、版本排期、谁谁谁昨晚又没回消息。我端着盘子坐在角落里,一边扒饭一边想服务拆分和表结构,脑子里那几条线程根本没停。别人吃饭是休息,我吃饭像 CPU 降频运行,表面上是暂停了,实际上后台任务一个没少。
吃到一半,小璇又给我发了条微信:
“活着没?”
我回:“还活着,就是单线程扛全局,CPU 温度有点高。”
她发了个猫瘫在桌上的表情,然后补了一句:
“先把主流程跑通,别一上来就想一步到位。你现在不是做架构艺术品,是先救活服务。”
我看着这句话,突然觉得她比我还懂我现在这个状态。
程序员最容易犯的一个病,就是项目刚开,脑子里已经把未来三年的扩展性都想完了,恨不得今天把消息队列、分布式事务、服务治理、统一监控全给补上。理想当然很丰满,可现实是你现在连第一条接口都还没稳定返回,谈那些东西,多少有点像人在城中村单间里租着床位,就已经开始规划别墅装修风格。
所以我下午干脆把节奏改了。
不再一口气想把全链路做美,而是老老实实按优先级收敛:
第一,任务创建和状态查询必须先稳。
第二,模型调用哪怕先丑一点,也要先打通。
第三,缓存策略先保守,别上来就把自己绕进去。
第四,事务边界、失败重试、日志埋点,先把关键节点兜住。
第五,把所有不稳定点记清楚,后面招人、补资源、做优化,至少有东西可讲。
这么一拆,我心里反而没那么堵了。
很多时候,压力不是事情本身大,而是你把十件事同时塞进脑子里,它们在里面像十个没加锁的线程一起抢资源,谁都想先执行,最后把你整个人卡死。
下午三点多,我终于把任务查询这块修顺了。
再测一遍。
创建任务成功。
查询任务成功。
状态流转正常。
虽然模型调用那块依旧偶发抽风,但至少主链路已经不是一碰就 500 了。
我看着 IDE 里那一串正常日志,忽然长长松了口气。
那种感觉有点像什么呢?
像你连续发了很多条消息,对方一直没回,你表面装得无所谓,心里已经开始脑补最坏情况了,结果半小时后手机一震,对面回了句:“刚在忙。”
就这么一句,能把你前面所有乱七八糟的线程瞬间释放掉。
当然,我也没敢高兴太早。
因为我太清楚了,新项目前期,今天能跑通,不代表明天不会炸;这会儿状态正常,不代表晚上换一组参数不会当场翻车。所谓“接口稳定”,很多时候只是“今天恰好没出事”这几个字的委婉说法。
但不管怎么说,我总算不是原地踏步了。
临下班前,我把今天踩过的坑全整理进了文档里:
- CI/CD 流水线不完善,环境切换成本高
- 模型接口返回不稳定,需增加超时重试和兜底策略
- 数据库迁移规范缺失,表结构和索引需统一梳理
- 缓存策略待补,先只保核心查询
- 事务边界已发现问题,后续需补状态一致性校验
- 日志埋点需要统一,不然后面排查全靠猜
- 团队扩张需求:后端、测试、运维支持都得提上日程
写到“团队扩张需求”那一行的时候,我手停了一下。
说真的,一个人单刷项目,短期会有种很爽的错觉。你会觉得所有东西都在自己掌控里,架构我定,接口我拍,数据库我拆,怎么搞都不用跟一堆人来回拉扯。
但这种爽,是有代价的。
因为掌控感的另一面,就是单点故障。
项目跑得起来,是你的功劳。
项目哪天炸了,第一个被拎出来看日志的,也是你。
这感觉很像单机部署。快是快,简单也是真简单,但只要你这台机器出问题,整个服务就跟着一起趴。
我关掉几个窗口,办公室这时候已经安静了不少。有人在收拾包,有人在讨论吃什么,有人已经下楼打车了。只有我还坐在工位上,看着 IDE 里最后一版日志发呆。
窗外高新园的天色慢慢暗下来,玻璃上反着电脑屏幕的光。
我忽然觉得自己这一整天,过得特别像一个被强行拉满负载的线程。
没法并发。
没人分担。
不能阻塞太久。
更不敢直接死掉。
因为我这条线程一挂,后面一串任务都得跟着 pending。
我靠在椅子上,低声跟自己说了一句:
“单线程也得撑住,项目才可能跑通。”
说完我自己都笑了。
这话听着挺惨,甚至有点像打工人版自我洗脑。
可没办法,现阶段现实就是这样。这个 AI 项目的后端,现在本质上就是我这一条线程在那儿硬顶着。顶得住,系统继续往前走;顶不住,大家就一起看着日志怀疑人生。
我收拾好电脑包,起身关屏幕的时候,微信又震了一下。
小璇发来一句:
“今天怎么样,服务还活着吗?”
我回她:
“活着,虽然只是单节点存活,但至少没全盘宕机。”
她发来一个“OK”的表情,又补了一句:
“那就行。别想着今晚把世界都修好,先把你自己下线休息。”
我看着那句话,心里忽然松了点。
至少在这座城市里,在这堆接口、文档、日志和需求之外,还有个人能在我快被系统整麻的时候,给我发一句像样的心跳包。
电梯门合上的时候,我脑子里还在想明天要补的事:模型调用重试、任务失败状态、数据库索引、环境脚本、资源申请……
任务很多。
坑也很多。
后面大概率还会继续炸。
但至少今天,我已经把这个项目从“纯靠想象”往前推了一小步。
对于一个只有单线程模式的后端来说,这已经算是不错的启动了。
只是我也知道,真正难的还不是今天这种本地调通。
真正难的,是后面它开始接更多需求、更多人、更多变化的时候,我到底还能不能一直扛住这条主线程不死。
毕竟项目这东西,最怕的不是报错。
最怕的是——
你还没来得及把系统搭起来,自己先被跑崩了。