Spring Cloud 入门:构建微服务架构的强大工具

今天我们来深入探讨 Spring Cloud,一个基于 Spring Boot 的微服务框架集合。Spring Cloud 提供了服务发现、配置管理、负载均衡、分布式追踪等功能,极大简化了微服务架构的开发和部署。本文将带你从零搭建一个简单的 Spring Cloud 微服务系统,包含服务注册与发现,适合初学者快速上手,同时为有经验的开发者提供进阶建议和优化思路。

Spring Cloud 集成了一系列工具(如 Eureka、Config Server),适合构建分布式系统。本文基于 Spring Cloud 2023.x(Hoxton 或最新版),使用 Spring Boot 3.x、Java 17 和 Maven,结合 Eureka 实现服务注册与发现。让我们开始吧!

前置准备

在开始之前,确保开发环境已就绪:

  • JDK:推荐 JDK 17(Spring Boot 3.x 要求 JDK 17+,2.x 支持 JDK 8+)。
  • Maven:用于依赖管理,确保配置好环境变量。
  • IDE:IntelliJ IDEA 或 VS Code,推荐使用 Spring Initializr 插件。
  • 工具:Postman 或 curl 用于测试 API。
  • 项目结构:创建两个项目(Eureka Server 和 User Service),目录如下:
    spring-cloud-demo
    ├── eureka-server
    │   ├── src
    │   │   ├── main
    │   │   │   ├── java/com/example/eureka
    │   │   │   └── resources/application.yml
    │   └── pom.xml
    ├── user-service
    │   ├── src
    │   │   ├── main
    │   │   │   ├── java/com/example/user
    │   │   │   │   ├── controller
    │   │   │   │   └── model
    │   │   │   └── resources/application.yml
    │   └── pom.xml
    

推荐使用 Spring Initializr 生成项目:

  • Eureka Server:依赖 Spring Cloud Netflix Eureka Server。
  • User Service:依赖 Spring Cloud Netflix Eureka Client, Spring Web。

步骤 1: 创建 Eureka Server

Eureka Server 负责服务注册与发现。

Maven 依赖

eureka-server/pom.xml

<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>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version>
        <relativePath/>
    </parent>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2023.0.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

配置 Eureka Server

eureka-server/src/main/resources/application.yml

server:
  port: 8761

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
  server:
    enable-self-preservation: false

主应用类

eureka-server/src/main/java/com/example/eureka/EurekaApplication.java

package com.example.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

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

说明

  • @EnableEurekaServer:启用 Eureka 服务注册中心。
  • port: 8761:默认 Eureka 端口。
  • register-with-eureka: false:防止 Eureka Server 注册自身。

步骤 2: 创建 User Service

User Service 是一个微服务,注册到 Eureka 并提供 REST API。

Maven 依赖

user-service/pom.xml

<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>user-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version>
        <relativePath/>
    </parent>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2023.0.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

配置 User Service

user-service/src/main/resources/application.yml

server:
  port: 8081

spring:
  application:
    name: user-service

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

用户模型

user-service/src/main/java/com/example/user/model/User.java

package com.example.user.model;

public class User {
    private Long id;
    private String name;
    private Integer age;

    public User() {}
    public User(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

控制器

user-service/src/main/java/com/example/user/controller/UserController.java

package com.example.user.controller;

import com.example.user.model.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {
    private List<User> users = Arrays.asList(
        new User(1L, "Alice", 25),
        new User(2L, "Bob", 30)
    );

    @GetMapping
    public List<User> getAllUsers() {
        return users;
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return users.stream()
            .filter(user -> user.getId().equals(id))
            .findFirst()
            .orElse(null);
    }
}

主应用类

user-service/src/main/java/com/example/user/UserApplication.java

package com.example.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

说明

  • @EnableDiscoveryClient:启用 Eureka 客户端,注册到 Eureka Server。
  • spring.application.name:服务名称,Eureka 识别用。

步骤 3: 运行和测试

  1. 启动 Eureka Server

    cd eureka-server
    mvn spring-boot:run
    

    访问 http://localhost:8761,查看 Eureka 仪表板。

  2. 启动 User Service

    cd user-service
    mvn spring-boot:run
    

    在 Eureka 仪表板确认 user-service 注册成功。

  3. 测试 API

    • GET http://localhost:8081/api/users:列出所有用户。
    • GET http://localhost:8081/api/users/1:获取 ID 为 1 的用户。
  4. 调试技巧

    • Eureka 未注册:检查 application.ymlservice-url
    • 端口冲突:修改 server.port 或检查占用。
    • 日志:查看 eureka-serveruser-service 的控制台日志。

步骤 4: 添加负载均衡(可选)

为 User Service 运行多个实例,模拟负载均衡。

  1. 复制 user-service 目录,修改端口:

    server:
      port: 8082
    
  2. 启动第二个实例:

    cd user-service-2
    mvn spring-boot:run
    
  3. 使用 RestTemplateWebClient 调用服务(需额外客户端项目):

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    

进阶与最佳实践

  • 配置中心

    • 使用 Spring Cloud Config:
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-config</artifactId>
      </dependency>
      
  • 网关

    • 集成 Spring Cloud Gateway:
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-gateway</artifactId>
      </dependency>
      
  • 分布式追踪

    • 使用 Spring Cloud Sleuth 和 Zipkin:
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-sleuth</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-zipkin</artifactId>
      </dependency>
      
  • 容器化
    创建 Dockerfile

    FROM openjdk:17-jdk-slim
    WORKDIR /app
    COPY target/*.jar app.jar
    EXPOSE 8080
    ENTRYPOINT ["java", "-jar", "app.jar"]
    
  • 资源推荐:Spring Cloud 官网(spring.io/projects/spring-cloud)、《Spring Microservices in Action》。多实践服务调用和配置管理。

总结

通过这个 Spring Cloud 示例,你学会了搭建 Eureka 服务注册中心和微服务,实现了服务注册与发现。Spring Cloud 的模块化工具简化了微服务开发,适合分布式系统。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