技术探索与实践:一个老后端的代码人生碎碎念
上周五晚上十点半,办公室只剩我和隔壁工位的运维小哥。耳机里放着周杰伦的《稻香》,眼前是刚上线的 AI 推荐服务在 Prometheus 里疯狂飙红的 CPU 曲线。我一边敲着 kubectl logs -f,一边默默点开外卖软件——这已经是我入职新公司两个月以来第三次深夜排查线上问题了。
没错,我是那个在京东干了五年后端的老兵,经历过无数个 618 和双 11 的流量洪峰洗礼,自以为见过大风大浪。结果跳槽到这家创业型公司才两个月,就发现自己像个刚毕业的实习生一样手忙脚乱。特别是最近被领导“温柔”地安排去搞 AI 相关的技术栈,每天都在怀疑人生:“我是不是该回老家卖红薯?”
但吐槽归吐槽,作为一个靠代码吃饭的人,总得把活儿干完。今天这篇文章,就是想和大家聊聊我在最近这次技术探索中踩过的坑、悟出的道理,以及那些让我半夜惊醒又豁然开朗的“最佳实践”。不灌鸡汤,只讲干货,顺便夹带点程序员的牢骚和自嘲。
起因:AI 不是魔法,但产品经理觉得它是
事情要从上个月说起。产品总监在周会上轻描淡写地说:“咱们能不能加个‘智能推荐’功能?用户看了 A 商品,就给他推 B,就像淘宝那样。”
我说:“行啊,但得先定指标、埋点、训练模型、部署推理服务……至少两个月。”
他眨眨眼:“能不能下周上线?MVP 版就行。”
我当时差点把咖啡喷出来。MVP?你当 AI 是 CRUD 啊?
但现实是,老板要,就得上。于是我硬着头皮接下了这个任务,开始从零搭建一个轻量级的推荐系统后端。目标很明确:用最小成本跑通端到端流程,支撑业务快速验证想法。
这就引出了我今天想分享的第一个核心理念:
技术探索的本质,不是追求最酷最前沿,而是找到“足够好+可迭代”的平衡点。
技术选型:别一上来就上 K8s + Ray + Triton
很多新人(包括曾经的我)一听到 AI,立刻想到的是大模型、GPU 集群、分布式训练。但在这个场景下,我们根本不需要那么重。
我们的业务数据量其实不大——日活用户不到十万,商品库也就几万 SKU。用户行为日志每天也就几个 GB。用不上动辄几十卡的训练集群。
所以我做了如下决策:
| 组件 | 初期方案 | 理由 |
|---|---|---|
| 特征工程 | Pandas + Scikit-learn | 快速验证特征有效性,无需复杂 pipeline |
| 模型 | LightFM(混合协同过滤) | 支持 user/item 特征,训练快,内存友好 |
| 推理服务 | Flask + Gunicorn | 轻量、熟悉、5 分钟能跑起来 |
| 部署 | Docker + 公有云 ECS | 团队没专职 SRE,K8s 上手成本太高 |
是的,你没看错,我用了 Flask。在 2024 年,一个五年经验的后端工程师,居然用 Flask 写 AI 服务。要是让前司的架构师看到,怕是要连夜把我拉黑。
但事实证明,这个“土法炼钢”策略非常有效。三天时间,我就跑通了从日志解析 → 特征构建 → 模型训练 → API 推理的完整链路。虽然性能一般(QPS 大概 80),但足够支撑 A/B 测试了。
而且,因为代码简单,测试同学都能看懂逻辑,提 Bug 时直接说:“你第 42 行那个相似度阈值是不是设太高了?” —— 这种协作效率,在微服务地狱里简直不敢想。
踩坑实录:那些让我想砸电脑的瞬间
当然,过程绝不是一帆风顺。下面这几个坑,我替你们踩过了,记得绕道。
坑 1:模型版本和代码版本对不上
第一次上线后,发现线上推荐结果和本地完全不一样。查了一晚上,才发现是模型文件用错了——本地训练完没 push 到 Git LFS,CI/CD 脚本拉了个空模型。
教训:模型也是代码的一部分!必须纳入版本管理。
后来我改成了这样:
# 训练脚本末尾自动打 tag
git add model.pkl
git commit -m "feat: update model v$(date +%Y%m%d)"
git push origin main
同时在服务启动时校验模型 hash:
import hashlib
def load_model(path):
with open(path, 'rb') as f:
model = pickle.load(f)
f.seek(0)
file_hash = hashlib.md5(f.read()).hexdigest()
# 打印 hash 便于排查
logger.info(f"Loaded model with hash: {file_hash}")
return model
坑 2:冷启动问题被忽视
新用户进来,没有任何行为记录,模型直接返回空列表。产品一看:“怎么新用户看不到推荐?是不是挂了?”
其实不是挂了,是没数据。但我忘了提前和产品沟通“冷启动策略”。
解决方案:兜底策略必须有!
def recommend(user_id):
if not has_behavior(userid):
# 返回热门商品(缓存 5 分钟)
return get_hot_items()
# 正常走模型
return model.predict(user_id)
而且这个“热门商品”列表,我们用 Redis Sorted Set 实现,每天凌晨用 Spark 跑一次 Top 100,既准又快。
坑 3:日志打得太少,排查靠猜
上线第一天,监控显示 5% 的请求超时。但日志里只有 “Request processed”,连 user_id 都没打。
我只好临时加日志重新部署,结果又引发了一次滚动更新抖动……运维小哥看我的眼神都变了。
现在我的日志规范是:
logger.info(
"recommend_request",
extra={
"user_id": user_id,
"item_count": len(items),
"model_version": MODEL_VERSION,
"latency_ms": time.time() - start,
"fallback_used": fallback_used
}
)
配合 ELK,任何异常都能秒级定位。
性能优化:从 80 QPS 到 1500 QPS 的野路子
初期 Flask 服务确实扛不住。压测到 100 并发就开始丢请求。但我不想立刻上 gRPC 或者换 Go,毕竟团队都是 Python 老兵。
于是开始“抠细节”:
模型加载只做一次
把model = load_model()放到全局,而不是每个请求都加载。省下 200ms。用 joblib 替代 pickle
from joblib import dump, load # 序列化速度提升 3 倍,内存占用减少 40%引入缓存层
对高频用户(比如运营号、爬虫)的结果做 1 分钟缓存:@lru_cache(maxsize=10000) def cached_recommend(user_id, timestamp_minute): return _real_recommend(user_id)异步化非关键路径
比如打点上报、ABTest 分流,全部扔进线程池:from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(max_workers=2) def log_async(event): executor.submit(_send_to_kafka, event)
优化后,单机(4C8G)QPS 从 80 提升到 1500,P99 延迟 < 80ms。产品终于闭嘴了。
工程化思维:代码人生不只是写函数
在京东那几年,我最大的收获不是技术,而是工程化思维。什么叫工程化?就是:
- 可观测性 > 功能完整性
- 可回滚 > 快速上线
- 文档即代码 > 口头约定
所以在新项目里,我坚持了几件事:
✅ 所有接口都有 OpenAPI 文档(用 FastAPI 自动生成)
✅ 每次部署必须带 changelog 和回滚脚本
✅ 关键路径必须有单元测试(哪怕只有 30% 覆盖率)
✅ 所有配置走环境变量,禁止 hardcode
举个例子,我们的 ABTest 配置:
# abtest.yaml
experiments:
- name: "rec_v2"
traffic: 10% # 逐步放量
enabled: true
rules:
- field: "user.country"
value: "CN"
服务启动时自动加载,支持热更新。再也不用求运维改 Nginx 配置了。
最佳实践总结:给后端同行的几句真心话
经过这两个月的折腾,我对“技术探索”有了新的理解。分享几点心得:
1. 先跑通,再优化
别一上来就设计“完美架构”。MVP 的核心是验证假设,不是炫技。能跑就行,跑不动再改。
2. 技术债要主动管理
我知道用 Flask 不够“高大上”,但我在 README 里明确写了:“待 QPS > 2000 时迁移到 FastAPI + ASGI”。这就是技术债的透明化。
3. 和业务对齐语言
不要和产品说 “embedding dimension”,要说 “推荐准确率”。他们关心的是结果,不是过程。
4. 保护自己的精力
我给自己定了规矩:晚上 9 点后不处理非 P0 问题。代码人生很长,别 burnout 在第一个月。
5. 保持学习,但别焦虑
AI 很火,但后端的基本功(网络、存储、并发)永远不过时。我现在学 PyTorch,不是为了转算法,而是为了更好地和算法同学沟通,写出更高效的推理服务。
结语:代码人生,是一场马拉松
写这篇文章的时候,窗外天刚亮。昨晚的线上问题终于定位到是 Redis 连接池泄漏,修复后一切恢复正常。
回想这五年,从京东大促的通宵值守,到现在创业公司的灵活试错,我越来越觉得:所谓“最佳实践”,不是教科书上的金科玉律,而是在具体约束下做出的最优权衡。
技术会变,框架会过时,但解决问题的思路、对系统的敬畏、对协作的尊重,这些才是代码人生的底层逻辑。
最后送大家一句我工牌背面的话(前司文化):“Stay humble, stay hungry.”
共勉。
P.S. 如果你也正在被 AI 项目折磨,欢迎留言交流。或者,一起听周杰伦写代码?🎧

评论 0