一、接口性能优化概述
接口性能优化是提升用户体验的关键:
优化方向:
- 减少等待时间(同步→异步)
- 并行处理(串行→并行)
- 减少计算量(缓存、预计算)
- 减少IO(合并请求、压缩)
二、异步化优化
1. 异步Servlet
java
@RestController
public class AsyncOrderController {
@Autowired
private AsyncOrderService asyncOrderService;
@GetMapping("/api/orders/{id}")
public Callable<Order> getOrderAsync(@PathVariable Long id) {
return () -> {
// 在另外的线程池中执行
return asyncOrderService.getOrder(id);
};
}
@GetMapping("/api/orders/{id}")
public CompletableFuture<Order> getOrderCompletable(@PathVariable Long id) {
return CompletableFuture.supplyAsync(() -> {
return asyncOrderService.getOrder(id);
});
}
}
2. 异步调用
java
@Service
public class OrderDetailService {
@Autowired
private UserService userService;
@Autowired
private ProductService productService;
@Autowired
private LogisticsService logisticsService;
// 同步方式(串行,耗时长)
public OrderDetail getOrderDetailSync(Long orderId) {
Order order = orderService.getById(orderId); // 10ms
User user = userService.getUser(order.getUserId()); // 20ms
Product product = productService.getProduct(order.getProductId()); // 15ms
Logistics logistics = logisticsService.getLogistics(order.getLogisticsId()); // 30ms
return new OrderDetail(order, user, product, logistics); // 总计:75ms
}
// 异步方式(并行,耗时短)
public CompletableFuture<OrderDetail> getOrderDetailAsync(Long orderId) {
CompletableFuture<Order> orderFuture =
CompletableFuture.supplyAsync(() -> orderService.getById(orderId));
CompletableFuture<User> userFuture =
CompletableFuture.supplyAsync(() -> userService.getUser(1001L));
CompletableFuture<Product> productFuture =
CompletableFuture.supplyAsync(() -> productService.getProduct(2001L));
CompletableFuture<Logistics> logisticsFuture =
CompletableFuture.supplyAsync(() -> logisticsService.getLogistics("LP123"));
return CompletableFuture.allOf(
orderFuture, userFuture, productFuture, logisticsFuture
).thenApply(v -> new OrderDetail(
orderFuture.join(),
userFuture.join(),
productFuture.join(),
logisticsFuture.join()
)); // 总耗时:max(10,20,15,30) = 30ms
}
}
3. 异步消息
java
@Service
public class OrderAsyncService {
@Autowired
private KafkaTemplate kafkaTemplate;
// 下单异步化
public String createOrderAsync(OrderRequest request) {
// 1. 生成预订单号
String orderNo = generateOrderNo();
// 2. 发送异步消息处理
kafkaTemplate.send("order:create", orderNo, request);
// 3. 立即返回
return orderNo;
}
}
@Component
public class OrderMessageConsumer {
@KafkaListener(topics = "order:create")
public void handleOrderCreate(ConsumerRecord<String, OrderRequest> record) {
// 在后台处理订单
Order order = processOrder(record.value());
saveOrder(order);
notifyUser(order);
}
}
三、并行化优化
1. CompletableFuture并行
java
@Service
public class HomePageService {
@Autowired
private BannerService bannerService;
@Autowired
private CategoryService categoryService;
@Autowired
private ProductService productService;
@Autowired
private RecommendService recommendService;
// 首页数据(串行)
public HomeData getHomeDataSync() {
List<Banner> banners = bannerService.getBanners(); // 100ms
List<Category> categories = categoryService.getCategories(); // 80ms
List<Product> hotProducts = productService.getHotProducts(); // 120ms
List<Product> recommendProducts = recommendService.getRecommend(); // 150ms
return new HomeData(banners, categories, hotProducts, recommendProducts);
// 总耗时:100+80+120+150 = 450ms
}
// 首页数据(并行)
public HomeData getHomeDataParallel() {
long start = System.currentTimeMillis();
CompletableFuture<List<Banner>> bannersFuture =
CompletableFuture.supplyAsync(() -> bannerService.getBanners());
CompletableFuture<List<Category>> categoriesFuture =
CompletableFuture.supplyAsync(() -> categoryService.getCategories());
CompletableFuture<List<Product>> hotProductsFuture =
CompletableFuture.supplyAsync(() -> productService.getHotProducts());
CompletableFuture<List<Product>> recommendFuture =
CompletableFuture.supplyAsync(() -> recommendService.getRecommend());
// 等待所有完成
CompletableFuture.allOf(
bannersFuture, categoriesFuture, hotProductsFuture, recommendFuture
).join();
HomeData data = new HomeData(
bannersFuture.join(),
categoriesFuture.join(),
hotProductsFuture.join(),
recommendFuture.join()
);
System.out.println("并行耗时: " + (System.currentTimeMillis() - start) + "ms");
return data;
// 总耗时:max(100,80,120,150) = 150ms
}
}
2. 线程池优化
java
@Configuration
public class ThreadPoolConfig {
@Bean("asyncExecutor")
public ThreadPoolTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
@Service
public class ParallelService {
@Async("asyncExecutor")
public CompletableFuture<Result> processTask(String taskId) {
// 异步任务
return CompletableFuture.completedFuture(process(taskId));
}
}
四、缓存化优化
1. 多级缓存
java
@Service
public class ProductCacheService {
// L1: 本地缓存(Caffeine)
private final LoadingCache<Long, Product> localCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build(id -> loadFromRedis(id));
// L2: Redis缓存
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public Product getProduct(Long id) {
// 1. 查本地缓存
Product product = localCache.getIfPresent(id);
if (product != null) {
return product;
}
// 2. 查Redis
String key = "product:" + id;
product = (Product) redisTemplate.opsForValue().get(key);
if (product != null) {
localCache.put(id, product);
return product;
}
// 3. 查数据库
product = productMapper.selectById(id);
if (product != null) {
redisTemplate.opsForValue().set(key, product, 30, TimeUnit.MINUTES);
localCache.put(id, product);
}
return product;
}
}
2. 预计算缓存
java
@Service
public class StatisticsCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 定时预计算
@Scheduled(cron = "0 0 * * * ?") // 每小时执行
public void precomputeStatistics() {
// 预计算今日销售统计
Map<String, Object> stats = calculateDailyStats();
String key = "stats:daily:" + LocalDate.now();
redisTemplate.opsForValue().set(key, stats, 25, TimeUnit.HOURS);
}
// 直接读取缓存
public Map<String, Object> getDailyStats() {
String key = "stats:daily:" + LocalDate.now();
return (Map<String, Object>) redisTemplate.opsForValue().get(key);
}
}
3. 热点数据缓存
java
@Service
public class HotProductService {
// 热点商品自动发现
private final LoadingCache<Long, Product> hotProductCache = Caffeine.newBuilder()
.maximumSize(100)
.expireAfterWrite(1, TimeUnit.MINUTES)
.refreshAfterWrite(30, TimeUnit.SECONDS)
.build(id -> {
// 热点商品走数据库,但使用更长的过期时间
Product product = productMapper.selectById(id);
return product;
});
public Product getHotProduct(Long id) {
return hotProductCache.get(id);
}
}
五、数据库优化
1. 批量查询
java
@Service
public class ProductBatchService {
@Autowired
private ProductMapper productMapper;
// 批量查询
public List<Product> getProductsByIds(List<Long> ids) {
// 分批查询,每批100个
List<Product> results = new ArrayList<>();
List<List<Long>> batches = Lists.partition(ids, 100);
for (List<Long> batch : batches) {
List<Product> products = productMapper.selectBatchIds(batch);
results.addAll(products);
}
return results;
}
}
2. 乐观锁
java
@Service
public class InventoryOptimisticLockService {
@Autowired
private InventoryMapper inventoryMapper;
// 乐观锁扣减库存
public boolean deductStock(Long productId, Integer quantity) {
int retries = 3;
while (retries > 0) {
Inventory inventory = inventoryMapper.selectById(productId);
if (inventory.getStock() < quantity) {
throw new BusinessException("库存不足");
}
// CAS更新
int result = inventoryMapper.updateStockOptimistic(
productId,
inventory.getVersion(),
inventory.getStock() - quantity
);
if (result > 0) {
return true;
}
retries--;
}
throw new BusinessException("库存扣减失败,请重试");
}
}
@Mapper
public interface InventoryMapper {
@Update("UPDATE inventory SET stock = #{stock}, version = version + 1 " +
"WHERE id = #{id} AND version = #{version}")
int updateStockOptimistic(@Param("id") Long id,
@Param("version") Integer version,
@Param("stock") Integer stock);
}
六、网络优化
1. 合并请求
java
@Service
public class BatchRequestService {
// 批量接口
@PostMapping("/api/batch")
public List<Object> batchRequest(@RequestBody List<Request> requests) {
return requests.parallelStream()
.map(this::processSingleRequest)
.collect(Collectors.toList());
}
}
2. 数据压缩
java
@Configuration
public class CompressionConfig {
@Bean
public FilterRegistrationBean<GzipCompressionFilter> compressionFilter() {
FilterRegistrationBean<GzipCompressionFilter> registration =
new FilterRegistrationBean<>();
registration.addUrlPatterns("/*");
registration.setFilter(new GzipCompressionFilter());
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
}
七、总结
接口性能优化三大方向:
- 异步化:非核心流程异步处理
- 并行化:多任务并行执行
- 缓存化:多级缓存减少计算
优化效果:
- 串行75ms → 并行30ms(提升60%)
- 单次查询 → 缓存命中(提升90%)
最佳实践:
- 先监控定位瓶颈
- 从简单优化开始
- 异步、并行、缓存组合使用
个人观点,仅供参考