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
相关产品推荐
相关产品推荐

