Spring Cloud 微服务,真的没你想的那么难!

独立开发小站
2026-03-24 02:29
阅读 217

大家好,我是一名干了5年 Java 后端开发的老兵。这几年带过不少刚入行的新人,每次聊到微服务,他们总是一脸“这玩意儿太高深了吧”的表情。其实我当初学的时候也一样——第一次看到 Eureka、Ribbon、Feign 这些名词,以为自己要学外星语了。

但真相是:微服务的核心思想很简单,Spring Cloud 只是帮你把复杂的事情封装好了。今天我就用最直白的语言,手把手带你从零跑通一个 Spring Cloud 微服务项目。全程不讲虚的,只写你能跑起来的代码。

顺便说一句,虽然标题里提到了“爬虫”,但 Spring Cloud 本身和爬虫关系不大。不过别急——文章最后我会告诉你,为什么学完微服务后,你反而能写出更强大的分布式爬虫系统


一、微服务到底是什么?跟单体应用有啥区别?

先打个比方:

  • 单体应用(Monolith):就像一家小餐馆,老板一个人又炒菜、又收银、又打扫卫生。初期效率高,但客人一多就忙不过来。
  • 微服务(Microservices):变成连锁餐厅,厨房、前台、配送各司其职,互相通过对讲机沟通。虽然协调成本高了点,但扩展性强,某个环节出问题也不至于全店瘫痪。

在 Java 世界里:

  • 单体应用 = 一个 jar 包搞定所有功能(用户管理、订单、支付……全塞一起)
  • 微服务 = 拆成多个独立的 jar 包,每个只干一件事,彼此通过 HTTP 调用通信

Spring Cloud 的作用:提供一套工具,帮你解决微服务之间的“对讲机”怎么搭、服务挂了怎么办、配置怎么统一等问题。


二、环境准备:5分钟搭好开发环境

💡 建议使用 JDK 17 + Maven + IDEA(社区版即可)

必装软件清单

软件 版本建议 用途
JDK 17(LTS) Java 运行环境
Maven 3.8+ 项目依赖管理
IntelliJ IDEA 2022+ 开发 IDE
Postman 最新版 测试接口

创建父工程(关键!)

微服务项目通常由多个子模块组成,我们先建一个“空壳”父工程来统一管理依赖版本。

  1. 打开 IDEA → New Project → 选择 Maven(不选模板)
  2. 填写 GroupId:com.example,ArtifactId:springcloud-demo
  3. 删除 src 文件夹(父工程不需要代码)
  4. 修改 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>springcloud-demo</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging> <!-- 注意这里是 pom -->

    <!-- Spring Boot 和 Spring Cloud 版本管理 -->
    <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>
</project>

✅ 这一步很重要!后续所有子模块都会继承这个父 POM,避免版本冲突。


三、核心概念:三个服务,搞懂微服务骨架

我们要搭建三个基础服务:

  1. 服务注册中心(Eureka Server) → 相当于“电话簿”,记录所有服务的地址
  2. 用户服务(user-service) → 提供用户信息查询
  3. 订单服务(order-service) → 调用用户服务,组合数据返回

步骤1:创建 Eureka 注册中心

右键父工程 → New → Module → Maven
ArtifactId 填 eureka-server

修改它的 pom.xml,加入 Eureka 依赖:

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

创建启动类 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);
    }
}

添加配置文件 application.yml

server:
  port: 8761 # Eureka 默认端口

eureka:
  client:
    register-with-eureka: false # 不向自己注册
    fetch-registry: false       # 不拉取注册表
  server:
    wait-time-in-ms-when-sync-empty: 0

🚀 启动它!访问 http://localhost:8761 ,你会看到 Eureka 的管理界面(虽然现在还没服务注册)


步骤2:创建用户服务(Provider)

新建模块 user-service,依赖如下:

<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>

启动类(不用加特殊注解):

@SpringBootApplication
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

配置文件 application.yml

server:
  port: 8081

spring:
  application:
    name: user-service # 服务名,必须唯一!

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/ # 注册到 Eureka

写个简单 Controller:

@RestController
public class UserController {

