从汽修工到Java程序员:我在新公司用Spring Cloud Alibaba踩过的坑

技术碎碎念
2026-01-05 23:57
阅读 1248

去年这个时候,我还在4S店拧螺丝,简历上写的还是“精通大众EA888发动机拆装”。今年三月,靠着三个月狂啃Java基础、刷LeetCode、背八股文,终于在30岁高龄成功转行,入职了一家电商中台公司。说实话,入职第一天看到满屏的微服务架构图,我差点想删了IDEA回老家继续修车——至少扳手不会报NoSuchBeanDefinitionException

入职两个月,项目组正在做一套新的促销系统,技术栈是Spring Boot + Spring Cloud Alibaba(SCA)。领导说:“你之前没接触过微服务?没事,边干边学。”然后丢给我一个任务:把新模块接入Nacos注册中心和Sentinel限流。我当时内心OS:Nacos是啥?能吃吗?

但没办法,为了不让自己的简历在下一次跳槽时还写着“只会CRUD”,只能硬着头皮上。今天这篇,就是我这两个月在生产环境里摸爬滚打的真实记录,全是血泪经验,不掺水。


为什么选Spring Cloud Alibaba?

我们团队原本用的是Spring Cloud Netflix那一套(Eureka + Hystrix + Zuul),但Netflix组件早就不维护了,加上公司想降本增效,运维同事天天吐槽Zuul性能差、Hystrix配置反人类。于是架构组拍板:全面迁移到Spring Cloud Alibaba。

好处很明显:

  • Nacos 既能做服务注册发现,又能做配置中心,省了两套中间件
  • Sentinel 提供实时监控+动态规则,比Hystrix可视化强太多
  • Seata 虽然还没用上,但未来分布式事务有保障

但坏处也很真实:文档散、社区案例少、坑多。尤其像我这种半路出家的,连“服务熔断”和“服务降级”都分不清,第一次看Sentinel控制台直接懵圈。


第一个坑:Nacos注册不上,服务“失联”

刚搭完本地环境,信心满满启动服务,结果Nacos控制台空空如也。查日志发现:

com.alibaba.nacos.api.exception.NacosException: failed to req API:/nacos/v1/ns/instance after all servers([127.0.0.1:8848]) tried

我第一反应:是不是Nacos没启动?结果一查,端口占用了!原来我本地同时跑着Redis、MySQL、RabbitMQ,8848被某个测试脚本占了。改端口后又遇到新问题:服务注册成功了,但其他服务调用时报UnknownHostException

后来才发现,Nacos默认用hostname注册,而我的Mac主机名是xiaomingdeMBP.local,其他Docker容器根本解析不了。解决办法很简单,在application.yml里强制指定IP:

spring:
  cloud:
    nacos:
      discovery:
        ip: 192.168.1.100  # 写死本机内网IP(开发环境临时方案)
        port: 8080

📌 生产建议:线上环境务必通过K8s或Docker网络配置,不要写死IP!我们后来用spring.cloud.inetutils.preferred-networks=10.0自动识别内网段。


第二个坑:Sentinel规则不生效,限流形同虚设

产品经理上周五下班前甩来一句:“双11大促,下单接口必须扛住10万QPS!” 我心想:好家伙,我们现在单机才500QPS,这不得崩?

赶紧给核心接口加上Sentinel注解:

@SentinelResource(value = "createOrder", blockHandler = "handleBlock")
public Result createOrder(OrderDTO dto) {
    // 业务逻辑
}

public Result handleBlock(OrderDTO dto, BlockException ex) {
    return Result.fail("系统繁忙,请稍后再试");
}

本地压测,一切正常。可上线后,监控显示流量暴增,但Sentinel控制台里的QPS始终是0!规则根本没触发。

排查半天才发现:Sentinel默认只监控Web入口(Controller),而我把注解放在了Service层。更坑的是,我们用了Feign远程调用,FeignClient默认也不被Sentinel接管!

