如何加快固定分页产品API多次调用的数据获取速度
解决方案
你的场景完全适合用并发异步请求提速,核心思路是先拿第一页获取总数据量,算出所有需要请求的offset,再控制并发量同时发起多个请求,全部返回后合并数据即可,可大幅降低串行请求的IO等待耗时。
需要注意两个核心前提:
- 接口没有限制同一客户端的并发请求数,建议先把并发数控制在5-10测试,不要一下子拉满导致被接口限流拒绝
- DataTable不是线程安全的,不要在并发请求过程中直接写同一个DataTable,等所有请求返回后再串行合并数据即可
改造后代码示例
// 需额外引入命名空间 using System.Threading; protected async void FSL_Sync_btn_Click(object sender, EventArgs e) { // 并发控制,最多同时发起10个请求,可根据接口实际限流规则调整 const int maxConcurrentRequests = 10; const int pageSize = 20; DataTable resTbl = CreateDt(); int total = 0; try { // 先请求第一页,获取总数据量 var firstPageData = await GetFSLData("0", "Products"); var firstPageResult = JObject.Parse(firstPageData); Int32.TryParse(firstPageResult.SelectToken("total").ToString(), out total); // 先合并第一页数据 resTbl = WriteInDataTable(resTbl, firstPageResult); // 总数据不足1页直接走入库流程 if (total <= pageSize) { goto InsertToDb; } // 计算剩余所有需要请求的offset var offsets = Enumerable.Range(1, (total - 1)/pageSize) .Select(x => x * pageSize) .ToList(); // 用SemaphoreSlim控制并发数,避免超过接口阈值 using var semaphore = new SemaphoreSlim(maxConcurrentRequests); var tasks = offsets.Select(async offset => { await semaphore.WaitAsync(); try { var data = await GetFSLData(offset.ToString(), "Products"); return JObject.Parse(data); } finally { semaphore.Release(); } }).ToList(); // 等待所有请求完成 var allResults = await Task.WhenAll(tasks); // 串行合并所有返回结果到DataTable,避免线程安全问题 foreach (var result in allResults) { resTbl = WriteInDataTable(resTbl, result); } } catch (Exception ex) { var msg = ex.Message; // 可在此补充异常处理逻辑,比如记录请求失败的offset后续补拉,或增加重试机制 } InsertToDb: // 走你原有存储过程入库的独立流程即可 }
额外优化提示
- 总数据量1500条的话,实际只需要75次请求即可拉完,不是你计算的700次,按10并发的话正常几秒就能完成全量数据拉取
- 可增加请求失败重试逻辑,遇到网络波动、接口限流报错时自动重试对应offset的请求,避免单次请求异常导致同步失败
内容的提问来源于stack exchange,提问作者JmukhadzeT
相关产品推荐
相关产品推荐

