关于技术探索与实践的一些经验

周华
2025-12-19 10:24
阅读 627

上周五晚上 9 点半,我坐在公司工位上,盯着屏幕上 Spring Boot 应用启动失败的日志——Error creating bean with name 'dataSource'...。窗外天已经全黑了,隔壁工位的同事早已溜之大吉,只有我和产品经理小王还在“深情对望”。他刚在企业微信里发来一句:“这个功能双11前必须上线啊,老板很看重。”

那一刻我真的想砸电脑。

但转念一想,这不就是我们这群写代码的人的日常吗?一边被 deadline 追着跑,一边还得琢磨怎么把代码写得既快又稳。今天这篇文章,就聊聊我在过去几年折腾技术时踩过的坑、攒下的经验,以及为什么我这个在老东家待了三年多的“老人”,开始认真考虑换个环境了。


我是谁?一个不想再当“人肉补丁”的试用期员工

对,你没看错——试用期员工。虽然我已经在这家公司干了三年多,但今年初内部转岗到了新成立的创新产品线,按流程重新走了一遍入职,现在正处于三个月试用期的尾巴上。说起来有点讽刺:明明是老员工,却要像新人一样写日报、做周报、参加各种“破冰”会议。

不过话说回来,这次转岗也让我有机会重新审视自己的技术栈和职业路径。之前一直在维护一个古老的单体系统,代码像意大利面条一样缠在一起,连加个日志都得小心翼翼。而新团队主推微服务 + Spring Boot 技术栈,要求高内聚、低耦合、可测试、可回滚……嗯,听起来很美好,但现实总是骨感的。

也正是在这种“既要又要还要”的压力下,我才真正意识到:技术探索不是为了炫技,而是为了活下去


产品需求 vs. 工程现实:一场永无止境的拉锯战

我们正在做的是一款面向 C 端用户的智能推荐产品。产品经理小王(对,就是那个周五晚上还在催我的人)的想法天马行空:“我们要做千人千面!实时更新!毫秒级响应!”

听起来很酷,但落到工程层面,问题就来了:

  • 数据源来自五个不同的上游系统
  • 用户行为日志每秒上万条
  • 推荐算法模型需要每天凌晨训练
  • 前端要求接口响应时间 ≤200ms

更惨的是,项目立项时只给了两个月开发周期。运维同学一听就摇头:“你们这架构,怕是要在双11当天给用户送‘404 礼包’。”

怎么办?硬上呗。

第一步:别急着写代码,先画边界

很多新人(包括曾经的我)一接到需求就打开 IDE 开干。结果往往是:写到一半发现上下游接口没对齐,或者某个依赖服务压根不支持你需要的功能。

这次我学乖了。花了整整两天时间,拉着后端、前端、算法、测试开“需求澄清会”。用白板画出了整个数据流:

[用户点击] → [埋点上报] → [Kafka] → [Flink 实时计算] → [Redis 缓存]
                          ↘ [离线 Hive 表] → [Spark 训练] → [模型服务]
→ [Spring Boot API] ← [MySQL + Elasticsearch]

明确每个环节的 SLA、容错机制和降级策略。比如 Redis 挂了怎么办?直接走 MySQL 冷查询,虽然慢点但不至于崩盘。

这个过程虽然“浪费”了两天,但避免了后期返工。代码可以重构,但信任一旦崩了,再难重建


Spring Boot:不是银弹,但能救命

新项目用 Spring Boot 3.x + Java 17。说实话,一开始我是抗拒的——毕竟老系统还在用 Spring Boot 1.5,升级成本太高。但这次是全新项目,正好借机上新版本。

不过,Spring Boot 的“约定优于配置”是一把双刃剑。新手觉得它开箱即用,老手知道它暗藏玄机。

踩坑实录:自动配置的“善意陷阱”

有一次,我在 application.yml 里配了两个数据源:

spring:
  datasource:
    primary:
      url: jdbc:mysql://...
    secondary:
      url: jdbc:mysql://...

结果启动时报错:No qualifying bean of type 'javax.sql.DataSource' available

查了半天才发现,Spring Boot 的 DataSourceAutoConfiguration 默认只会绑定到 spring.datasource 下的配置。自定义多数据源?得自己写 @Configuration 类,手动注入 DataSource Bean。

后来我干脆封装了一个通用的多数据源 Starter,加了详细的注释:

/**
 * 多数据源配置 - 注意:不要和 Spring Boot 默认的 DataSourceAutoConfiguration 冲突
 * 使用方式:
 * 1. 在 application.yml 中定义 ds1, ds2...
 * 2. 在 Service 上用 @DS("ds1") 注解指定数据源
 */
@Configuration
public class MultiDataSourceConfig {
    // ... 省略实现
}

这种“看起来很简单,其实很坑”的地方,在 Spring Boot 里比比皆是。自动配置省了你 80% 的活,但也偷走了你对系统的掌控感。所以我的建议是:至少读一遍官方文档的 Auto-configuration 章节,再决定要不要用


