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

并发很头大
2025-12-17 02:31
阅读 673

上周五晚上十点半,我坐在成都家里阳台的小桌子前,泡了杯速溶咖啡——别笑,咱国企程序员不讲究这些花里胡哨的,能提神就行。窗外锦江边上夜跑的人还不少,而我正对着电脑屏幕,调试一个本地跑不通的 Eureka 注册中心。这场景要是被产品经理看到了,怕是要感动得热泪盈眶:“你看人家多敬业!”

但说实话,我根本不是“加班”,纯粹是自己想搞明白 Spring Cloud。毕竟在我们这种双休雷打不动、下班六点准时锁门的国企,项目节奏慢得像树懒走路。可我也不想躺平啊,尤其看到隔壁组老王跳槽去了字节,薪资翻倍,心里那个痒啊……

于是上个月,我给自己立了个 flag:用 Spring Cloud 搭一套完整的微服务 Demo,就当是为下一次面试攒点干货。顺便——你懂的——万一哪天想跑路呢?


为啥要折腾微服务?真不是闲得慌

去年双11前,我们部门接了个“数字化转型”项目(领导原话),说是要把原来那个巨石应用拆成微服务。听起来高大上,实际上就是个内部审批系统,用户量不到一千,QPS 峰值也就 20。运维同事私下吐槽:“这拆微服务,纯属给蚊子装火箭推进器。”

但既然领导拍板了,那就干呗。问题是,团队里除了我,其他人连 Feign 和 Ribbon 都分不清。测试妹子甚至问我:“微服务是不是跟区块链一样,都是炒概念的?” —— 我当场差点一口茶喷出来。

说到区块链,其实跟本文关系不大,但我得按要求提一嘴:别被忽悠了,90% 的业务根本用不上区块链。微服务也一样,不是银弹。但如果你的系统确实有模块解耦、独立部署、弹性扩缩容的需求(比如我们后来真的接了个对接外部支付平台的子系统),那 Spring Cloud 真香。


从零开搞:注册中心 + 服务提供者 + 消费者

我决定从最基础的三件套开始:Eureka(注册中心) + 两个 Spring Boot 应用(一个提供者,一个消费者)。目标很简单:消费者能通过服务名调用提供者的接口。

第一步:搭 Eureka Server

新建一个 eureka-server 项目,pom.xml 引入:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

application.yml 配置:

server:
  port: 8761

eureka:
  client:
    register-with-eureka: false  # 自己就是注册中心,不用注册自己
    fetch-registry: false
  server:
    enable-self-preservation: false  # 开发环境关掉自我保护,不然服务下线后还会显示

主启动类加上 @EnableEurekaServer,搞定。启动后访问 http://localhost:8761,熟悉的蓝色界面出现,那一刻,我仿佛回到了大学做课程设计的日子——简单,但踏实。

第二步:写个服务提供者(user-service)

再建一个 user-service,引入:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置文件:

server:
  port: 8081

spring:
  application:
    name: user-service  # 服务名,消费者靠它找你

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

写个简单的 Controller:

@RestController
public class UserController {
    @GetMapping("/user/{id}")
    public String getUser(@PathVariable Long id) {
        return "User-" + id; // 假数据,别较真
    }
}

启动后刷新 Eureka 页面,USER-SERVICE 出现在 Instances 下,绿色 UP 状态。稳了!

第三步:消费者(order-service)调用它

新建 order-service,同样引入 Eureka Client,配置类似,端口改成 8082,服务名叫 order-service

关键来了:怎么调用 user-service

早期可以用 RestTemplate + @LoadBalanced,但现在更推荐 OpenFeign(声明式 HTTP 客户端)。

先加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

启动类加 @EnableFeignClients

然后定义 Feign 接口:

@FeignClient(name = "user-service") // 对应 provider 的 spring.application.name
public interface UserClient {
    @GetMapping("/user/{id}")
    String getUser(@PathVariable("id") Long id);
}

在 OrderController 里注入使用:

@RestController
public class OrderController {

    @Autowired
    private UserClient userClient;

    @GetMapping("/order/{userId}")
    public String createOrder(@PathVariable Long userId) {
        String user = userClient.getUser(userId);
        return "Created order for " + user;
    }
}

