Spring Boot 3微服务架构:构建企业级分布式系统实战

# Spring Boot 3微服务架构:构建企业级分布式系统实战


在数字化转型浪潮中,企业级应用对高可用、可扩展架构的需求日益迫切。基于Spring Boot 3的微服务架构,通过现代化的技术栈和设计模式,为构建分布式系统提供了完整的解决方案。


## 微服务基础架构设计


Spring Boot 3配合Spring Cloud 2022.x,构建了完整的微服务生态系统。


```java

// 服务注册与发现配置

// discovery-service/src/main/java/com/example/discovery/DiscoveryApplication.java

@SpringBootApplication

@EnableEurekaServer

public class DiscoveryApplication {

    public static void main(String[] args) {

        SpringApplication.run(DiscoveryApplication.class, args);

    }

}


// application-discovery.yml

server:

  port: 8761


eureka:

  instance:

    hostname: localhost

  client:

    register-with-eureka: false

    fetch-registry: false

    service-url:

      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

  server:

    enable-self-preservation: false

    renewal-percent-threshold: 0.85


spring:

  application:

    name: discovery-service

  security:

    user:

      name: admin

      password: ${DISCOVERY_PASSWORD:admin123}

```


## 配置中心与服务治理


```java

// config-service/src/main/java/com/example/config/ConfigApplication.java

@SpringBootApplication

@EnableConfigServer

public class ConfigApplication {

    public static void main(String[] args) {

        SpringApplication.run(ConfigApplication.class, args);

    }

}


// application-config.yml

server:

  port: 8888


spring:

  application:

    name: config-service

  profiles:

    active: native

  cloud:

    config:

      server:

        native:

          search-locations: classpath:/config-repo

        encrypt:

          enabled: true

        bootstrap: true


encrypt:

  key: ${CONFIG_ENCRYPT_KEY:changeme}


# Git仓库配置(可选)

# spring:

#   cloud:

#     config:

#       server:

#         git:

#           uri: https://github.com/your-repo/config-repo

#           search-paths: '{application}'

#           default-label: main


// config-repo/application-common.yml

# 公共配置

spring:

  datasource:

    url: jdbc:mysql://${DB_HOST:localhost}:3306/${DB_NAME:microservice}?useSSL=false&serverTimezone=UTC

    username: ${DB_USER:root}

    password: ${DB_PASSWORD:password}

    hikari:

      maximum-pool-size: 20

      minimum-idle: 5

      connection-timeout: 30000

      idle-timeout: 600000

      max-lifetime: 1800000

  

  jpa:

    hibernate:

      ddl-auto: update

    show-sql: true

    properties:

      hibernate:

        dialect: org.hibernate.dialect.MySQL8Dialect

        format_sql: true

  

  redis:

    host: ${REDIS_HOST:localhost}

    port: ${REDIS_PORT:6379}

    password: ${REDIS_PASSWORD:}

    timeout: 5000ms

    lettuce:

      pool:

        max-active: 20

        max-idle: 10

        min-idle: 5

        max-wait: -1ms


# Spring Cloud配置

eureka:

  client:

    service-url:

      defaultZone: http://${EUREKA_HOST:localhost}:8761/eureka/

  instance:

    prefer-ip-address: true

    instance-id: ${spring.application.name}:${spring.application.instance-id:${random.value}}


# 熔断器配置

resilience4j:

  circuitbreaker:

    instances:

      default:

        register-health-indicator: true

        sliding-window-size: 10

        minimum-number-of-calls: 5

        permitted-number-of-calls-in-half-open-state: 3

        automatic-transition-from-open-to-half-open-enabled: true

        wait-duration-in-open-state: 5s

        failure-rate-threshold: 50

        event-consumer-buffer-size: 10

  

  retry:

    instances:

      default:

        max-attempts: 3

        wait-duration: 1s

        retry-exceptions:

          - org.springframework.web.client.HttpServerErrorException

          - java.net.ConnectException

  

  bulkhead:

    instances:

      default:

        max-concurrent-calls: 25

        max-wait-duration: 0


# Sleuth链路追踪

spring:

  sleuth:

    enabled: true

    sampler:

      probability: 1.0

    propagation:

      type: B3

  zipkin:

    base-url: http://${ZIPKIN_HOST:localhost}:9411/


# 监控配置

management:

  endpoints:

    web:

      exposure:

        include: health,info,metrics,prometheus

  endpoint:

    health:

      show-details: always

  metrics:

    export:

      prometheus:

        enabled: true

    distribution:

      percentiles-histogram:

        http.server.requests: true

  tracing:

    sampling:

      probability: 0.1

```


