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

产品说很简单
2025-12-16 07:48
阅读 235

上周五晚上十点,我戴着耳机听着 Lo-fi Hip Hop 写代码(别笑,这玩意儿真能治焦虑),突然收到产品发来的新需求:“咱们要搞个去中心化的供应链溯源系统,用区块链存关键交易记录。”我当时差点一口老血喷在机械键盘上——我们后端还在单体架构里挣扎,连数据库读写分离都没做好,现在就要上链?

但转念一想,反正干了三年多,也该换个环境了。跳槽简历上总不能只写“精通 CRUD”吧?于是咬咬牙,决定把整个系统重构为微服务架构,顺便把 Spring Cloud 这套东西彻底吃透。

说真的,如果不是被逼到墙角,谁愿意在 deadline 前两周重写整个系统架构啊!


为什么是 Spring Cloud?不是 Go?不是 Service Mesh?

先澄清一个误区:很多人觉得“微服务 = 必须用 Go”,或者“新项目不上 Kubernetes 就是土鳖”。但现实是——我们团队全是 Java 老兵,运维对 Spring Boot 熟得跟自家厨房一样,而产品经理下周就要 demo。时间不等人。

Go 确实快、轻量、部署简单,我也在业余时间用它写过几个小工具(比如自动抓取 GitHub Star 的脚本)。但在企业级复杂业务场景下,Spring 生态的成熟度、监控能力、事务管理、以及那堆开箱即用的 starter,真的香。尤其是 Spring Cloud Alibaba 这一套,Nacos + Sentinel + Seata,国内云厂商支持得好,文档也全。

至于区块链?别被营销话术带偏了。我们只是用 Hyperledger Fabric 存哈希值做防篡改校验,核心业务逻辑还是跑在微服务里。区块链不是银弹,更不是架构选型的理由。


从单体到微服务:我的踩坑日记

我们的老系统是个典型的“上帝类”应用:一个 Spring Boot 项目,Controller 里嵌着 DAO,Service 层调用第三方 API 还没加熔断,数据库连接池配置还是默认的 10。去年双11,流量一上来,直接 OOM,运维半夜打电话骂街。

所以这次重构,我给自己定了三个原则:

  1. 高内聚低耦合:每个服务只干一件事
  2. 可观测性优先:日志、指标、链路追踪必须到位
  3. 可维护性 > 性能:代码要让实习生也能看懂(别笑,我们真招了个实习生)

第一步:服务拆分

我把系统拆成了四个核心服务:

  • user-service:用户认证、权限
  • order-service:订单创建、状态流转
  • product-service:商品信息、库存
  • blockchain-gateway:对接 Fabric,提交交易哈希

注意:blockchain-gateway 是独立服务!千万别把区块链 SDK 直接塞进业务代码,否则调试起来能让你怀疑人生。

第二步:注册中心选型

纠结过 Eureka vs Consul vs Nacos。最后选了 Nacos,原因很现实:

  • 支持 AP + CP 切换(开发用 AP,生产切 CP)
  • 中文文档友好
  • 阿里系,和我们用的阿里云无缝集成
# bootstrap.yml (每个服务都要配)
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_HOST:localhost}:${NACOS_PORT:8848}

启动后,打开 http://localhost:8848/nacos,看到服务列表亮起绿色小点,那一刻真的爽——比看到工资条还开心。


关键配置:让微服务“活”起来

光注册还不够,微服务之间怎么通信?怎么防雪崩?怎么传用户上下文?

Feign + Ribbon:声明式调用

以前写 RestTemplate,URL 拼得像意大利面。现在用 Feign,接口定义即文档:

@FeignClient(name = "product-service", fallback = ProductClientFallback.class)
public interface ProductClient {
    @GetMapping("/products/{id}")
    Product getProduct(@PathVariable("id") Long id);
}

配合 @EnableFeignClients,注入就能用。而且天然集成 Ribbon 负载均衡,不用自己写轮询逻辑。

吐槽一句:测试同事总抱怨“你们接口又 500 了”,其实 90% 是下游服务挂了。所以 fallback 必须写!

Sentinel:熔断限流保命符

