You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PDF管理API POST请求耗时过长 求助问题排查

问题:PDF管理器POST请求耗时过长甚至超时

我开发了一款PDF管理器,功能是接收PDF文件、解析其中句子,将PDF文件存储到Azure对象存储,句子数据存储到Azure SQL DB。近期突然出现POST请求耗时极长的问题,此前无此现象,通过版本控制也没定位到具体原因。

最初怀疑是数据库问题,但切换到本地数据库后直接出现连接超时。关闭WithTxtFile、WithImages选项后问题依旧,且句子解析逻辑自开发以来未改动。

API方法代码

//(POST) API to post a PDF to the database and parse its sentences
[HttpPost]
[Authorize]
public async Task<ActionResult<List<PDF>>> PostPDF(List<IFormFile> Files, bool? WithImages, bool? WithTxtFile)
{
    List<PDF> ListPDF = new List<PDF>();
    bool _WithImages = WithImages ?? false;
    bool _WithTxtFile = WithTxtFile ?? false;
    foreach(var file in Files)
    {
        if(System.IO.Path.GetExtension(file.FileName) == ".pdf") //Ensure the file being sent is a PDF
        {
            var FileInBytes = ManipulatorPDF.LoadBytePDF(file); //Byte array representing the PDF
            PdfDocument FileLoader = ManipulatorPDF.LoadPDF(file);
            List<Sentences> Sentences = ManipulatorPDF.GetSentences(FileLoader, _WithImages);
            
            //Create a new instance of a PDF with all the required parameters.
            //Save the file instance and sentences in an Azure blob storage using AzureSerices.SaveFile()
            string SentencesInTxt = (_WithTxtFile) ? await AzureServices.SaveFile(ManipulatorPDF.SentencesToText(Sentences), file.FileName.Substring(0, file.FileName.Length - 4)+"_Sentence.txt", "sentences-container") 
            : "This file was not posted with 'WithTxtFile' enabled";
            PDF FileInstance = new PDF(file.FileName, file.Length, FileLoader.Pages.Count, Sentences, await AzureServices.SaveFile(FileInBytes, file.FileName, "pdf-container"), SentencesInTxt);

            DB.Add(FileInstance); //Add an instance of the PDF class to the database
            ListPDF.Add(FileInstance); //Add instance to a list
        }
        else
        {
            return BadRequest("Bad request: Only PDFs are accepted. File(s) sent is not a PDF"); //Return bad request message if a non-PDF is sent
        }
    }
    Cache.Remove("ListPDF"); //Unload the cache after a new post
    await DB.SaveChangesAsync();
    return ListPDF; //Return the list of PDFs representing a successful POST
}

EF Core执行日志

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (58ms) [Parameters=[@p0='?' (Size = 4000), @p1='?' (DbType = Double), @p2='?' (Size = 4000), @p3='?' (DbType = Int32), @p4='?' (Size = 4000), @p5='?' (DbType = DateTime2)], CommandType='Text', CommandTimeout='30']
      SET IMPLICIT_TRANSACTIONS OFF;
      SET NOCOUNT ON;
      INSERT INTO [PDFs] ([FileLink], [FileSize], [Name], [NumberOfPages], [SentencesLinkTxt], [TimeOfUpload])
      OUTPUT INSERTED.[id]

目前的情况是:950kb、约5000词的小PDF用Azure存储时耗时很久,本地数据库直接超时,仅3kb纯文本PDF能成功处理。


排查方向

1. 检查EF Core关联实体的插入逻辑

  • 确认Sentences实体与PDF的关联配置:如果是一对多关系且开启级联插入,几千条Sentences会被EF Core逐条插入,产生大量数据库请求,直接拖慢速度。
  • 查看EF Core是否启用了批量插入支持,默认情况下EF Core不会批量插入关联数据,需要手动配置(比如用第三方扩展包)。
  • 检查DB.Add(FileInstance)后,EF是否在追踪大量Sentences实体,导致内存占用过高和后续SaveChanges时的性能损耗。

2. 优化数据库操作时机与配置

  • 尝试将DB.Add替换为DB.AddRange(ListPDF),减少EF的追踪开销。
  • 调整数据库连接字符串的CommandTimeout参数,当前日志显示是30秒,改为60或120秒,测试本地数据库是否还会超时。
  • 开启EF Core的详细日志,查看插入Sentences表的耗时,确认是不是这部分导致的超时。

3. 单独测试Azure存储与PDF解析的耗时

  • 单独编写测试代码,调用AzureServices.SaveFile上传950kb的PDF文件,记录耗时,确认是否是Azure存储的网络延迟问题。
  • 单独测试ManipulatorPDF.GetSentences解析目标PDF的耗时,即使逻辑没改,也可能存在某些特殊PDF格式导致的隐性性能损耗。

4. 关键步骤计时定位瓶颈

  • 在代码中添加Stopwatch计时,分别测量以下步骤的耗时:
    var watch = System.Diagnostics.Stopwatch.StartNew();
    var FileInBytes = ManipulatorPDF.LoadBytePDF(file);
    watch.Stop();
    Console.WriteLine($"LoadBytePDF耗时: {watch.ElapsedMilliseconds}ms");
    
    watch.Restart();
    PdfDocument FileLoader = ManipulatorPDF.LoadPDF(file);
    watch.Stop();
    Console.WriteLine($"LoadPDF耗时: {watch.ElapsedMilliseconds}ms");
    
    watch.Restart();
    List<Sentences> Sentences = ManipulatorPDF.GetSentences(FileLoader, _WithImages);
    watch.Stop();
    Console.WriteLine($"GetSentences耗时: {watch.ElapsedMilliseconds}ms");
    
    watch.Restart();
    var pdfBlobLink = await AzureServices.SaveFile(FileInBytes, file.FileName, "pdf-container");
    watch.Stop();
    Console.WriteLine($"SavePDFToAzure耗时: {watch.ElapsedMilliseconds}ms");
    
    watch.Restart();
    await DB.SaveChangesAsync();
    watch.Stop();
    Console.WriteLine($"SaveChanges耗时: {watch.ElapsedMilliseconds}ms");
    
  • 通过计时结果直接定位哪一步是性能瓶颈。

内容的提问来源于stack exchange,提问作者Saucter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 23:07:43