Spring Cloud 微服务从零起步:手把手教你搭建第一个分布式系统
大家好,我是一名工作五年的后端工程师,也带过不少刚入行的新人。很多人一听到“微服务”“Spring Cloud”就头皮发麻,觉得这玩意儿高深莫测。其实我当初学的时候也一样——看文档像读天书,跑个 Demo 半天起不来,差点以为自己不适合干这行。
今天我就用最直白的方式,带你从零开始搭建一个真正的 Spring Cloud 微服务项目。哪怕你连“微服务”是什么都不知道,也能跟着做完!
顺便说一句:虽然标题里提到了“爬虫”和“Python”,但别担心——这不是一篇讲 Python 的文章。我们会在最后用 Python 写一个极简爬虫,用来调用我们搭建的微服务接口,这样你就能看到前后端协作的真实场景了!
为什么需要微服务?
想象一下:你开发了一个电商网站,所有功能(用户登录、商品展示、订单支付)都写在一个 Java 项目里。一开始没问题,但随着业务增长,代码越来越臃肿,改一个小功能可能要重新部署整个系统,团队协作也变得混乱。
微服务就是把大项目拆成多个小服务,每个服务独立开发、部署、运行。比如:
user-service负责用户管理product-service负责商品信息order-service负责下单逻辑
它们之间通过网络互相调用,就像乐高积木一样灵活组合。
而 Spring Cloud 就是一套工具箱,帮你解决微服务之间的通信、配置、容错等问题。
环境准备:5 分钟搭好开发环境
⚠️ 注意:本教程基于 Java 17 + Maven + IntelliJ IDEA。如果你还没装 JDK,请先安装。
1. 安装必要软件
| 软件 | 版本建议 | 作用 |
|---|---|---|
| JDK | 17(推荐 OpenJDK) | 运行 Java 程序 |
| Maven | 3.8+ | 项目依赖管理 |
| IntelliJ IDEA | 社区版即可 | 代码编辑器 |
| Python | 3.8+ | 最后一步写爬虫用 |
你可以通过命令行验证是否安装成功:
java -version # 应显示 17.x
mvn -v # 显示 Maven 版本
python --version # 显示 Python 3.x
2. 创建父工程(Maven 聚合项目)
微服务项目通常包含多个子模块,我们先建一个“空壳”父工程来统一管理。
在终端执行:
mkdir spring-cloud-demo
cd spring-cloud-demo
然后创建 pom.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.0</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<!-- 后面会添加子模块 -->
</modules>
</project>
这一步只是定义了项目的基础结构,还没写任何业务代码。
核心概念:微服务三要素
在动手前,先搞懂三个关键角色:
1. 服务注册中心(Eureka)
就像公司的通讯录——每个服务启动时都要去“登记”自己的名字和地址,其他服务想调用它,就去通讯录里查。
2. 服务提供者
提供具体功能的微服务,比如返回商品列表。
3. 服务消费者
调用其他服务的微服务,比如订单服务需要调用用户服务获取用户信息。
✅ 简单记:注册中心是“中介”,提供者是“卖家”,消费者是“买家”。
实战:搭建你的第一个微服务系统
我们将创建三个模块:
eureka-server:服务注册中心product-service:商品服务(提供者)order-service:订单服务(消费者)
第一步:创建 Eureka 注册中心
在项目根目录下执行:
mkdir eureka-server
在 eureka-server 目录中创建 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
然后创建主启动类 src/main/java/com/example/EurekaServerApplication.java:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer // 启用 Eureka 服务端
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
再加一个配置文件 src/main/resources/application.yml:
server:
port: 8761
eureka:
client:
register-with-eureka: false # 不向自己注册
fetch-registry: false # 不拉取注册表
server:
wait-time-in-ms-when-sync-empty: 0
💡 为什么端口是 8761?这是 Eureka 默认端口,约定俗成。
第二步:创建商品服务(提供者)
mkdir product-service
product-service/pom.xml:
<project ...>
<parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>product-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
主启动类 ProductServiceApplication.java:
@SpringBootApplication
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
控制器 ProductController.java:
@RestController
public class ProductController {
@GetMapping("/products/{id}")
public Map<String, Object> getProduct(@PathVariable Long id) {
return Map.of("id", id, "name", "iPhone 15", "price", 5999);
}
}
配置文件 application.yml:
server:
port: 8081
spring:
application:
name: product-service # 服务名,必须唯一!
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
第三步:创建订单服务(消费者)
同样创建 order-service 模块,pom.xml 和 product-service 一样。
关键区别在于:我们要调用商品服务。
主启动类加上 @EnableDiscoveryClient:
@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
// 注册 RestTemplate 用于远程调用
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
订单控制器:
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/orders/{id}")
public String createOrder(@PathVariable Long id) {
// 通过服务名调用,而不是 IP+端口!
String url = "http://product-service/products/" + id;
Map product = restTemplate.getForObject(url, Map.class);
return "已下单:" + product.get("name");
}
}
配置文件 application.yml:
server:
port: 8082
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
第四步:启动并测试
- 启动
EurekaServerApplication(访问 http://localhost:8761,应看到 Eureka 面板) - 启动
ProductServiceApplication - 启动
OrderServiceApplication
几秒后,刷新 Eureka 页面,你会看到两个服务已注册:
Application AMIs Availability Zones
PRODUCT-SERVICE 1 (1)
ORDER-SERVICE 1 (1)
现在访问订单接口:
curl http://localhost:8082/orders/1001
# 返回:已下单:iPhone 15
✅ 成功!订单服务通过服务名 product-service 找到了商品服务,完全不需要知道它的 IP 和端口!
用 Python 爬虫调用微服务(资源联动)
前面提到“爬虫”和“Python”,这里我们用 Python 写一个脚本,模拟外部系统调用我们的微服务。
创建 call_order.py:
import requests
def place_order(product_id):
url = f"http://localhost:8082/orders/{product_id}"
response = requests.get(url)
if response.status_code == 200:
print("✅ 订单成功:", response.text)
else:
print("❌ 调用失败:", response.status_code)
if __name__ == "__main__":
place_order(1001)
安装依赖并运行:
pip install requests
python call_order.py
输出:
✅ 订单成功: 已下单:iPhone 15
🌟 这就是微服务的价值:无论你是前端、Python 脚本、手机 App,只要知道接口地址,就能使用服务!
新手常见问题 & 避坑指南
Q1:启动报错 “Cannot resolve configuration property”?
A:检查 application.yml 缩进是否正确。YAML 对空格敏感,必须用空格,不能用 Tab。
Q2:服务没出现在 Eureka 页面?
A:检查三点:
- 提供者/消费者是否配置了
eureka.client.service-url.defaultZone - 服务名(
spring.application.name)是否重复 - 防火墙是否阻止了 8761 端口
Q3:调用时报 UnknownHostException: product-service?
A:确保 RestTemplate 加了 @LoadBalanced 注解!这是 Spring Cloud 实现服务发现的关键。
Q4:为什么不用 Nacos 而用 Eureka?
A:Eureka 是 Spring Cloud Netflix 套件中最经典的注册中心,学习曲线平缓。后续你可以无缝迁移到 Nacos、Consul 等。
下一步怎么学?
你已经迈出了微服务的第一步!接下来建议:
- 深入学习 Spring Cloud Alibaba(国内更流行)
- 加入配置中心(如 Spring Cloud Config 或 Nacos Config)
- 引入网关(Spring Cloud Gateway)统一入口
- 学习熔断机制(Sentinel 或 Hystrix)防止雪崩
📌 我的经验:不要一开始就追求“高可用”“分布式事务”。先跑通一个完整链路,再逐步优化。
结语
微服务不是银弹,但它是现代后端开发的必备技能。今天这个 Demo 虽小,却包含了服务注册、发现、调用的核心逻辑。你写的每一行代码,都是通往架构师之路的基石。
如果你跟着做完了,恭喜你——你已经超越了 80% 只看不练的初学者!
有问题欢迎留言,我会一一解答。下期我们聊聊“如何用 Docker 一键部署整套微服务”。
Happy coding!

评论 0