线上最怕级联失败。上次就是因为 product-service 响应慢,拖垮了整个 order-service。这次上了 Sentinel,配置如下:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            data-id: order-service-sentinel
            group-id: DEFAULT_GROUP
            rule-type: flow

在 Sentinel Dashboard 里设置 QPS 阈值,超了就快速失败,而不是傻等。还能根据 RT、异常比例自动熔断。上线后,再也不用半夜接 PagerDuty 报警了。

分布式事务:Seata 来救场

订单创建涉及扣库存、生成流水、发消息……传统 JTA 太重。我们用了 Seata AT 模式,只需要:

  1. 在每个服务的数据源包装成 DataSourceProxy
  2. 全局事务注解 @GlobalTransactional
@GlobalTransactional
public void createOrder(OrderRequest request) {
    // 1. 扣库存 (product-service)
    // 2. 创建订单 (本地)
    // 3. 发送MQ (异步)
}

虽然性能有损耗(毕竟两阶段提交),但保证了数据一致性。对于金融相关操作,这点代价值得。


数据库设计:别让微服务变成“分布式单体”

很多团队拆了服务,但数据库还是共用一个 schema,这叫“伪微服务”。

我的做法:

  • 每个服务独享数据库(甚至不同实例)
  • 禁止跨服务直接查表!只能通过 API
  • 事件驱动 解耦:订单创建成功 → 发 Kafka 事件 → 库存服务消费并更新
-- order-service 的 orders 表
CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    status VARCHAR(20) NOT NULL, -- PENDING, PAID, CANCELLED
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- product-service 的 inventory 表(完全独立)
CREATE TABLE inventory (
    product_id BIGINT PRIMARY KEY,
    stock INT NOT NULL
);

初期会多几次网络调用,但换来的是真正的解耦。后期想把 product-service 用 Go 重写?没问题,只要 API 兼容就行。


生产环境那些事儿

开发爽了,上线才是地狱模式。分享几个血泪经验:

问题 解决方案
日志分散,查问题像大海捞针 统一接入 ELK,用 traceId 串联全链路
服务启动顺序依赖 用 Nacos 的 @ConditionalOnProperty 控制初始化顺序
配置文件泄露敏感信息 敏感配置走 Nacos 加密插件 + KMS
网络抖动导致调用失败 Feign 配置 Retryer,重试 2 次

特别提一下 链路追踪。集成 SkyWalking 后,在 UI 上能看到请求从 gateway 到 order-service 再到 product-service 的完整路径,耗时一目了然。有一次发现 80% 时间花在数据库连接获取上,原来是连接池太小——这种问题靠肉眼根本看不出来。


和 Go 微服务对比?其实没必要对立

我知道有些 Go 粉要跳脚了:“Java 太重!Go 才是未来!” 但技术选型不是宗教信仰。

我们内部其实有个用 Go 写的轻量级网关,处理 TLS 卸载和 IP 黑名单,性能确实比 Spring Cloud Gateway 高 30%。但核心业务?还是 Java 更稳。混合架构才是常态

如果你团队熟悉 Go,且业务简单(比如纯 API 转发),那 Go 微服务很合适。但涉及复杂事务、遗留系统集成、大量中间件,Spring Cloud 的生态优势就出来了。


最后:微服务不是终点,而是起点

折腾了一个月,系统终于跑起来了。压力测试下,QPS 从原来的 300 提升到 2000+,最关键的是——任何一个服务挂掉,其他功能还能用

上周给产品演示时,他问:“区块链在哪?” 我指了指后台日志里一闪而过的交易哈希,他点点头:“哦,那就行。” ——你看,技术人总在为那些看不见的地方拼命。

现在我的简历上可以写:“主导微服务架构升级,支撑日均百万级交易,集成区块链防篡改。” 跳槽底气足了点。

但说实话,最让我开心的不是这些,而是某天实习生跑来问我:“哥,这个 Feign 超时怎么配?” ——说明代码真的可读、可维护。这才是工程师的浪漫。

技术分享的意义,不就是让更多人少踩坑吗?
如果你也在被单体架构折磨,不妨试试 Spring Cloud。
记住:架构没有银弹,但有适合你团队的那颗子弹。

P.S. Cursor 又帮我自动生成了 200 行配置代码,我真的离不开它了……(狗头)

评论 0

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