## 业务微服务实现


```java

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

@SpringBootApplication

@EnableDiscoveryClient

@EnableFeignClients

@EnableCircuitBreaker

public class UserApplication {

    public static void main(String[] args) {

        SpringApplication.run(UserApplication.class, args);

    }

}


// UserController.java - 用户服务API

@RestController

@RequestMapping("/api/v1/users")

@RequiredArgsConstructor

@Slf4j

public class UserController {

    

    private final UserService userService;

    private final OrderServiceClient orderServiceClient;

    private final CircuitBreakerFactory circuitBreakerFactory;

    private final Tracer tracer;

    

    @Operation(summary = "获取用户详情")

    @GetMapping("/{userId}")

    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")

    public ResponseEntity getUserDetail(@PathVariable Long userId) {

        UserDTO user = userService.getUserById(userId);

        return ResponseEntity.ok(user);

    }

    

    @Operation(summary = "获取用户订单")

    @GetMapping("/{userId}/orders")

    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")

    public ResponseEntity> getUserOrders(@PathVariable Long userId) {

        // 使用熔断器包装外部调用

        CircuitBreaker circuitBreaker = circuitBreakerFactory.create("orderService");

        

        List orders = circuitBreaker.run(

            () -> orderServiceClient.getUserOrders(userId),

            throwable -> {

                log.error("获取用户订单失败,使用降级策略", throwable);

                return Collections.emptyList();

            }

        );

        

        // 添加链路追踪信息

        Span span = tracer.nextSpan().name("user-orders-query").start();

        try (Tracer.SpanInScope ws = tracer.withSpan(span)) {

            span.tag("user.id", userId.toString());

            span.tag("order.count", String.valueOf(orders.size()));

        } finally {

            span.end();

        }

        

        return ResponseEntity.ok(orders);

    }

    

    @Operation(summary = "创建用户")

    @PostMapping

    @PreAuthorize("hasRole('ADMIN')")

    public ResponseEntity createUser(@Valid @RequestBody CreateUserDTO createDTO) {

        UserDTO user = userService.createUser(createDTO);

        return ResponseEntity.status(HttpStatus.CREATED)

                .header("Location", "/api/v1/users/" + user.getId())

                .body(user);

    }

    

    @Operation(summary = "批量用户查询")

    @GetMapping("/batch")

    public ResponseEntity> getUsersBatch(@RequestParam List userIds) {

        // 使用并行流提高查询性能

        List> futures = userIds.stream()

            .map(userId -> CompletableFuture.supplyAsync(

                () -> userService.getUserById(userId),

                userService.getExecutor()

            ))

            .collect(Collectors.toList());

        

        List users = futures.stream()

            .map(CompletableFuture::join)

            .filter(Objects::nonNull)

            .collect(Collectors.toList());

        

        return ResponseEntity.ok(users);

    }

}


// UserService.java - 用户服务业务逻辑

@Service

@RequiredArgsConstructor

@Slf4j

public class UserService {

    

    private final UserRepository userRepository;

    private final RoleRepository roleRepository;

    private final PasswordEncoder passwordEncoder;

    private final CacheManager cacheManager;

    private final EventPublisher eventPublisher;

    private final RetryTemplate retryTemplate;

    

    @Transactional

    public UserDTO createUser(CreateUserDTO createDTO) {

        // 检查用户名是否已存在

        if (userRepository.existsByUsername(createDTO.getUsername())) {

            throw new BusinessException("用户名已存在");

        }

        

        // 检查邮箱是否已注册

        if (userRepository.existsByEmail(createDTO.getEmail())) {

            throw new BusinessException("邮箱已被注册");

        }

        

        // 创建用户实体

        User user = User.builder()

                .username(createDTO.getUsername())

                .password(passwordEncoder.encode(createDTO.getPassword()))

                .email(createDTO.getEmail())

                .phone(createDTO.getPhone())

                .status(UserStatus.ACTIVE)

                .build();

        

        // 分配默认角色

        Role userRole = roleRepository.findByName("ROLE_USER")

                .orElseThrow(() -> new ResourceNotFoundException("默认角色不存在"));

        user.addRole(userRole);

        

        // 使用重试机制保存用户

        User savedUser = retryTemplate.execute(context -> {

            log.info("保存用户,重试次数: {}", context.getRetryCount());

            return userRepository.save(user);

        });

        

        // 清除缓存

        evictUserCache(savedUser.getId(), savedUser.getUsername());

        

        // 发布用户创建事件

        eventPublisher.publishEvent(new UserCreatedEvent(

            savedUser.getId(),

            savedUser.getUsername(),

            savedUser.getEmail()

        ));

        

        log.info("用户创建成功: {}", savedUser.getUsername());

        

        return UserMapper.INSTANCE.toDTO(savedUser);

    }

    

    @Cacheable(value = "users", key = "#userId")

    public UserDTO getUserById(Long userId) {

        return userRepository.findById(userId)

                .map(UserMapper.INSTANCE::toDTO)

                .orElseThrow(() -> new ResourceNotFoundException("用户不存在"));

    }

    

    @Cacheable(value = "users", key = "#username")

    public UserDTO getUserByUsername(String username) {

        return userRepository.findByUsername(username)

                .map(UserMapper.INSTANCE::toDTO)

                .orElseThrow(() -> new ResourceNotFoundException("用户不存在"));

    }

    <"b3.p5k3.org.cn"><"r9.p5k3.org.cn"><"k2.p5k3.org.cn">

    @Caching(evict = {

        @CacheEvict(value = "users", key = "#userId"),

        @CacheEvict(value = "users", key = "#username")

    })

    public void evictUserCache(Long userId, String username) {

        log.debug("清除用户缓存: userId={}, username={}", userId, username);

    }

    

    @Async("userTaskExecutor")

    public CompletableFuture getUserByIdAsync(Long userId) {

        return CompletableFuture.completedFuture(getUserById(userId));

    }

    

    @Bean("userTaskExecutor")

    public Executor userTaskExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        executor.setCorePoolSize(5);

        executor.setMaxPoolSize(10);

        executor.setQueueCapacity(100);

        executor.setThreadNamePrefix("user-task-");

        executor.initialize();

        return executor;

    }

}


// OrderServiceClient.java - Feign客户端

@FeignClient(

    name = "order-service",

    url = "${feign.client.order-service.url:}",

    configuration = OrderServiceClientConfig.class,

    fallbackFactory = OrderServiceClientFallbackFactory.class

)

public interface OrderServiceClient {

    

    @GetMapping("/api/v1/orders/users/{userId}")

    List getUserOrders(@PathVariable Long userId);

    

    @PostMapping("/api/v1/orders")

    OrderDTO createOrder(@RequestBody CreateOrderDTO createDTO);

    

    @GetMapping("/api/v1/orders/{orderId}")

    OrderDTO getOrderDetail(@PathVariable Long orderId);

}


// OrderServiceClientConfig.java - Feign配置

@Configuration

public class OrderServiceClientConfig {

    

    @Bean

    public Retryer feignRetryer() {

        return new Retryer.Default(1000, 2000, 3);

    }

    

    @Bean

    public ErrorDecoder feignErrorDecoder() {

        return new FeignErrorDecoder();

    }

    

    @Bean

    public RequestInterceptor oauth2FeignRequestInterceptor() {

        return requestTemplate -> {

            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

            if (authentication != null && authentication.getCredentials() instanceof String token) {

                requestTemplate.header("Authorization", "Bearer " + token);

            }

        };

    }

}


// OrderServiceClientFallbackFactory.java - 降级工厂

@Component

@Slf4j

public class OrderServiceClientFallbackFactory implements FallbackFactory {

    

    @Override

    public OrderServiceClient create(Throwable cause) {

        return new OrderServiceClient() {

            @Override

            public List getUserOrders(Long userId) {

                log.warn("订单服务不可用,返回空订单列表", cause);

                return Collections.emptyList();

            }

            

            @Override

            public OrderDTO createOrder(CreateOrderDTO createDTO) {

                log.error("订单服务不可用,无法创建订单", cause);

                throw new ServiceUnavailableException("订单服务暂时不可用");

            }

            

            @Override

            public OrderDTO getOrderDetail(Long orderId) {

                log.error("订单服务不可用,无法获取订单详情", cause);

                throw new ServiceUnavailableException("订单服务暂时不可用");

            }

        };

    }

}

```


