跳到主要内容
Spring Boot 微服务架构设计与实战 | 极客日志
Java java
Spring Boot 微服务架构设计与实战 综述由AI生成 本文详细阐述了 Spring Boot 微服务架构的设计与实现路径。内容涵盖微服务核心概念、基于 Eureka 的服务注册与发现机制、Config Server 配置中心搭建、以及利用 Ribbon 实现服务间负载均衡通信。通过提供注册中心、服务提供者与消费者的完整代码示例,展示了从依赖引入、配置编写到启动运行的全流程,为实际开发中构建高可用微服务系统提供了清晰的实战参考。
云朵棉花糖 发布于 2026/3/25 更新于 2026/5/13 8 浏览Spring Boot 微服务架构设计与实战
学习目标与重点提示
本章我们将深入掌握 Spring Boot 微服务架构的核心概念与落地方法。内容涵盖微服务的定义与特性、Spring Boot 与微服务框架的集成方式、配置管理方案以及实际开发中的常见场景。
核心重点 :
微服务架构的定义与特点
Spring Boot 与微服务的集成(以 Eureka 为例)
配置中心的使用
服务间通信的基本方法
实际应用场景分析
微服务架构概述
在 Java 生态中,微服务架构已成为构建大型应用的主流选择。
什么是微服务?
简单来说,微服务是一种将应用程序拆分为一组独立服务的架构风格。每个服务运行在自己的进程中,通过轻量级机制(通常是 HTTP API)进行通信。
这种架构的主要优势在于:
可扩展性 :可以根据负载单独扩展特定服务。
可维护性 :代码库更小,团队可以独立迭代。
可靠性 :单个服务的故障不会导致整个系统崩溃。
常见的技术栈包括 Spring Cloud、Netflix OSS、Docker 容器化技术以及 Kubernetes 编排工具等。
核心特点
独立部署 :每个服务可以独立发布,互不影响。
独立开发 :不同团队可以使用各自偏好的语言或框架开发。
独立运行 :服务进程隔离,资源占用可控。
网络通信 :依赖服务发现与负载均衡机制。
Spring Boot 与微服务的集成
集成 Spring Cloud Eureka 是实现服务注册与发现的关键步骤。下面我们通过一个完整的示例来演示如何搭建服务注册中心、服务提供者和服务消费者。
1. 搭建服务注册中心 (Eureka Server)
首先创建 Spring Boot 项目,并引入必要的依赖。在 pom.xml 中添加 Eureka Server 依赖和版本管理:
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-starter-netflix-eureka-server</artifactId >
</ >
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
Hoxton.SR12
pom
import
dependency
<dependency >
<groupId >
</groupId >
<artifactId >
</artifactId >
<scope >
</scope >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId >
</groupId >
<artifactId >
</artifactId >
<version >
</version >
<type >
</type >
<scope >
</scope >
</dependency >
</dependencies >
</dependencyManagement >
接着配置 application.properties,关闭自我注册功能,使其仅作为注册中心:
# 服务器端口
server.port=8761
# Eureka Server 配置
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=localhost
启动类需要添加 @EnableEurekaServer 注解:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main (String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
2. 创建服务提供者 (Product Service) 服务提供者需要注册到 Eureka 中心。同样引入 spring-cloud-starter-netflix-eureka-client 依赖。
# 服务器端口
server.port=8081
# 应用名称
spring.application.name=product-service
# Eureka Client 配置
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.instance.prefer-ip-address=true
public class Product {
private Long id;
private String productId;
private String productName;
private double price;
private int sales;
@Override
public String toString () {
return "Product{" +
"id=" + id +
", productId='" + productId + '\'' +
", productName='" + productName + '\'' +
", price=" + price +
", sales=" + sales +
'}' ;
}
}
控制器 ProductController 提供 RESTful 接口:
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/products")
public class ProductController {
private List<Product> products = new ArrayList <>();
public ProductController () {
products.add(new Product (1L , "P001" , "手机" , 1000.0 , 100 ));
products.add(new Product (2L , "P002" , "电脑" , 5000.0 , 50 ));
products.add(new Product (3L , "P003" , "电视" , 3000.0 , 80 ));
products.add(new Product (4L , "P004" , "手表" , 500.0 , 200 ));
products.add(new Product (5L , "P005" , "耳机" , 300.0 , 150 ));
}
@GetMapping("/")
public List<Product> getAllProducts () {
return products;
}
@GetMapping("/{id}")
public Product getProductById (@PathVariable Long id) {
return products.stream()
.filter(product -> product.getId().equals(id))
.findFirst()
.orElse(null );
}
@PostMapping("/")
public Product addProduct (@RequestBody Product product) {
product.setId((long ) (products.size() + 1 ));
products.add(product);
return product;
}
@PutMapping("/{id}")
public Product updateProduct (@PathVariable Long id, @RequestBody Product product) {
Product existingProduct = getProductById(id);
if (existingProduct != null ) {
existingProduct.setProductId(product.getProductId());
existingProduct.setProductName(product.getProductName());
existingProduct.setPrice(product.getPrice());
existingProduct.setSales(product.getSales());
}
return existingProduct;
}
@DeleteMapping("/{id}")
public void deleteProduct (@PathVariable Long id) {
products.removeIf(product -> product.getId().equals(id));
}
}
启动类需添加 @EnableEurekaClient:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main (String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
3. 创建服务消费者 (Order Service) 消费者服务同样需要注册到 Eureka,并引入 Ribbon 依赖以实现负载均衡。
server.port=8082
spring.application.name=order-service
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.instance.prefer-ip-address=true
public class Order {
private Long id;
private String orderId;
private List<Product> products;
@Override
public String toString () {
return "Order{" +
"id=" + id +
", orderId='" + orderId + '\'' +
", products=" + products +
'}' ;
}
}
控制器中使用 RestTemplate 调用上游服务:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
private List<Order> orders = new ArrayList <>();
public OrderController () {
orders.add(new Order (1L , "O001" , new ArrayList <>()));
orders.add(new Order (2L , "O002" , new ArrayList <>()));
orders.add(new Order (3L , "O003" , new ArrayList <>()));
}
@Bean
@LoadBalanced
public RestTemplate restTemplate () {
return new RestTemplate ();
}
@GetMapping("/")
public List<Order> getAllOrders () {
return orders;
}
@GetMapping("/{id}")
public Order getOrderById (@PathVariable Long id) {
return orders.stream()
.filter(order -> order.getId().equals(id))
.findFirst()
.orElse(null );
}
@PostMapping("/")
public Order addOrder (@RequestBody Order order) {
order.setId((long ) (orders.size() + 1 ));
orders.add(order);
return order;
}
@PutMapping("/{id}")
public Order updateOrder (@PathVariable Long id, @RequestBody Order order) {
Order existingOrder = getOrderById(id);
if (existingOrder != null ) {
existingOrder.setOrderId(order.getOrderId());
existingOrder.setProducts(order.getProducts());
}
return existingOrder;
}
@DeleteMapping("/{id}")
public void deleteOrder (@PathVariable Long id) {
orders.removeIf(order -> order.getId().equals(id));
}
@GetMapping("/{id}/products")
public List<Product> getOrderProducts (@PathVariable Long id) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products;
}
return new ArrayList <>();
}
@PostMapping("/{id}/products")
public Order addOrderProduct (@PathVariable Long id, @RequestBody Product product) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().add(product);
}
return order;
}
@DeleteMapping("/{id}/products/{productId}")
public Order deleteOrderProduct (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().removeIf(product -> product.getId().equals(productId));
}
return order;
}
@GetMapping("/{id}/product/{productId}")
public Product getProductById (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products.stream()
.filter(product -> product.getId().equals(productId))
.findFirst()
.orElse(null );
}
return null ;
}
}
启动类同样添加 @EnableEurekaClient。
4. 测试验证 import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderServiceApplicationTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
void contextLoads () {}
@Test
void testGetAllOrders () {
List<Order> orders = restTemplate.getForObject("http://localhost:" + port + "/api/orders/" , List.class);
assertThat(orders).isNotNull();
assertThat(orders.size()).isGreaterThanOrEqualTo(3 );
}
@Test
void testAddOrder () {
Order order = new Order (null , "O004" , new ArrayList <>());
Order savedOrder = restTemplate.postForObject("http://localhost:" + port + "/api/orders/" , order, Order.class);
assertThat(savedOrder).isNotNull();
assertThat(savedOrder.getOrderId()).isEqualTo("O004" );
}
@Test
void testAddOrderProduct () {
Product product = new Product (1L , "P001" , "手机" , 1000.0 , 100 );
HttpEntity<Product> requestEntity = new HttpEntity <>(product);
ResponseEntity<Order> response = restTemplate.exchange(
"http://localhost:" + port + "/api/orders/1/products" ,
HttpMethod.POST,
requestEntity,
Order.class
);
assertThat(response.getStatusCodeValue()).isEqualTo(200 );
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getProducts().size()).isGreaterThanOrEqualTo(1 );
}
}
Spring Boot 与微服务的配置 集中化管理配置是微服务架构的重要环节,Spring Cloud Config 提供了完善的解决方案。
配置 Config Server 创建配置服务器项目,引入 spring-cloud-config-server 依赖。
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/username/config-repo
spring.cloud.config.server.git.search-paths=config-repo
spring.cloud.config.server.git.username=username
spring.cloud.config.server.git.password=password
启动类添加 @EnableConfigServer。
配置客户端 客户端服务引入 spring-cloud-starter-config 依赖。
在 bootstrap.properties 中指定配置中心地址:
spring.application.name=product-service
spring.cloud.config.uri=http://localhost:8888
具体的业务配置(如数据库连接)则放在 Git 仓库的 product-service-dev.properties 文件中:
spring.application.name=product-service
server.port=8081
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
这样,当服务启动时,会自动从配置中心拉取最新的配置信息,无需修改本地文件。
Spring Boot 与微服务的基本方法 服务间的通信通常涉及负载均衡和熔断机制。这里主要介绍 Ribbon 的使用。
使用 Ribbon Ribbon 是客户端负载均衡器,配合 RestTemplate 使用非常方便。在消费者服务中,我们已经在 OrderController 中定义了 @LoadBalanced 的 RestTemplate Bean。这样在调用服务时,只需使用服务名(如 http://product-service/api/products),Ribbon 会自动根据注册中心的信息选择实例进行请求。
Spring Boot 的实际应用场景 在实际开发中,Spring Boot 微服务架构的应用非常广泛,典型场景包括:
产品服务微服务化 :将商品管理独立部署,便于库存与价格调整。
用户服务微服务化 :统一认证授权,支持多端登录。
订单服务微服务化 :处理复杂的交易流程,保证数据一致性。
支付服务微服务化 :对接第三方支付渠道,隔离风险。
通过上述示例,我们可以看到各个服务如何通过 Eureka 注册发现,通过 Config Server 统一管理配置,并通过 RestTemplate 完成业务交互。
总结 本章我们梳理了 Spring Boot 微服务架构的设计思路与实现细节。从微服务的基础概念出发,深入讲解了 Eureka 服务注册与发现、Config Server 配置中心、以及基于 Ribbon 的服务间通信。掌握了这些核心组件后,就能在实际项目中灵活应对微服务架构带来的挑战,构建高可用、易扩展的系统架构。后续章节我们将继续探索 Spring Boot 的其他组件及更高级的微服务特性。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online