    @GetMapping("/user/{id}")
    public Map<String, Object> getUser(@PathVariable Long id) {
        Map<String, Object> user = new HashMap<>();
        user.put("id", id);
        user.put("name", "张三");
        user.put("email", "zhangsan@example.com");
        return user;
    }
}

启动后刷新 Eureka 页面,你会看到 USER-SERVICE 出现在 Instances 列表中!


步骤3:创建订单服务(Consumer)

新建模块 order-service,依赖同 user-service

重点来了:如何调用 user-service?

传统方式:硬编码 URL(比如 http://localhost:8081/user/1)→ 一旦 IP 或端口变,全崩!

Spring Cloud 方案:用服务名代替 IP!

方法一:使用 RestTemplate + @LoadBalanced(推荐新手)

  1. 在启动类中注入 RestTemplate:
@SpringBootApplication
public class OrderServiceApplication {

    @Bean
    @LoadBalanced // 关键!开启负载均衡
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}
  1. 写 Controller 调用 user-service:
@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/order/{userId}")
    public Map<String, Object> getOrder(@PathVariable Long userId) {
        // 注意:这里用的是服务名 user-service,不是 IP!
        String url = "http://user-service/user/" + userId;
        Map user = restTemplate.getForObject(url, Map.class);

        Map<String, Object> order = new HashMap<>();
        order.put("orderId", "ORDER_001");
        order.put("user", user);
        return order;
    }
}

配置文件 application.yml

server:
  port: 8082

spring:
  application:
    name: order-service

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

✅ 启动 order-service,访问 http://localhost:8082/order/1
你会看到返回了包含用户信息的订单数据!整个调用链:
浏览器 → order-service → (通过 Eureka 发现) → user-service


四、常见问题解答(避坑指南)

❓ 问题1:启动报错 “Cannot execute request on any known server”

原因:Eureka 客户端找不到注册中心。
解决

  • 检查 defaultZone 地址是否正确(注意结尾的 /eureka/
  • 确保 Eureka Server 已先启动

❓ 问题2:调用服务时报 “UnknownHostException: user-service”

原因:RestTemplate 没加 @LoadBalanced 注解!
解决:务必在 Bean 定义上加上该注解,否则无法解析服务名。

❓ 问题3:服务启动了但在 Eureka 看不到?

排查步骤

  1. 检查客户端是否配置了 eureka.client.service-url.defaultZone
  2. 检查防火墙是否阻止了 8761 端口
  3. 查看控制台日志是否有注册成功的日志(关键词:Registered instance

五、关于“爬虫”和微服务的关系

你可能纳闷:说好的爬虫呢?

其实,微服务架构非常适合构建分布式爬虫系统!举个例子:

  • 你可以拆出一个 crawler-service 专门负责抓取网页
  • 一个 parser-service 负责解析 HTML 提取数据
  • 一个 storage-service 负责存入数据库

它们之间通过 Spring Cloud 通信,还能轻松横向扩展(比如部署 10 个 crawler 实例同时抓取)。而单体爬虫程序很难做到这种弹性。

我之前做的一个舆情监控系统,就是用 Spring Cloud + WebMagic(Java 爬虫框架)搭建的,每天处理百万级网页,稳得很!


六、下一步学什么?我的学习路线建议

你已经跑通了最基础的服务注册与发现。接下来可以按顺序深入:

  1. 服务调用升级:用 OpenFeign 替代 RestTemplate(声明式调用,代码更简洁)
  2. 服务容错:集成 Resilience4j 或 Sentinel,防止级联失败
  3. 配置中心:用 Nacos 或 Spring Cloud Config 统一管理配置
  4. 网关:用 Spring Cloud Gateway 做统一入口、限流、鉴权
  5. 链路追踪:集成 Sleuth + Zipkin,看清请求在哪些服务间流转

📌 记住:不要试图一口吃成胖子。先把今天这三个服务玩熟,再逐个添加新组件。


结语

微服务听起来高大上,但拆解开来,每一步都很简单。我当初也是从这样一个“Hello World 级”的 Eureka 项目开始,慢慢啃下来的。

技术没有魔法,只有清晰的逻辑和反复的实践。希望这篇教程能帮你跨过最初的那道坎。有问题欢迎留言,我会尽力解答!

最后提醒:代码一定要自己敲一遍!复制粘贴永远学不会。

评论 0

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