解决方法:

  1. 在启动类加@EnableFeignSentinel
  2. 配置文件开启对Feign的支持:
    feign:
      sentinel:
        enabled: true
    
  3. 确保Sentinel Transport端口没被防火墙挡住(我们运维一度关了18719端口)

搞定后,终于能在控制台动态调整阈值了。上周大促预演,我们把下单接口限流设为2000QPS,超出就返回友好提示,系统稳如老狗。


工具链:没有趁手的工具,等于裸奔

作为一个从传统行业转来的新人,我深刻体会到:光会写代码不够,得会用工具。我们团队推崇“可观测性优先”,所以以下工具成了我的救命稻草:

工具 用途 我的使用场景
Arthas Java诊断神器 线上CPU飙高,用trace定位到某个循环没加缓存
SkyWalking 分布式链路追踪 查Feign调用超时,发现下游服务GC频繁
JMeter 压测 验证Sentinel限流是否生效
GitLab CI 自动化部署 每次提交自动打包、推镜像、更新K8s

特别说下Arthas。有一次凌晨两点,订单服务突然大量超时,我连上服务器敲了句:

watch com.example.service.OrderService createOrder '{params, returnObj}' -x 3

直接看到入参和返回值,发现是某个优惠券ID传错了导致DB死循环。要是没这工具,我可能得通宵翻日志。


数据库与接口设计:别让微服务变成“分布式屎山”

很多人以为上微服务就是拆模块、加注册中心。但我在修车时就明白:再好的发动机,油路堵了也跑不动

我们的促销系统涉及商品、库存、订单、用户四个服务。最初设计时,每个服务都有自己的DB,但查询订单详情要调三次Feign。结果大促时,链路过长,一个环节慢,全链路雪崩。

后来我们做了两件事:

  1. 读写分离 + 缓存:订单详情页走ES聚合数据,避免跨服务JOIN
  2. 异步解耦:下单成功后发MQ消息,由库存服务异步扣减,避免同步阻塞

接口设计上,坚决不用Map传参!全部定义DTO,并加上Swagger注解:

/**
 * 创建订单请求
 */
@Data
@ApiModel("CreateOrderRequest")
public class CreateOrderRequest {
    @ApiModelProperty(value = "商品ID", required = true)
    @NotNull(message = "商品ID不能为空")
    private Long productId;
    
    @ApiModelProperty(value = "购买数量", example = "1")
    @Min(value = 1, message = "数量至少为1")
    private Integer quantity;
}

前端同事夸我“终于不像外包写的代码了”,其实我只是怕被测试提一堆“参数校验缺失”的bug。


心得:30岁转行,靠的不是天赋,是脸皮厚

这两个月,我问的问题可能比团队所有人加起来还多。从“Nacos怎么集群部署”到“Sentinel和Hystrix区别”,甚至问运维“为什么K8s Pod重启了”。一开始怕被笑话,后来发现:大家其实都愿意帮新人,只要你肯学

上周团建,CTO跟我说:“你虽然是转行的,但工具用得比很多老员工还溜。” 其实哪有什么天赋,不过是下班后边听周杰伦《晴天》边敲代码,周末泡在B站看SCA源码解析。

如果你也和我一样,30岁+、非科班、简历平平,别怕。Java生态的护城河很深,但Spring Cloud Alibaba这样的国产框架,反而给了我们弯道超车的机会。至少现在,我的简历上可以写:“主导微服务治理,支撑日均百万订单”。

最后送自己一句话,也送给你:

扳手换键盘,代码即扳手。只要肯拧,没有修不好的Bug。


本文所有案例均来自真实生产环境(已脱敏)。项目已稳定运行两周,QPS峰值达1.2万,错误率<0.1%。感谢团队小伙伴的耐心带教,特别是容忍我每天问“这个配置是干嘛的”的后端组长。

评论 0

最热最新
暂无评论
技术碎碎念Lv.1
0
影响力
0
文章
0
粉丝