目录

1.SpringCloud介绍

2.项目整体结构搭建

3.搭建 Eureka 服务注册中心(servercenter1)

3.1 新建项目

3.2 在项目clouddemo1中新建模块servercenter1

3.3 修改模块servercenter1下的内容

3.3.1 配置 pom.xml 依赖

3.3.2 配置 application.properties

3.3.3 编写启动类 (Servercenter1Application.java)

3.3.4 启动并测试注册中心

4.搭建服务消费者(consumer)

4.1 在项目 clouddemo1 中新建模块 consumer (服务消费者)

4.2 修改模块servercenter1下的内容

4.2.1 配置 pom.xml 依赖

4.2.2 配置 application.properties

4.2.3 编写启动类 (ConsumerApplication.java)

4.2.4 编写远程调用控制器

4.2.5 实现消费者多实例部署

5.搭建服务生产者(proservice)

5.1 在项目 clouddemo1 中新建模块 proservice (服务生产者)

5.2 修改模块 proservice 下的内容

5.2.1 配置 pom.xml 依赖

5.2.2 配置 application.properties

5.2.3 编写业务接口控制器

5.2.4 编写启动类

5.2.5 实现生产者多实例部署

6.整体运行与测试

6.1 启动顺序

6.2 验证服务注册

6.3 验证远程调用与负载均衡

7.实战总结与核心要点


1.SpringCloud介绍

在分布式系统开发中,Spring Cloud 作为基于 Spring Boot 构建的微服务架构框架,提供了服务注册与发现、负载均衡、熔断降级等核心能力,能高效实现微服务的治理与管理。下文将搭建基于 Eureka 的服务注册中心,实现生产者(proservice)和消费者(consumer)的微服务调用,并完成客户端负载均衡的实战配置。

  • Eureka/Nacos:服务注册与发现中心,管理服务实例的注册和动态发现。 ‌
  • Ribbon:客户端负载均衡器,支持轮询等算法分配请求。 ‌
  • Hystrix:熔断与降级框架,防止服务雪崩。 ‌
  • Feign:声明式HTTP客户端,简化服务间调用。 ‌
  • Config Server:集中化配置管理,支持动态更新。

Spring Cloud是对Spring Boot的一个微服务治理(管理)的一个框架。

2.项目整体结构搭建

本次实战基于空 Maven 项目clouddemo1搭建,在主项目下创建三个子模块,分别对应注册中心、生产者、消费者,整体项目结构如下:

clouddemo1(父项目)
├─ servercenter1(Eureka服务注册中心,端口8855)
├─ proservice(服务生产者,端口9091/9092,多实例)
└─ consumer(服务消费者,端口9001/9002,多实例)

3.搭建 Eureka 服务注册中心(servercenter1)

Eureka 作为微服务架构的 “注册中心”,是所有服务的核心枢纽,负责接收服务实例的注册请求,并为消费者提供服务发现能力。

3.1 新建项目

3.2 在项目clouddemo1中新建模块servercenter1

3.3 修改模块servercenter1下的内容

3.3.1 配置 pom.xml 依赖

引入Eureka Server核心依赖,同时继承 Spring Boot 父工程,配置 Spring Cloud 版本管理:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>
    <groupId>com.hy</groupId>
    <artifactId>servercenter1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>servercenter1</name>
    <description>Eureka服务注册中心</description>

    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2021.0.8</spring-cloud.version>
    </properties>

    <dependencies>
        <!-- Spring Boot核心依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Eureka Server核心依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <!-- Spring Cloud版本管理 -->
    <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>

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

3.3.2 配置 application.properties

配置 Eureka 服务端核心参数,指定服务名、端口,关闭自身注册与发现(注册中心无需注册自己):

# 服务名称
spring.application.name=servercenter1
# 服务端口
server.port=8855
# Eureka实例主机名
eureka.instance.hostname=localhost
# 关闭注册中心自身注册到Eureka
eureka.client.register-with-eureka=false
# 关闭注册中心从Eureka发现服务
eureka.client.fetch-registry=false
# Eureka注册中心地址
eureka.client.service-url.defaultZone = http://${eureka.instance.hostname}:${server.port}/eureka