## 分布式事务管理


```java

// TransactionService.java - 分布式事务服务

@Service

@RequiredArgsConstructor

@Slf4j

public class TransactionService {

    

    private final UserService userService;

    private final AccountService accountService;

    private final OrderService orderService;

    private final InventoryService inventoryService;

    private final TransactionTemplate transactionTemplate;

    private final StringRedisTemplate redisTemplate;

    

    @Transactional(rollbackFor = Exception.class)

    public OrderDTO placeOrderWithTransaction(PlaceOrderDTO orderDTO) {

        // 阶段1:验证和预处理

        validateOrder(orderDTO);

        

        // 阶段2:创建订单(本地事务)

        OrderDTO order = orderService.createOrder(orderDTO);

        

        // 阶段3:扣减库存(分布式事务)

        try {

            inventoryService.deductInventory(orderDTO.getItems());

        } catch (Exception e) {

            // 库存扣减失败,补偿订单

            orderService.cancelOrder(order.getId(), "库存不足");

            throw new BusinessException("库存扣减失败", e);

        }

        

        // 阶段4:扣减账户余额(分布式事务)

        try {

            accountService.deductBalance(orderDTO.getUserId(), order.getFinalAmount());

        } catch (Exception e) {

            // 余额扣减失败,补偿库存和订单

            inventoryService.restoreInventory(orderDTO.getItems());

            orderService.cancelOrder(order.getId(), "余额不足");

            throw new BusinessException("余额扣减失败", e);

        }

        

        // 阶段5:发送订单创建消息

        sendOrderCreatedMessage(order);

        

        return order;

    }

    

    @Saga

    public void processPaymentSaga(PaymentSagaDTO sagaDTO) {

        // Saga模式处理分布式事务

        TransactionSaga saga = new TransactionSaga("payment-saga-" + sagaDTO.getOrderId());

        

        saga.start()

            .step("deduct-inventory")

                .invoke(() -> inventoryService.deductInventory(sagaDTO.getItems()))

                .withCompensation(() -> inventoryService.restoreInventory(sagaDTO.getItems()))

            .step("deduct-balance")

                .invoke(() -> accountService.deductBalance(sagaDTO.getUserId(), sagaDTO.getAmount()))

                .withCompensation(() -> accountService.refundBalance(sagaDTO.getUserId(), sagaDTO.getAmount()))

            .step("create-order")

                .invoke(() -> orderService.createOrder(sagaDTO.getOrderDTO()))

                .withCompensation(() -> orderService.cancelOrder(sagaDTO.getOrderId(), "支付失败"))

            .step("send-notification")

                .invoke(() -> notificationService.sendOrderNotification(sagaDTO.getOrderId()))

            .end();

        

        saga.execute();

    }

    

    @Transactional(propagation = Propagation.REQUIRES_NEW)

    public void recordTransactionLog(TransactionLog log) {

        // 记录事务日志

        transactionLogRepository.save(log);

        

        // 发布事务事件

        applicationEventPublisher.publishEvent(

            new TransactionRecordedEvent(log.getId(), log.getType(), log.getStatus())

        );

    }

    

    private void validateOrder(PlaceOrderDTO orderDTO) {

        // 验证用户状态

        UserDTO user = userService.getUserById(orderDTO.getUserId());

        if (!UserStatus.ACTIVE.equals(user.getStatus())) {

            throw new BusinessException("用户状态异常");

        }

        

        // 验证商品状态

        orderDTO.getItems().forEach(item -> {

            ProductDTO product = productService.getProductById(item.getProductId());

            if (!product.isAvailable()) {

                throw new BusinessException("商品" + product.getName() + "不可用");

            }

        });

        

        // 分布式锁:防止重复下单

        String lockKey = "order:lock:" + orderDTO.getUserId() + ":" + orderDTO.getItemsHash();

        Boolean locked = redisTemplate.opsForValue()

            .setIfAbsent(lockKey, "1", Duration.ofSeconds(30));

        

        if (Boolean.FALSE.equals(locked)) {

            throw new BusinessException("操作过于频繁,请稍后重试");

        }

    }

}


// Seata分布式事务配置

@Configuration

public class SeataConfig {

    <"p5.p5k3.org.cn"><"m1.p5k3.org.cn"><"a8.p5k3.org.cn">

    @Bean

    public DataSourceProxy dataSourceProxy(DataSource dataSource) {

        return new DataSourceProxy(dataSource);

    }

    

    @Bean

    public GlobalTransactionScanner globalTransactionScanner() {

        return new GlobalTransactionScanner(

            "${spring.application.name}",

            "my_test_tx_group"

        );

    }

    

    @Bean

    public FailureHandler failureHandler() {

        return new DefaultFailureHandlerImpl();

    }

}


// 使用Seata分布式事务

@Service

public class OrderServiceWithSeata {

    

    @GlobalTransactional(name = "create-order-tx", timeoutMills = 60000)

    public OrderDTO createOrderWithSeata(CreateOrderDTO createDTO) {

        // 创建订单

        OrderDTO order = createOrder(createDTO);

        

        // 扣减库存(跨服务)

        inventoryService.deductInventory(createDTO.getItems());

        

        // 扣减余额(跨服务)

        accountService.deductBalance(createDTO.getUserId(), order.getFinalAmount());

        

        return order;

    }

}

```


