浅谈技术探索与实践:一个带娃写代码的妈妈的碎碎念
今天早上8点整,我准时坐到电脑前——不是因为自律,而是因为娃刚被送去幼儿园,再不开工今天的KPI就要凉了。作为一名远程办公的全职妈妈+分布式系统方向的后端工程师,我的日常就是在“奶瓶”和“微服务”之间反复横跳。上周五晚上11点,我在哄睡失败、代码跑崩、线上告警连环炸的三重夹击下,终于顿悟了一件事:技术探索从来不是锦上添花,而是雪中送炭,尤其是在你连喝口水都要掐着时间的时候。
这篇文章,就当是我给同样在“带娃+coding”夹缝中求生的同行们一点微不足道的技术分享吧。
事情得从“那个要命的产品需求”说起
去年双11前一个月,产品团队突然甩过来一个需求文档,标题赫然写着:“支持千万级实时用户在线互动”。我盯着屏幕看了三秒,内心OS:“你们是打算让我用单机MySQL扛住整个抖音的流量吗?”
更离谱的是,产品经理小王还一脸天真地问我:“这个功能后天能上线吗?大促要用。”
我差点把咖啡喷到键盘上——后天?你知道光部署一套 Kafka 集群都得调三天配置吗?
但吐槽归吐槽,活儿还是得干。我们现有的架构还是基于传统的请求-响应模型,状态全靠数据库扛。面对这种高并发、低延迟、强状态的场景,显然不够看。于是,技术探索被迫提上日程——不是我想搞新花样,是真的快被线上事故逼疯了。
踩坑记:从“我觉得行”到“我真的不行”
一开始,我天真地以为引入 Redis + WebSocket 就能搞定。结果第一次压测,连接数一过5万,服务器直接 OOM。日志里全是:
java.lang.OutOfMemoryError: Unable to create new native thread
那一刻,我坐在凌晨两点的书房里,听着隔壁房间娃的翻身声,真的想砸电脑。
后来翻遍 Stack Overflow,才意识到问题出在线程模型上。每个 WebSocket 连接默认占用一个线程,这在高并发下就是资源黑洞。于是开始调研更轻量的通信方案,最终锁定了 Reactive Streams + Project Reactor 的组合。
但 Reactive 编程的学习曲线……emmm,怎么说呢?就像一边给孩子换尿布一边背《九阴真经》——脑子不够用。尤其是处理 backpressure 和上下文传播时,debug 到怀疑人生。
最崩溃的是某次上线后,发现用户登录态莫名其妙丢失。排查三天才发现是 Reactor 的 Context 在异步链路中断了,导致 SecurityContext 没传下去。这种“幽灵 Bug”,测试根本测不出来,只能靠肉眼盯日志+人肉回溯调用链。
技术选型:没有银弹,只有权衡
在确定用 Reactive 架构后,我们还得选消息中间件。团队内部吵了一周:有人推 RabbitMQ(老熟人,稳),有人推 Pulsar(新潮,分层存储香),还有人说直接上 Kafka(毕竟社区大)。
我拉了个表格对比了一下核心指标:
| 中间件 | 吞吐量 (msg/s) | 延迟 (ms) | 运维复杂度 | 社区活跃度 | 是否支持多租户 |
|---|---|---|---|---|---|
| Kafka | 500k+ | <10 | 中 | ⭐⭐⭐⭐⭐ | 弱 |
| Pulsar | 300k+ | <5 | 高 | ⭐⭐⭐⭐ | 强 |
| RabbitMQ | 50k | <1 | 低 | ⭐⭐⭐ | 中 |
考虑到我们未来要支持多个业务线共用同一套实时通道(产品又画了个大饼),多租户隔离成了关键。最后咬牙上了 Pulsar——虽然运维同事一脸生无可恋,但架不住它 topic 级别的配额控制真香。
顺便说一句,Pulsar 的 BookKeeper 调优过程简直反人类。光是 ledgerDirs 和 journalDirs 的磁盘 IO 分离,就让我和运维老李对骂了两次。不过现在回头看,那次“痛苦”的升级,反而让团队对分布式存储的理解深了一个 level。
实践出真知:别信文档,信监控
技术落地最怕什么?不是写不出代码,而是线上效果和预期对不上。
我们上线第一周,虽然吞吐量达标了,但 P99 延迟飙到 800ms。用户反馈“消息发出去半天才收到”。我一度以为是网络抖动,直到打开 Argo CD 的拓扑图才发现:反向代理层成了瓶颈。
原来 Nginx 默认的 keepalive 连接池太小,大量短连接打满后,新请求排队等复用。调整 upstream 配置后,延迟直接降到 30ms 以内:
upstream backend {
server reactive-service:8080;
keepalive 1000;
}
location /ws {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://backend;
}
这件事给我敲响警钟:再牛的技术栈,也扛不住基础设施的短板。从此以后,我养成了上线前必查“全链路监控”的习惯——从 CDN 到 DB,一个环节都不能放过。
技术分享的意义:不是秀肌肉,是少踩坑
说到这儿,可能有人觉得我在炫耀技术选型多牛。其实真不是。作为一个每天和尿布、辅食、deadline 打交道的妈妈程序员,我深知时间是最奢侈的资源。所以每次踩完坑,我都强迫自己写一篇内部 Wiki,哪怕只有三句话。
比如那篇《Reactor Context 丢失的七种死法》,已经被团队新人收藏为“保命指南”。上周实习生小张照着改了两行代码,避免了一次重大资损——那一刻,我觉得比涨薪还爽。
技术分享的本质,不是证明“我懂”,而是告诉别人“你可以不用像我一样痛”。
写在最后:在混乱中寻找秩序
现在,我们的实时互动系统已经稳稳扛过了今年618。虽然过程中经历了三次深夜回滚、两次 P0 事故,但至少没再出现“用户发个消息全家断网”的史诗级 Bug。
回头看看这段技术探索之路,其实没什么高深理论,就是在有限资源下,用最小代价解决问题。而所谓“前瞻性”,不过是提前预判了产品又要画饼,提前给自己挖好逃生通道罢了。
至于我?今天下午三点要去接娃,所以这篇博客必须在中午前写完。赶紧保存草稿,去改最后一个 Bug —— 毕竟,生活和代码一样,总得在 deadline 前跑通。
共勉,各位在育儿和 coding 之间走钢丝的战友。

评论 0