如何提升Spring Boot的RPS?百万请求场景下仅达300RPS
优化Spring Boot调用第三方API的RPS方案
1. 调整HttpClient连接池核心配置
当前的setMaxConnPerRoute(200)是单域名路由的最大连接数,如果所有请求都指向同一个第三方API域名,这个值会成为并发瓶颈。建议将其调高至接近maxConnTotal的数值,同时补充超时和连接存活配置,避免资源浪费:
CloseableHttpClient httpClient = HttpClients.custom() .setMaxConnTotal(2000) .setMaxConnPerRoute(1500) // 匹配第三方API域名的单路由并发上限,按需调整 .setConnectionTimeToLive(30, TimeUnit.SECONDS) // 自动回收闲置连接 .setDefaultRequestConfig(RequestConfig.custom() .setConnectTimeout(5000) // 连接建立超时5秒 .setSocketTimeout(10000) // 响应读取超时10秒 .setConnectionRequestTimeout(2000) // 连接池取连接超时2秒 .build()) .build();
同时必须确保请求完成后正确释放资源,用try-with-resources包裹CloseableHttpResponse,避免连接泄漏耗尽池资源。
2. 替换@Async默认线程池
默认@Async使用的SimpleAsyncTaskExecutor会频繁创建销毁线程,效率极低,必须自定义高效线程池:
@Configuration @EnableAsync public class AsyncConfig { @Bean(name = "apiCallExecutor") public Executor asyncApiExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(600); // 常驻核心线程数 executor.setMaxPoolSize(1200); // 最大可扩容线程数 executor.setQueueCapacity(3000); // 任务缓冲队列 executor.setThreadNamePrefix("ApiCall-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略:避免丢任务,让调用线程兜底执行 executor.initialize(); return executor; } }
使用时指定自定义线程池:@Async("apiCallExecutor")。注意server.tomcat.threads.max是Tomcat的Web请求处理线程数,和异步调用线程池无直接关联,保持合理值即可。
3. 排查第三方API限流瓶颈
RPS无法突破很可能是第三方API自身的单IP限流(比如限制单IP RPS为300),此时本地配置再优化也无效。可以:
- 直接用curl/Postman压测第三方API,确认其能支持的最高RPS
- 联系第三方确认限流规则,若允许则使用代理池切换多IP发起请求
4. 系统与网络层面优化
- JVM参数调优:加大堆内存(如
-Xmx4g -Xms4g),启用G1垃圾收集器减少停顿,避免GC拖慢并发效率 - Linux内核TCP优化:修改系统参数减少TIME_WAIT连接堆积,提升连接复用率:
echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf echo "net.ipv4.tcp_fin_timeout = 30" >> /etc/sysctl.conf echo "net.core.somaxconn = 2048" >> /etc/sysctl.conf sysctl -p - 序列化优化:用Jackson的非阻塞模式处理JSON,或改用Protobuf替代JSON,减少请求响应的序列化开销
5. 批量请求优化(若第三方支持)
如果第三方API提供批量接口(比如一次请求处理10条数据),将100万次单请求合并为10万次批量请求,可直接将RPS提升一个数量级,这是效率最高的优化方式。
6. 监控定位瓶颈
用工具精准定位阻塞点:
- 用Arthas/VisualVM监控线程池状态,查看是否有队列满、线程阻塞的情况
- 统计HttpClient连接池指标(空闲连接数、等待连接的请求数),确认连接池是否够用或存在泄漏
- 通过Spring Boot Actuator的
executor.*指标,监控异步任务的活跃线程数、队列积压量
内容的提问来源于stack exchange,提问作者anks
相关产品推荐
相关产品推荐