## 监控与可观测性


```yaml

# prometheus.yml - 监控配置

global:

  scrape_interval: 15s

  evaluation_interval: 15s


alerting:

  alertmanagers:

    - static_configs:

        - targets:

          - alertmanager:9093


rule_files:

  - "alert-rules.yml"


scrape_configs:

  - job_name: 'spring-boot-apps'

    metrics_path: '/actuator/prometheus'

    static_configs:

      - targets:

        - 'user-service:8080'

        - 'order-service:8080'

        - 'product-service:8080'

        - 'inventory-service:8080'

        - 'payment-service:8080'

    relabel_configs:

      - source_labels: [__address__]

        target_label: instance

      - source_labels: [__meta_docker_container_name]

        target_label: container


  - job_name: 'eureka'

    static_configs:

      - targets: ['discovery-service:8761']


  - job_name: 'zipkin'

    static_configs:

      - targets: ['zipkin:9411']


# grafana-dashboard.json

{

  "title": "微服务监控仪表板",

  "panels": [

    {

      "title": "服务请求量",

      "targets": [

        {

          "expr": "sum(rate(http_server_requests_seconds_count[5m])) by (application)",

          "legendFormat": "{{application}}"

        }

      ],

      "type": "graph"

    },

    {

      "title": "服务响应时间P95",

      "targets": [

        {

          "expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket[5m])) by (le, application))",

          "legendFormat": "{{application}}"

        }

      ],

      "type": "graph"

    },

    {

      "title": "熔断器状态",

      "targets": [

        {

          "expr": "resilience4j_circuitbreaker_state{state=\"OPEN\"}",

          "legendFormat": "{{name}}"

        }

      ],

      "type": "stat"

    },

    {

      "title": "数据库连接池",

      "targets": [

        {

          "expr": "hikaricp_connections_active{pool=\"userService\"}",

          "legendFormat": "活跃连接"

        },

        {

          "expr": "hikaricp_connections_idle{pool=\"userService\"}",

          "legendFormat": "空闲连接"

        }

      ],

      "type": "gauge"

    }

  ]

}


// HealthIndicator.java - 健康检查

@Component

public class ServiceHealthIndicator implements HealthIndicator {

    

    private final UserRepository userRepository;

    private final RedisConnectionFactory redisConnectionFactory;

    private final RestTemplate restTemplate;

    

    @Override

    public Health health() {

        Health.Builder builder = Health.up();

        

        // 检查数据库连接

        try {

            long userCount = userRepository.count();

            builder.withDetail("database.users.count", userCount);

        } catch (Exception e) {

            builder.down()

                .withDetail("database.error", e.getMessage());

        }

        

        // 检查Redis连接

        try {

            RedisConnection connection = redisConnectionFactory.getConnection();

            String pong = connection.ping();

            builder.withDetail("redis.status", "UP")

                .withDetail("redis.response", pong);

            connection.close();

        } catch (Exception e) {

            builder.down()

                .withDetail("redis.error", e.getMessage());

        }

        

        // 检查依赖服务

        checkDependencyServices(builder);

        

        return builder.build();

    }

    

    private void checkDependencyServices(Health.Builder builder) {

        Map services = Map.of(

            "order-service", "http://order-service:8080/actuator/health",

            "inventory-service", "http://inventory-service:8080/actuator/health"

        );

        

        services.forEach((serviceName, url) -> {

            try {

                ResponseEntity response = restTemplate.getForEntity(url, Map.class);

                if (response.getStatusCode().is2xxSuccessful()) {

                    builder.withDetail(serviceName + ".status", "UP");

                } else {

                    builder.withDetail(serviceName + ".status", "DOWN");

                }

            } catch (Exception e) {

                builder.withDetail(serviceName + ".status", "DOWN")

                    .withDetail(serviceName + ".error", e.getMessage());

            }

        });

    }

}

```


基于Spring Boot 3的微服务架构为企业级分布式系统提供了现代化解决方案。通过服务注册与发现、配置中心、熔断器、分布式事务等核心组件,构建了高可用、可扩展的微服务生态系统。在实际部署中,需要结合容器化技术、服务网格和可观测性工具,形成完整的DevOps流水线,确保系统的稳定运行和高效运维。随着业务规模的增长,还需要持续优化架构设计,平衡微服务的粒度与治理复杂度。


请使用浏览器的分享功能分享到微信等