启动 order-service,访问 http://localhost:8082/order/123,返回 Created order for User-123。完美!


踩过的坑 & 面试题预警

你以为这就完了?Too young.

坑1:服务注册延迟

本地开发时,服务启动后 Eureka 页面要等 30 秒才显示?因为默认心跳间隔是 30 秒。开发环境可以调快点:

eureka:
  instance:
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 10

但生产环境千万别乱改!否则可能引发误判下线。

坑2:Feign 超时

有一次线上调用突然超时,查了半天发现 Feign 默认超时只有 1 秒。赶紧配:

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 10000

坑3:服务雪崩

没加熔断,一个服务慢,整个链路卡死。后来上了 Resilience4j(Hystrix 已停更),加 fallback:

@FeignClient(name = "user-service", fallback = UserClientFallback.class)
public interface UserClient { ... }

@Component
public class UserClientFallback implements UserClient {
    @Override
    public String getUser(Long id) {
        return "Default User"; // 降级返回
    }
}

性能优化:别只顾着功能,忘了 QPS

作为对性能优化有点执念的人,我顺手压测了一下。

用 JMeter 模拟 100 并发,直接调 order-service

场景 平均响应时间 (ms) 错误率
单体应用(模拟) 45 0%
微服务(无优化) 120 0%
微服务 + Feign 连接池 78 0%

Feign 默认用的是 JDK 的 HttpURLConnection,性能一般。换成 OkHttp:

feign:
  httpclient:
    enabled: false
  okhttp:
    enabled: true

并加连接池配置:

okhttp:
  max-connections: 200
  max-connections-per-route: 50

效果立竿见影。后端开发不能只写 CRUD,得关心网络开销、序列化效率、连接复用。


关于 Python 和跨语言调用

有朋友问:我们团队主要用 Python,能和 Spring Cloud 互通吗?

答案是:可以,但别硬融

Eureka 支持非 Java 客户端(比如 py-eureka-client),Consul 或 Nacos 更友好。但如果你的 Python 服务只是偶尔调用 Java 微服务,不如走 API Gateway(比如 Spring Cloud Gateway)暴露 REST 接口,简单可靠。

微服务的核心是解耦,不是技术栈统一。强行让 Python 服务注册到 Eureka,后期维护成本可能高于收益。


生产环境那些事儿

在我们国企,上线流程比代码还复杂。但微服务上线,我总结了几条血泪经验:

  1. 每个服务必须有健康检查接口(Spring Boot Actuator /actuator/health
  2. 日志必须带 traceId,用 Sleuth + Zipkin 链路追踪,不然排查问题靠猜
  3. 配置中心用 Nacos 或 Apollo,别把数据库密码写死在 yml 里
  4. 不要过度拆分!我们一开始拆了 8 个服务,结果 CI/CD 流水线跑一次 20 分钟,测试环境资源不够,天天吵架

最后:这玩意儿面试真考

最近帮几个朋友模拟面试,Spring Cloud 高频面试题基本逃不开:

  • Eureka 和 Zookeeper 的 CAP 区别?
  • Feign 的工作原理?怎么实现负载均衡?
  • 服务雪崩怎么预防?Hystrix 和 Resilience4j 选哪个?
  • 网关的作用?为什么不用 Nginx 直接做?

这些问题,光背八股文没用。你得真搭过、真踩过坑,才能答出细节。比如被问“Feign 超时怎么配”,如果你只说 readTimeout,面试官可能觉得你纸上谈兵;但如果你补充一句“我们线上因为没配,导致支付回调超时,后来加了 OkHttp 连接池和重试机制”,那印象分直接拉满。


写在最后

折腾这套 Demo 花了我三个深夜,但值了。不仅搞懂了 Spring Cloud 的核心组件,还顺手整理了一份可复用的脚手架模板。现在每次新项目,直接 clone 改改就能用,再也不用求着架构组给模板了。

虽然我们国企项目节奏慢,但技术不能停。谁知道哪天政策一变,或者自己想换个赛道呢?保持手感,永远比抱怨环境有用

对了,如果你也在成都,又对微服务或性能优化感兴趣,欢迎一起喝杯茶(或者火锅)聊聊。反正周末我不加班,有的是时间。

—— 一个在锦江边写代码的国企程序员,于 2024 年初夏

评论 0

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