【架构实战】接口性能优化:异步化/并行化/缓存化

一、接口性能优化概述

接口性能优化是提升用户体验的关键:

优化方向:

  • 减少等待时间(同步→异步)
  • 并行处理(串行→并行)
  • 减少计算量(缓存、预计算)
  • 减少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%)

最佳实践:

  1. 先监控定位瓶颈
  2. 从简单优化开始
  3. 异步、并行、缓存组合使用

个人观点,仅供参考

相关推荐
阳光是sunny11 小时前
Vue 项目怎么做用户行为全链路监控?轻量插件方案详解
前端·面试·架构
EMA17 小时前
Docker虚拟化失败解决方案
架构
李斯维18 小时前
从历史的角度看 Android 软件架构
android·架构·android jetpack
JouYY20 小时前
聊一下多 Agent 编排架构的应用实践
架构·llm·agent
Sunia20 小时前
《AgentX 专栏》10-生产部署:3台2C4G云服务器把企业级Agent真正跑起来的完整方案
java·架构
ZhengEnCi2 天前
Q01-高并发点赞系统架构设计
架构
笨鸟飞不快2 天前
从 MVC 到 DDD:一次真实的渐进式迁移实录
后端·架构
这个DBA有点耶3 天前
GROUP BY优化全解:如何写出既不丢数据又飞快的分组查询
数据库·mysql·架构
锋行天下3 天前
我试图优化 Vite 的拆包,结果首屏慢了 10 倍
前端·vue.js·架构