Spring Cloud从零开始:微服务入门指南

★何秀珍
2025-12-18 21:56
阅读 2031

早上8点刚到工位,咖啡还没泡上,钉钉就弹出一条消息:“双11大促系统压测报告出来了,单体架构扛不住了。” 我盯着屏幕叹了口气——又来了。作为前端出身、被逼着转型全栈的“老码农”,我本以为这辈子和Spring Boot打交道就够多了,结果去年领导一句话:“我们要上微服务,你牵头搞一下。” 当时真的想砸键盘。

坐标北京,每天挤地铁一小时通勤,到公司第一件事不是写代码,是看线上告警。但说真的,自从接手这个项目,我对后端架构的理解确实上了一个台阶。今天这篇不是教科书式的教程,而是我从“手写党”被迫拥抱微服务的真实踩坑记录,顺带聊聊怎么让运营、爬虫甚至前端(对,就是我这种写JavaScript的)在微服务体系里也能活得好好的。

为什么非得搞微服务?

事情得从去年双11说起。我们原来的系统是个典型的单体应用:用户管理、订单、库存、营销全塞在一个Spring Boot项目里。前端用Vue写交互,后端Java处理逻辑,运营同学每天催着加活动页、改优惠规则。测试一跑,数据库死锁;运维一看日志,CPU飙到90%。最离谱的是,有个爬虫脚本半夜疯狂请求商品详情页,直接把整个服务拖垮了——因为所有功能共用同一个线程池!

产品经理当时还一脸无辜:“不就是多几个请求嘛?加个限流不就行了?”
我内心OS:大哥,这是单体架构,限流得限整个服务,那正常用户也进不去了啊!

于是,微服务成了唯一出路。拆!把用户中心、订单服务、商品服务、营销引擎各自独立,互不影响。哪怕爬虫把商品服务打崩了,用户还能下单、支付。

动手前先理清边界

很多人一上来就 spring-cloud-starter 全家桶怼上去,结果发现服务注册了半天找不到,配置中心连不上,熔断器莫名其妙触发。我一开始也这样,直到被运维小哥嘲讽:“你这微服务,比我家Wi-Fi还不稳定。”

关键在于边界划分。我们团队开了三天会,拉着运营、产品、测试一起画领域模型:

  • 用户服务:只管注册、登录、权限
  • 商品服务:商品CRUD、分类、库存预占
  • 订单服务:下单、支付状态、退款
  • 营销服务:优惠券、满减、限时活动

特别注意:运营提的需求往往横跨多个服务。比如“给新用户发30元无门槛券”,就得调用户服务判断是否新用户,再调营销服务发券。这时候不能图省事在某个服务里硬编码调另一个——得用事件驱动或API网关聚合。

手把手搭建骨架(附真实配置)

别信网上那些“5分钟搭建微服务”的鬼话。我花了整整一周才跑通第一个Hello World级别的调用。下面是我目前稳定运行的最小可行配置,亲测有效。

1. 注册中心:Eureka起步

# eureka-server/src/main/resources/application.yml
server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false  # 服务端不注册自己
    fetch-registry: false

启动后访问 http://localhost:8761,看到那个熟悉的红色“NO UP INSTANCES”就对了——还没服务注册呢。

2. 商品服务(被爬虫最爱的那个)

// ProductService.java
@RestController
public class ProductController {
    
    @GetMapping("/api/v1/products/{id}")
    public Product getProduct(@PathVariable Long id) {
        // 实际业务逻辑...
        return productRepository.findById(id);
    }
}

它的 application.yml 要注册到Eureka:

spring:
  application:
    name: product-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

3. 网关层:Zuul挡爬虫

这里重点来了!运营总抱怨“爬虫把接口刷爆了”,其实可以在网关层做统一防护:

# zuul-gateway/application.yml
zuul:
  routes:
    product:
      path: /product/**
      serviceId: product-service
      strip-prefix: false

# 加入限流(用Redis+Lua脚本实现)
rate-limiter:
  redis:
    host: localhost
    port: 6379
  rules:
    - path: /product/**
      qps: 100  # 每秒最多100次

这样,哪怕爬虫再猛,也只会被限在商品服务入口,不会影响用户下单。

前端/运营如何与微服务共舞?

我知道你们前端和运营同学看到“微服务”三个字就头大。但好消息是:对你们来说,几乎没变化!

  • 前端(JavaScript):依然调同一个域名(比如 api.yourcompany.com),后面Zuul网关自动路由到对应服务。我们甚至保留了旧版API路径,用Swagger生成文档,前端同学根本不用关心后端拆了几块。

  • 运营:他们用的后台管理系统,前端通过 /admin/marketing/coupons 请求发券,网关会转发到营销服务。运营只需知道“这个功能在哪点”,不用懂服务名。

  • 爬虫:我们专门开了一个 crawler-service,要求所有外部爬虫必须带特定Header(比如 X-Crawler-Token: secret123),否则403。顺便加了User-Agent检测,防君子不防小人。

生产环境血泪教训

别以为本地跑通就万事大吉。上周五晚上11点,线上突然大量500错误。查日志发现是服务间调用超时——订单服务调商品服务,默认Feign超时只有1秒,而商品服务在查ES时偶尔慢到2秒。

解决方案:显式配置超时和重试

# order-service/application.yml
feign:
  client:
    config:
      default:
        connectTimeout: 2000
        readTimeout: 5000
  retryer:
    enabled: true

另外,数据库连接池也要隔离。之前所有服务共用一个DB,结果营销服务跑批量任务把连接占满了,用户登录都失败。现在每个服务独立数据源,甚至用不同MySQL实例。

性能对比:拆完真香?

拆分前后核心指标对比:

指标 单体架构 微服务架构
平均响应时间 420ms 210ms(网关+服务)
爬虫攻击影响 全站瘫痪 仅商品页降级
发布频率 每周1次 每天多次(各服务独立发布)
故障排查时间 2小时+ <30分钟(精准定位服务)

虽然运维复杂度上升了(要管N个服务的日志、监控),但稳定性提升是实打实的。特别是双11当天,商品服务被爬虫打到自动熔断(Hystrix兜底返回缓存数据),订单服务完全不受影响——运营总监当场请我们团队喝了奶茶。

写在最后:手写党的反思

作为曾经坚信“能手写绝不依赖框架”的老派程序员,我一度觉得Spring Cloud太重、太黑盒。但现实是:业务复杂度上来后,轮子造不过来。Eureka的服务发现、Ribbon的负载均衡、Hystrix的熔断——这些你手写一个月也未必比官方稳定。

当然,我依然坚持:关键业务逻辑必须手写,不能盲目依赖AI生成。上周Copilot给我生成了个Feign客户端,结果漏了@RequestMapping,调用直接404。还是得自己一行行敲,心里才有底。

微服务不是银弹,但当你面对运营天天改需求、爬虫半夜刷接口、产品喊着“快速迭代”时,它可能是目前最靠谱的解法。至少现在,我能在8点准时下班(偶尔),而不是盯着半夜告警修到凌晨。

共勉。

评论 0

最热最新
暂无评论
★何秀珍Lv.1
0
影响力
0
文章
0
粉丝