概述
微服务架构是现代企业级应用开发的主流模式,它将单体应用拆分为多个独立的、可部署的服务。Spring Boot作为Java生态中最受欢迎的框架,为微服务开发提供了完整的解决方案。本文将深入探讨如何使用Spring Boot构建高效、可扩展的微服务系统。
核心技术组件
1. 技术栈选择
- Spring Boot: 核心框架,简化配置
- Spring Cloud: 微服务治理工具集
- Eureka: 服务注册与发现
- Feign: 声明式HTTP客户端
- Hystrix: 熔断器模式实现
- Gateway: API网关
项目架构设计
用户服务实现
@RestController
@RequestMapping("/api/users")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@GetMapping("/{id}")
@Cacheable(value = "users", key = "#id")
public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {
log.info("获取用户信息: {}", id);
try {
UserDTO user = userService.findById(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
} catch (Exception e) {
log.error("获取用户信息失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@PostMapping
@Transactional
public ResponseEntity<UserDTO> createUser(@Valid @RequestBody CreateUserRequest request) {
log.info("创建用户: {}", request.getUsername());
// 参数验证
if (userService.existsByUsername(request.getUsername())) {
return ResponseEntity.badRequest()
.body(new ErrorResponse("用户名已存在"));
}
UserDTO createdUser = userService.createUser(request);
// 发布用户创建事件
eventPublisher.publishEvent(new UserCreatedEvent(createdUser));
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
}
服务间通信配置
@Component
@FeignClient(name = "order-service", fallback = OrderServiceFallback.class)
public interface OrderServiceClient {
@GetMapping("/api/orders/user/{userId}")
List<OrderDTO> getUserOrders(@PathVariable("userId") Long userId);
@PostMapping("/api/orders")
OrderDTO createOrder(@RequestBody CreateOrderRequest request);
}
@Component
public class OrderServiceFallback implements OrderServiceClient {
@Override
public List<OrderDTO> getUserOrders(Long userId) {
log.warn("订单服务调用失败,返回默认值");
return Collections.emptyList();
}
@Override
public OrderDTO createOrder(CreateOrderRequest request) {
log.error("订单服务不可用");
throw new ServiceUnavailableException("订单服务暂时不可用");
}
}
配置管理与服务发现
application.yml配置
server:
port: ${SERVER_PORT:8080}
spring:
application:
name: user-service
datasource:
url: jdbc:mysql://localhost:3306/user_db?useSSL=false&serverTimezone=UTC
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:password}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: false
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
redis:
host: ${REDIS_HOST:localhost}
port: 6379
timeout: 2000ms
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
lease-renewal-interval-in-seconds: 30
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: always
logging:
level:
com.example: INFO
org.springframework.web: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
启动类配置
@SpringBootApplication
@EnableEurekaClient
@EnableJpaRepositories
@EnableCaching
@EnableScheduling
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.entryTtl(Duration.ofMinutes(30));
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
数据持久化层
实体类定义
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String email;
@Column(name = "phone_number")
private String phoneNumber;
@Enumerated(EnumType.STRING)
private UserStatus status = UserStatus.ACTIVE;
@CreationTimestamp
@Column(name = "created_at")
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@Version
private Integer version;
}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
boolean existsByUsername(String username);
@Query("SELECT u FROM User u WHERE u.status = :status")
Page<User> findByStatus(@Param("status") UserStatus status, Pageable pageable);
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.id = :id")
int updateUserStatus(@Param("id") Long id, @Param("status") UserStatus status);
}
服务层实现
@Service
@Transactional
@Slf4j
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserMapper userMapper;
@Autowired
private ApplicationEventPublisher eventPublisher;
@Retryable(value = {DataAccessException.class}, maxAttempts = 3)
public UserDTO createUser(CreateUserRequest request) {
log.info("创建新用户: {}", request.getUsername());
User user = userMapper.toEntity(request);
user.setStatus(UserStatus.ACTIVE);
User savedUser = userRepository.save(user);
// 发布事件
eventPublisher.publishEvent(new UserCreatedEvent(savedUser.getId()));
return userMapper.toDTO(savedUser);
}
@Cacheable(value = "users", key = "#id", unless = "#result == null")
public UserDTO findById(Long id) {
return userRepository.findById(id)
.map(userMapper::toDTO)
.orElse(null);
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
log.info("用户已删除: {}", id);
}
}
监控与健康检查
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Autowired
private UserRepository userRepository;
@Override
public Health health() {
try {
long userCount = userRepository.count();
return Health.up()
.withDetail("users.count", userCount)
.withDetail("status", "服务正常运行")
.build();
} catch (Exception e) {
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
}
}
@RestController
@RequestMapping("/actuator/custom")
public class CustomMetricsController {
@Autowired
private MeterRegistry meterRegistry;
@GetMapping("/metrics")
public Map<String, Object> getCustomMetrics() {
Map<String, Object> metrics = new HashMap<>();
Counter.Sample sample = Timer.start(meterRegistry);
// 业务逻辑执行时间统计
sample.stop(Timer.builder("business.execution.time")
.description("业务执行时间")
.register(meterRegistry));
return metrics;
}
}
Docker部署配置
FROM openjdk:11-jre-slim
VOLUME /tmp
COPY target/user-service-1.0.0.jar app.jar
EXPOSE 8080
ENV JAVA_OPTS=""
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar"]
最佳实践总结
1. 服务设计原则
- 单一职责: 每个服务专注于特定的业务领域
- 无状态设计: 服务实例间可以任意切换
- 数据库独立: 避免服务间直接数据库访问
2. 性能优化策略
- 合理使用缓存减少数据库访问
- 实现服务熔断避免级联失败
- 采用异步处理提升响应速度
- 数据库连接池优化
3. 监控与运维
- 集成APM工具进行性能监控
- 实现分布式链路追踪
- 配置告警机制及时发现问题
- 定期进行容量规划和性能测试
微服务架构虽然带来了系统的灵活性和可扩展性,但也增加了复杂度。通过Spring Boot生态的支持,我们可以更轻松地构建和管理微服务系统,实现企业级应用的现代化改造。