3.3.3 编写启动类 (Servercenter1Application.java)

在启动类上添加@EnableEurekaServer注解,标记该应用为 Eureka 服务注册中心,配合@SpringBootApplication开启 Spring Boot 自动配置:

package com.hy.servercenter1;

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

@EnableEurekaServer // 开启Eureka服务端功能
@SpringBootApplication
public class Servercenter1Application {
    public static void main(String[] args) {
        SpringApplication.run(Servercenter1Application.class, args);
    }
}

3.3.4 启动并测试注册中心

运行启动类,访问http://127.0.0.1:8855,即可进入 Eureka 控制台。此时控制台显示No instances available,说明注册中心启动成功,暂无服务实例注册。

4.搭建服务消费者(consumer)

消费者作为微服务的调用方,通过 Eureka 发现生产者服务,通过RestTemplate发起远程调用,本次将搭建消费者并实现多实例部署。

4.1 在项目 clouddemo1 中新建模块 consumer (服务消费者)

4.2 修改模块servercenter1下的内容

4.2.1 配置 pom.xml 依赖

引入Eureka Client依赖(消费者作为 Eureka 客户端,需注册到注册中心),同时保留 Spring Boot 核心依赖:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>
    <groupId>com.hy</groupId>
    <artifactId>consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>consumer</name>
    <description>服务消费者</description>

    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2021.0.8</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Eureka Client依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- Web依赖,提供HTTP接口能力 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

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

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

4.2.2 配置 application.properties

配置消费者服务名、端口,指定 Eureka 注册中心地址,将消费者注册到 Eureka:

# 服务名称(核心,消费者通过该名称注册,生产者通过服务名调用)
spring.application.name=consumer
# 服务端口
server.port=9001
# 注册到Eureka的地址(与注册中心配置一致)
eureka.client.service-url.defaultZone=http://127.0.0.1:8855/eureka

4.2.3 编写启动类 (ConsumerApplication.java)

添加@EnableDiscoveryClient注解开启服务发现能力,配置RestTemplate并添加@LoadBalanced注解开启客户端负载均衡:

package com.hy.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient // 开启服务发现能力
@SpringBootApplication
public class ConsumerApplication {

    //RPC机制,远程过程调用机制,分布式调用
    //Springcloud内置rest远程调用   openfeign调用机制
    // 配置RestTemplate Bean,实现远程调用
    @Bean   //这个方法的对象实例化
    @LoadBalanced  // 开启客户端负载均衡,支持通过服务名调用
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

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

}

4.2.4 编写远程调用控制器

创建controller包,编写UserController,通过RestTemplate调用生产者proservice/querydata接口,对外提供/loaddatas访问接口:

package com.hy.consumer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class UserController {

    // 注入配置好的RestTemplate
    @Autowired
    private RestTemplate restTemplate;

    // 对外暴露的调用接口
    @RequestMapping("/loaddatas")
    public String loadDatas() {
        System.out.println("UserController  is  loadDatas  start...");
        // 核心:通过服务名proservice调用,而非IP+端口,由Eureka和负载均衡自动解析
        String result = this.restTemplate.getForObject("http://proservice/querydata", String.class);
        System.out.println("微服务调用的机制的结果为 :" + result);
        return result;
    }
}

4.2.5 实现消费者多实例部署

在 IDEA 中开启允许多个实例运行:点击运行配置 -> 勾选Allow multiple instances,修改application.propertiesserver.port为 9002,再次启动即可实现消费者 9001、9002 两个实例同时运行,且均注册到 Eureka。

# 服务名称(核心,消费者通过该名称注册,生产者通过服务名调用)
spring.application.name=consumer
# 服务端口
server.port=9002
# 注册到Eureka的地址(与注册中心配置一致)
eureka.client.service-url.defaultZone=http://127.0.0.1:8855/eureka

启动后访问 Eureka 控制台,可看到CONSUMER服务下有两个实例,状态为UP,说明消费者注册成功。

5.搭建服务生产者(proservice)

生产者作为微服务的提供方,负责提供具体的业务接口,注册到 Eureka 后被消费者发现并调用,本次实现生产者的接口开发与多实例部署,并配置负载均衡依赖。

