简易电商订单处理策略
正常情况:任务进入线程池队列处理
队列满时:优先存入Redis待处理队列
Redis异常时:降级到低优先级线程池
系统过载时:触发熔断保护机制
OrderTask实现订单任务包装
支持Redis持久化获取订单数据
采用组合拒绝策略实现多级处理
Redis持久化使用List结构存储待处理订单
熔断器基于令牌桶算法实现限流
自定义线程池 以及 拒绝策略
1. 拒绝策略 – 队列满时:优先存入Redis待处理队列
import com.orderhandler.model.OrderTask;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class RedisBackupPolicy implements RejectedExecutionHandler {
private static final String PENDING_ORDERS_KEY = "order:pending";
private final RedisTemplate<String, OrderTask> redisTemplate;
public RedisBackupPolicy(RedisTemplate<String, OrderTask> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (r instanceof OrderTask) {
OrderTask task = (OrderTask) r;
try {
// Store the task in Redis list
redisTemplate.opsForList().rightPush(PENDING_ORDERS_KEY, task);
} catch (Exception e) {
// If Redis fails, propagate the exception to try next handler
throw new RuntimeException("Failed to store task in Redis", e);
}
} else {
throw new IllegalArgumentException("Task must be an OrderTask");
}
}
// Method to retrieve pending tasks from Redis
public OrderTask retrievePendingTask() {
return redisTemplate.opsForList().leftPop(PENDING_ORDERS_KEY);
}
// Method to get pending tasks count
public Long getPendingTasksCount() {
return redisTemplate.opsForList().size(PENDING_ORDERS_KEY);
}
}
2. 拒绝策略 – Redis异常时:降级到低优先级线程池
//
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class TieredDegradePolicy implements RejectedExecutionHandler {
private final ThreadPoolExecutor lowPriorityPool;
public TieredDegradePolicy(ThreadPoolExecutor lowPriorityPool) {
this.lowPriorityPool = lowPriorityPool;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
// Try to submit the task to low priority pool
lowPriorityPool.execute(r);
} catch (Exception e) {
// If low priority pool also rejects, propagate the exception
throw new RuntimeException("Failed to degrade task to low priority pool", e);
}
}
}
3. 拒绝策略 – 系统过载时:触发熔断保护机制
// 熔断器基于令牌桶算法实现限流
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.TimeUnit;
public class CircuitBreakerPolicy implements RejectedExecutionHandler {
private final TokenBucket tokenBucket;
public CircuitBreakerPolicy(int capacity, int refillRate) {
this.tokenBucket = new TokenBucket(capacity, refillRate);
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!tokenBucket.tryConsume()) {
throw new RuntimeException("Circuit breaker triggered - system overloaded");
}
// If we got here, we have a token but nowhere to execute
// Propagate rejection to trigger fallback mechanisms
throw new RuntimeException("All processing capacity exhausted");
}
// Token Bucket implementation for rate limiting
private static class TokenBucket {
private final int capacity;
private final int refillRate;
private final AtomicInteger tokens;
private long lastRefillTimestamp;
public TokenBucket(int capacity, int refillRate) {
this.capacity = capacity;
this.refillRate = refillRate;
this.tokens = new AtomicInteger(capacity);
this.lastRefillTimestamp = System.nanoTime();
}
public synchronized boolean tryConsume() {
refill();
if (tokens.get() > 0) {
tokens.decrementAndGet();
return true;
}
return false;
}
private void refill() {
long now = System.nanoTime();
long duration = now - lastRefillTimestamp;
// Calculate tokens to add based on time elapsed
long newTokens = TimeUnit.NANOSECONDS.toSeconds(duration) * refillRate;
if (newTokens > 0) {
int currentTokens = Math.min(capacity, tokens.get() + (int)newTokens);
tokens.set(currentTokens);
lastRefillTimestamp = now;
}
}
}
}
4. 组合拒绝策略处理器
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.RejectedExecutionException;
public class CompositePolicy implements RejectedExecutionHandler {
private final List<RejectedExecutionHandler> handlers = new ArrayList<>();
public CompositePolicy addHandler(RejectedExecutionHandler handler) {
handlers.add(handler);
return this;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
for (RejectedExecutionHandler handler : handlers) {
try {
handler.rejectedExecution(r, executor);
return; // If handler succeeds, return immediately
} catch (Exception e) {
// Continue to next handler if current one fails
continue;
}
}
// If all handlers fail, throw exception
throw new RejectedExecutionException("All handlers failed to process task");
}
}
5. 自定义线程池 – 采取多个拒绝策略形成的组合策略
import com.orderhandler.model.OrderTask;
import com.orderhandler.thread.CircuitBreakerPolicy;
import com.orderhandler.thread.CompositePolicy;
import com.orderhandler.thread.RedisBackupPolicy;
import com.orderhandler.thread.TieredDegradePolicy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Configuration
public class ThreadPoolConfig {
@Bean
public RedisTemplate<String, OrderTask> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, OrderTask> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new Jackson2JsonRedisSerializer<>(OrderTask.class));
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(OrderTask.class));
return template;
}
@Bean
public ThreadPoolExecutor lowPriorityPool() {
return new ThreadPoolExecutor(
2, // Core pool size
5, // Maximum pool size
60L, // Keep alive time
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(50) // Queue capacity
);
}
@Bean
public ThreadPoolExecutor orderExecutor(
RedisTemplate<String, OrderTask> redisTemplate,
ThreadPoolExecutor lowPriorityPool) {
CircuitBreakerPolicy breaker = new CircuitBreakerPolicy(100, 10); // 100 tokens, 10 per second refill
CompositePolicy rejectionPolicy = new CompositePolicy()
.addHandler(new RedisBackupPolicy(redisTemplate)) // 优先持久化
.addHandler(new TieredDegradePolicy(lowPriorityPool)) // 次选降级
.addHandler(breaker); // 最后熔断
return new ThreadPoolExecutor(
8, // Core pool size
16, // Maximum pool size
300L, // Keep alive time
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(200), // Queue capacity
rejectionPolicy
);
}
}
订单相关
1. 订单服务
import com.orderhandler.model.OrderTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@Service
public class OrderProcessingService {
private final ThreadPoolExecutor orderExecutor;
private final RedisTemplate<String, OrderTask> redisTemplate;
private static final String PENDING_ORDERS_KEY = "order:pending";
@Autowired
public OrderProcessingService(
ThreadPoolExecutor orderExecutor,
RedisTemplate<String, OrderTask> redisTemplate) {
this.orderExecutor = orderExecutor;
this.redisTemplate = redisTemplate;
}
public void submitOrder(String orderId, String userId, Double amount) {
OrderTask task = new OrderTask(orderId, userId, amount);
try {
orderExecutor.execute(() -> processOrder(task));
} catch (Exception e) {
log.error("Failed to submit order: {}", orderId, e);
throw e;
}
}
private void processOrder(OrderTask task) {
try {
log.info("Processing order: {}", task.getOrderId());
task.markProcessing();
// Simulate order processing
Thread.sleep(1000);
task.markCompleted();
log.info("Order completed: {}", task.getOrderId());
} catch (Exception e) {
task.markFailed();
log.error("Order processing failed: {}", task.getOrderId(), e);
}
}
// Method to process orders from Redis backup queue
public void processBackupOrders() {
while (true) {
OrderTask task = redisTemplate.opsForList().leftPop(PENDING_ORDERS_KEY);
if (task == null) {
break;
}
try {
orderExecutor.execute(() -> processOrder(task));
} catch (RejectedExecutionException e) {
log.error("Failed to process backup order: {}", task.getOrderId(), e);
// Put it back in the queue
redisTemplate.opsForList().rightPush(PENDING_ORDERS_KEY, task);
// Stop processing more orders since executor is full
break;
} catch (Exception e) {
log.error("Unexpected error processing backup order: {}", task.getOrderId(), e);
// Put it back in the queue for retry
redisTemplate.opsForList().rightPush(PENDING_ORDERS_KEY, task);
break;
}
}
}
// Get executor statistics
public String getExecutorStats() {
return String.format(
"Pool size: %d, Active: %d, Queue size: %d, Completed: %d",
orderExecutor.getPoolSize(),
orderExecutor.getActiveCount(),
orderExecutor.getQueue().size(),
orderExecutor.getCompletedTaskCount()
);
}
}
2. 订单任务包装类
//订单任务包装类
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class OrderTask implements Serializable {
private static final long serialVersionUID = 1L;
private String orderId;
private String userId;
private Double amount;
private Integer priority;
private LocalDateTime createTime;
private OrderStatus status;
public enum OrderStatus {
PENDING,
PROCESSING,
COMPLETED,
FAILED
}
// Constructor for creating a new order task
public OrderTask(String orderId, String userId, Double amount) {
this.orderId = orderId;
this.userId = userId;
this.amount = amount;
this.createTime = LocalDateTime.now();
this.status = OrderStatus.PENDING;
this.priority = 0;
}
// Method to mark the task as processing
public void markProcessing() {
this.status = OrderStatus.PROCESSING;
}
// Method to mark the task as completed
public void markCompleted() {
this.status = OrderStatus.COMPLETED;
}
// Method to mark the task as failed
public void markFailed() {
this.status = OrderStatus.FAILED;
}
}
结尾 TIPS
AI工具 或许 成为 All-Factor Engineer 又一个得力助手,你会面临失业吗?😄 😂 🔔