基于SpringCloud构建微服务电商平台实战指南
一、项目架构设计
1. 微服务拆分方案
电商平台通常按照业务功能划分为以下核心服务:
├── 用户服务(user-service) # 用户注册/登录/权限管理
├── 商品服务(product-service) # 商品管理/类目管理
├── 订单服务(order-service) # 订单创建/状态流转
├── 支付服务(payment-service) # 支付渠道对接
├── 库存服务(inventory-service) # 库存管理
├── 搜索服务(search-service) # 商品搜索
├── 推荐服务(recommend-service) # 个性化推荐
└── 网关服务(gateway) # 统一API入口
2. 技术栈选型
spring-cloud: 2022.0.4
spring-cloud-alibaba: 2022.0.0.0
spring-boot: 3.1.0
java: 17
nacos: 2.2.3 # 服务注册与配置中心
sentinel: 1.8.6 # 流量控制与熔断降级
seata: 1.7.1 # 分布式事务
redis: 7.0 # 缓存与分布式锁
rabbitmq: 3.11 # 异步消息处理
elasticsearch: 8.7 # 商品搜索
二、核心服务实现
1. 商品服务实现
// 商品领域模型
@Entity
@Table(name = "product")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private BigDecimal price;
@Column(name = "category_id")
private Long categoryId;
@Column(columnDefinition = "TEXT")
private String description;
@Column(name = "stock_count")
private Integer stockCount;
// Getters & Setters...
}
// 商品服务接口
@RestController
@RequestMapping("/products")
@RequiredArgsConstructor
public class ProductController {
private final ProductService productService;
@GetMapping("/{id}")
public Result<Product> getProduct(@PathVariable Long id) {
return Result.success(productService.getById(id));
}
@PostMapping
public Result<Long> createProduct(@Valid @RequestBody ProductCreateDTO dto) {
return Result.success(productService.createProduct(dto));
}
@GetMapping("/search")
public Result<PageResult<Product>> searchProducts(
@RequestParam String keyword,
@RequestParam(defaultValue = "0") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
return Result.success(productService.search(keyword, page, size));
}
}
2. 订单服务分布式事务
// 订单创建服务(使用Seata)
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final OrderMapper orderMapper;
private final InventoryClient inventoryClient;
private final ProductClient productClient;
@GlobalTransactional // 开启全局事务
@Override
public Long createOrder(OrderCreateDTO dto) {
// 1. 验证商品信息
Product product = productClient.getProduct(dto.getProductId());
if (product == null) {
throw new BusinessException("商品不存在");
}
// 2. 扣减库存
inventoryClient.deductStock(dto.getProductId(), dto.getQuantity());
// 3. 创建订单
Order order = new Order();
order.setUserId(dto.getUserId());
order.setProductId(dto.getProductId());
order.setQuantity(dto.getQuantity());
order.setTotalAmount(product.getPrice().multiply(
BigDecimal.valueOf(dto.getQuantity())));
order.setStatus(OrderStatus.CREATED);
orderMapper.insert(order);
// 4. 发送订单创建事件
sendOrderCreatedEvent(order);
return order.getId();
}
private void sendOrderCreatedEvent(Order order) {
// 消息队列实现...
}
}
三、服务通信设计
1. OpenFeign声明式调用
// 库存服务Feign客户端
@FeignClient(name = "inventory-service", path = "/inventories")
public interface InventoryClient {
@PostMapping("/deduct")
Result<Void> deductStock(
@RequestParam Long productId,
@RequestParam Integer quantity);
@PostMapping("/increase")
Result<Void> increaseStock(
@RequestParam Long productId,
@RequestParam Integer quantity);
}
// 自定义Feign配置
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Retryer feignRetryer() {
return new Retryer.Default(100, 1000, 3);
}
}
2. 消息队列异步处理
// 订单支付成功消息处理
@Component
@RequiredArgsConstructor
@RabbitListener(queues = "order.payment.success.queue")
public class OrderPaymentSuccessListener {
private final OrderService orderService;
private final InventoryService inventoryService;
@RabbitHandler
public void handlePaymentSuccess(PaymentSuccessMessage message) {
// 1. 更新订单状态
orderService.updateStatus(message.getOrderId(), OrderStatus.PAID);
// 2. 扣减真实库存(预扣库存已在创建订单时完成)
inventoryService.confirmDeduction(message.getOrderId());
// 3. 发送订单支付成功通知
sendPaymentSuccessNotification(message);
}
}
四、关键业务逻辑实现
1. 购物车实现方案
// Redis购物车服务
@Service
@RequiredArgsConstructor
public class CartServiceImpl implements CartService {
private final RedisTemplate<String, Object> redisTemplate;
private final ProductClient productClient;
private String getCartKey(Long userId) {
return "cart:" + userId;
}
@Override
public void addItem(Long userId, CartItemDTO item) {
// 验证商品信息
Product product = productClient.getProduct(item.getProductId());
if (product == null) {
throw new BusinessException("商品不存在");
}
// 存储购物车项
redisTemplate.opsForHash().put(
getCartKey(userId),
item.getProductId().toString(),
item
);
}
@Override
public List<CartItemDTO> getCart(Long userId) {
List<Object> items = redisTemplate.opsForHash().values(getCartKey(userId));
return items.stream()
.map(item -> (CartItemDTO) item)
.collect(Collectors.toList());
}
}
2. 分布式锁实现秒杀
// 秒杀服务实现
@Service
@RequiredArgsConstructor
public class SeckillServiceImpl implements SeckillService {
private final RedissonClient redissonClient;
private final ProductService productService;
private final OrderService orderService;
@Override
public SeckillResult seckill(Long userId, Long seckillId) {
// 获取分布式锁
RLock lock = redissonClient.getLock("seckill:lock:" + seckillId);
try {
// 尝试加锁,最多等待100ms,锁有效期10s
if (lock.tryLock(100, 10000, TimeUnit.MILLISECONDS)) {
// 1. 检查库存
Product product = productService.getSeckillProduct(seckillId);
if (product.getStock() <= 0) {
return SeckillResult.soldOut();
}
// 2. 检查是否已购买
if (orderService.hasPurchased(userId, seckillId)) {
return SeckillResult.repeatPurchase();
}
// 3. 创建秒杀订单
Long orderId = orderService.createSeckillOrder(userId, seckillId);
return SeckillResult.success(orderId);
}
return SeckillResult.retryLater();
} finally {
lock.unlock();
}
}
}
五、平台安全设计
1. JWT认证实现
// JWT工具类
@Component
public class JwtTokenProvider {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
public String generateToken(UserDetails userDetails) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
return true;
} catch (Exception ex) {
return false;
}
}
}
// 认证过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenProvider tokenProvider;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = getJwtFromRequest(request);
if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
String username = tokenProvider.getUsernameFromToken(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
六、性能优化实践
1. 多级缓存设计
// 商品详情缓存服务
@Service
@RequiredArgsConstructor
public class ProductCacheServiceImpl implements ProductCacheService {
private final ProductMapper productMapper;
private final RedisTemplate<String, Object> redisTemplate;
private final CaffeineCache localCache;
private static final String REDIS_KEY_PREFIX = "product:";
@Cacheable(value = "products", key = "#id") // 本地缓存
@Override
public Product getProductById(Long id) {
// 1. 查Redis
String redisKey = REDIS_KEY_PREFIX + id;
Product product = (Product) redisTemplate.opsForValue().get(redisKey);
if (product == null) {
// 2. 查数据库
product = productMapper.selectById(id);
if (product != null) {
// 3. 写Redis
redisTemplate.opsForValue().set(
redisKey,
product,
30, TimeUnit.MINUTES);
}
}
return product;
}
}
2. 接口限流配置
// Sentinel限流配置
@Configuration
public class SentinelConfig {
@PostConstruct
public void init() {
// 商品查询接口限流
FlowRule rule1 = new FlowRule();
rule1.setResource("GET:/api/products/{id}");
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setCount(100); // 每秒100次
// 订单创建接口限流
FlowRule rule2 = new FlowRule();
rule2.setResource("POST:/api/orders");
rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule2.setCount(50); // 每秒50次
FlowRuleManager.loadRules(Arrays.asList(rule1, rule2));
}
}
// 网关层限流
@Configuration
public class GatewayConfig {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
}
七、项目部署方案
1. Docker Compose部署
version: '3.8'
services:
nacos:
image: nacos/nacos-server:2.2.3
ports:
- "8848:8848"
environment:
- MODE=standalone
redis:
image: redis:7.0
ports:
- "6379:6379"
rabbitmq:
image: rabbitmq:3.11-management
ports:
- "5672:5672"
- "15672:15672"
user-service:
build: ./user-service
ports:
- "8081:8080"
depends_on:
- nacos
- redis
product-service:
build: ./product-service
ports:
- "8082:8080"
depends_on:
- nacos
- redis
- rabbitmq
2. Kubernetes部署文件
# product-service部署示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service
spec:
replicas: 3
selector:
matchLabels:
app: product-service
template:
metadata:
labels:
app: product-service
spec:
containers:
- name: product
image: registry.example.com/ecommerce/product-service:1.0.0
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
resources:
limits:
cpu: "2"
memory: 2Gi
---
apiVersion: v1
kind: Service
metadata:
name: product-service
spec:
selector:
app: product-service
ports:
- protocol: TCP
port: 80
targetPort: 8080
通过本项目的实践,开发者可以全面掌握基于SpringCloud的微服务架构设计与实现,构建高可用、高性能的电商平台。课程强调生产级代码规范与最佳实践,帮助学员从零开始搭建完整的分布式系统,为应对复杂业务场景打下坚实基础。