5.1 在项目 clouddemo1 中新建模块 proservice (服务生产者)

5.2 修改模块 proservice 下的内容

5.2.1 配置 pom.xml 依赖

引入Eureka Clientspring-boot-starter-web(提供接口能力)、spring-cloud-starter-loadbalancer(负载均衡核心依赖):

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>
    <groupId>com.hy</groupId>
    <artifactId>proservice</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>proservice</name>
    <description>服务生产者</description>

    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2021.0.8</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Eureka Client依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- Web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 负载均衡依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>

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

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

5.2.2 配置 application.properties

配置生产者服务名、端口,注册到 Eureka,服务名proservice需与消费者调用的服务名完全一致:

# 服务名称(与消费者调用的服务名一致,核心)
spring.application.name=proservice
# 服务端口
server.port=9091
# 注册到Eureka的地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8855/eureka

5.2.3 编写业务接口控制器

创建controller包,编写DataController,提供/querydata接口,返回随机数模拟业务数据:

package com.hy.proservice.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Random;

@RestController
public class DataController {

    // 生产者提供的核心接口,被消费者调用
    @RequestMapping("/querydata")
    public String queryData() {
        System.out.println("DataController  is  queryData  start....");
        Random r = new Random();
        // 生成0-999的随机数,模拟业务返回结果
        String value = String.valueOf(r.nextInt(1000));
        System.out.println("产生的随机数为:" + value);
        return value;
    }
}

5.2.4 编写启动类

添加@EnableDiscoveryClient注解,开启服务注册与发现能力,无需额外配置,Spring Boot 自动扫描控制器:

package com.hy.proservice;

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

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

5.2.5 实现生产者多实例部署

与消费者配置一致,勾选 IDEA 运行配置的Allow multiple instances,修改server.port为 9092,再次启动即可实现生产者 9091、9092 两个实例运行,注册到 Eureka 后,消费者可通过负载均衡调用两个实例。

spring.application.name=proservice

server.port= 9092
eureka.client.service-url.defaultZone=http://127.0.0.1:8855/eureka

6.整体运行与测试

6.1 启动顺序

微服务启动需遵循依赖顺序,确保注册中心先启动,再启动生产者和消费者:

  • 启动 Eureka 注册中心(servercenter1,8855);
  • 启动生产者两个实例(proservice,9091/9092);
  • 启动消费者实例(consumer,9002)。

6.2 验证服务注册

访问 Eureka 控制台http://127.0.0.1:8855,可看到CONSUMERPROSERVICE服务均为UP状态,且 PROSERVICE 有 2 个实例,说明所有服务注册成功。

6.3 验证远程调用与负载均衡

访问消费者的/loaddatas接口:http://localhost:9002/loaddatas,页面会返回一个随机数,同时观察控制台:

  • 消费者控制台打印UserController is loadDatas start... 和调用结果;
  • 生产者控制台打印DataController is queryData start.... 和生成的随机数;
  • 多次刷新接口,生产者 9091 和 9092 实例会交替打印日志,说明客户端负载均衡生效,请求在两个生产者实例间轮询分发。

7.实战总结与核心要点

本次实战完成了 Spring Cloud 基于 Eureka 的微服务架构搭建,实现了服务注册、发现、远程调用和负载均衡,核心要点总结如下:

  • Eureka 核心区分:服务端添加@EnableEurekaServer,客户端添加@EnableDiscoveryClient,注册中心需关闭自身注册与发现;
  • 服务名一致性:生产者的spring.application.name必须与消费者调用的服务名完全一致,否则无法发现服务;
  • 负载均衡开启RestTemplate必须添加@LoadBalanced注解,否则无法通过服务名调用,只能使用 IP + 端口;
  • 多实例部署:IDEA 中勾选Allow multiple instances,修改端口即可实现多实例,Eureka 会自动识别并实现负载均衡;
  • 依赖正确性:生产者和消费者作为 Eureka 客户端,需引入eureka-client依赖,而非eureka-server依赖,同时需添加spring-boot-starter-web提供接口能力。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