代码人生:可读性比性能更重要(在大多数情况下)

我是个 Mac 党,Windows 只用来测兼容性。不是装,是真的觉得 macOS 的终端 + VS Code + iTerm2 组合太香了。但有一次,我写的代码在 Windows 测试机上跑不起来——因为路径分隔符用了 / 而不是 File.separator

测试妹子直接在 JIRA 里@我:“MacBoy,你的代码又飘了!”

这件事让我反思:我们写代码,到底是为了机器执行,还是为了人阅读?

在高压交付环境下,很多人会说:“能跑就行,别管格式。”但等你半年后回头看自己写的代码,发现连自己都看不懂,那种绝望感……懂的都懂。

所以我现在坚持几个原则:

  1. 方法不超过 30 行:超过就拆
  2. 变量命名拒绝缩写userPaymentServiceups 强一百倍
  3. 复杂逻辑必须写注释:不是解释“做了什么”,而是说明“为什么这么做”
  4. 提交信息写清楚上下文fix bug 是垃圾,fix NPE in OrderService when user is null (see JIRA-123) 才是专业

举个真实例子。我们有个订单状态机,最初是用一堆 if-else 写的:

if (status == PAID && action == SHIP) {
    // ...
} else if (status == SHIPPED && action == DELIVER) {
    // ...
}

后来我把它改成了状态模式 + 策略模式,虽然代码量多了,但新增状态只需要加一个类,不用动主流程。短期看是“过度设计”,长期看是“救命稻草”


简历上的“技术亮点”,往往来自深夜的崩溃

说到简历,最近我在偷偷更新。三年多的经验,不能只写“熟悉 Spring Boot”、“参与过多个项目”这种废话。

HR 看简历平均只有 6 秒。怎么在 6 秒内抓住眼球?用结果说话

比如:

  • ❌ “使用 Spring Boot 开发后端服务”

  • ✅ “通过 Spring Boot 自定义 Starter 封装多数据源组件,降低团队接入成本 70%,支撑日均 500w 请求”

  • ❌ “优化系统性能”

  • ✅ “重构订单状态机,将状态变更错误率从 5% 降至 0.1%,减少客诉 200+/月”

这些数字哪来的?都是被线上事故逼出来的。

记得去年双11,我们的推荐接口因为缓存穿透,QPS 瞬间打爆数据库。半夜三点被 PagerDuty 叫醒,手抖着回滚版本。第二天复盘会上,CTO 盯着我说:“你要对你的代码负责,不只是写完就跑。”

那之后,我给所有对外接口加了熔断、限流、降级三件套:

@CircuitBreaker(name = "recommendation", fallbackMethod = "fallbackRecommend")
@RateLimiter(name = "recommendation", limitForPeriod = 1000)
public List<Item> getRecommendations(String userId) {
    // ...
}

private List<Item> fallbackRecommend(String userId, Exception e) {
    log.warn("Fallback to default recommendations due to: {}", e.getMessage());
    return defaultItems;
}

现在这段代码成了我简历里的“明星案例”。


技术选型:没有最好,只有最合适

经常看到网上争论:“Spring Boot vs. Go”、“Kafka vs. RabbitMQ”、“MySQL vs. MongoDB”……

但在真实业务中,技术选型从来不是纯技术问题,而是成本、风险、团队能力的综合权衡

我们团队只有 5 个后端,3 个刚毕业。如果强行上一套复杂的 Event Sourcing + CQRS 架构,估计三天就得崩。所以最终我们选择了:

组件 选择 原因
Web 框架 Spring Boot 3.x 团队熟悉,生态成熟
消息队列 Kafka 高吞吐,已有运维支持
缓存 Redis Cluster 支持数据分片,社区方案多
数据库 MySQL 8.0 ACID 强一致,DBA 有经验

有人可能会说:“这不够酷。”但能稳定跑一年的平庸架构,远胜于三天就崩的‘先进’架构


写在最后:为什么我想换个环境?

说了这么多,其实有个心结一直没解开。

在这家公司三年多,我从 Junior 成长为能独立负责模块的工程师,也积累了不少实战经验。但最近越来越觉得:舒适区待久了,技术会生锈

团队氛围不错,领导也认可我的能力,但业务进入平稳期,技术挑战越来越少。每天的工作变成了“修修补补”、“救火救火”。而我想做的,是参与从 0 到 1 的产品构建,尝试更前沿的技术(比如云原生、Serverless),而不是在旧系统上打补丁。

所以,我开始更新简历,也开始写这样的技术总结。不是为了炫耀,而是梳理自己的知识体系,看清下一步该往哪走

技术探索的本质,从来不是追新,而是在约束条件下找到最优解。而所谓“代码人生”,就是在无数次崩溃与修复中,慢慢学会与不确定性共处。

哦对了,上周五那个 dataSource 的问题,最后发现是 YAML 缩进错了两格。😅


P.S. 如果你也在经历类似的职业倦怠,不妨问问自己:现在的环境,还能让你每周学到新东西吗? 如果答案是否定的,也许,是时候出发了。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