在我的应用程序服务上处理文件的替代方案
Alternative to processing files on my app service
我目前正在使用我的应用程序服务来处理文件。我正在上传 Excel 个文件并使用 PhpSpreadsheet 处理它们。
在本地,他们将在不到 90 秒的时间内完成(笔记本电脑、SSD、i7、16GB RAM)。在我的应用程序服务(小型 Linux 计划)中,相同的文件和脚本可能需要 10 分钟以上的时间。这会导致 504 网关超时错误。然后我在数据库中手动确认数据上传。
有什么方法可以替代这种处理文件的方式?
编辑#1
通过处理,我的意思是上传一个 Excel 文件,遍历行,提取数据并使用 PhpSpreadsheet 更新数据库。我当前的文件是 102KB,有 4300 行,23 列,大约需要 6 分钟。在本地,只有几秒钟。
示例:
if ($this->request->is('post'))
{
$file = $this->request->getData()['my_file'];
$path = TMP.time()."_".$file->getClientFileName();
$file->moveTo($path);
$spreadsheet = IOFactory::load($path);
$sheetData = $spreadsheet->getActiveSheet()->toArray(null, false, true, true);
foreach($sheetData as $sheet_row)
{ ... }
}
评论提供了一些关于基本选项的好想法,简要总结:
- 使用更快的服务器
- 使您的算法更快地解析您的文件(无论它是什么)。
两者都可能在短期内缓解您的问题。但是,假设您的算法是 well-optimized 并且您的服务器的速度与您愿意支付的速度一样快,这两者对您来说可能都是正确的,并且在 real-world 情况下通常也是如此。我们还假设您的文件大小有些不可预测,因此即使 well-optimized 并且速度很快,您也可能需要支持处理速度较慢的较大文件的异常情况。
听起来您的工作流程是(同步):
- 客户端使用 Excel 文件向服务器发送 HTTP 请求
- PHP 服务器运行文件解析
- 服务器 returns 一个 HTTP 200(正常)和解析完成后的文件。如果请求花费 > 600 秒(或任何超时时间),它将超时并且 returns 504.
我同意建议删除第 2 步并将其放入 background-job processing 的评论。这将使您的工作流程看起来像:
- 客户端使用 Excel 文件向服务器发送 HTTP 请求
- 服务器将 Excel 文件异步发送到后台作业处理器,开始处理但不等待它完成。
- 服务器 returns HTTP“201 已创建”表示服务器已开始处理文件。
- 客户端每
n
秒轮询一次服务器上的作业状态端点以检查作业是否完成
有很多不同的方法可以做到这一点(上面的后台处理 link 详细介绍了一些 Azure-esque 方法)。
我能想到的一个 Azure-centric 方法是使用 function app triggered by a queue。在这种情况下,您的服务器可以接受一个 Excel 文件,将其保存在某处(或者您的客户端可以将其直接上传到 Azure Blob 存储),然后向您的队列添加一个条目,说明要处理的文件在哪里.使用队列触发器,这可以自动触发您的功能应用程序代码,它可以从您的队列中提取最旧的消息,找到要处理的文件,在尽可能多的时间内处理它,然后上传“处理过的” " 文件返回到 blob 存储以供客户端使用。
我对 PHP 后台作业工具知之甚少,因此 Azure-ness 以上建议,但肯定有许多其他方法可以完成上面提出的相同基本工作流,并且好处以上是你可以使用基本上任何你想要的语言来实现它,核心架构保持不变。
我目前正在使用我的应用程序服务来处理文件。我正在上传 Excel 个文件并使用 PhpSpreadsheet 处理它们。
在本地,他们将在不到 90 秒的时间内完成(笔记本电脑、SSD、i7、16GB RAM)。在我的应用程序服务(小型 Linux 计划)中,相同的文件和脚本可能需要 10 分钟以上的时间。这会导致 504 网关超时错误。然后我在数据库中手动确认数据上传。
有什么方法可以替代这种处理文件的方式?
编辑#1
通过处理,我的意思是上传一个 Excel 文件,遍历行,提取数据并使用 PhpSpreadsheet 更新数据库。我当前的文件是 102KB,有 4300 行,23 列,大约需要 6 分钟。在本地,只有几秒钟。
示例:
if ($this->request->is('post'))
{
$file = $this->request->getData()['my_file'];
$path = TMP.time()."_".$file->getClientFileName();
$file->moveTo($path);
$spreadsheet = IOFactory::load($path);
$sheetData = $spreadsheet->getActiveSheet()->toArray(null, false, true, true);
foreach($sheetData as $sheet_row)
{ ... }
}
评论提供了一些关于基本选项的好想法,简要总结:
- 使用更快的服务器
- 使您的算法更快地解析您的文件(无论它是什么)。
两者都可能在短期内缓解您的问题。但是,假设您的算法是 well-optimized 并且您的服务器的速度与您愿意支付的速度一样快,这两者对您来说可能都是正确的,并且在 real-world 情况下通常也是如此。我们还假设您的文件大小有些不可预测,因此即使 well-optimized 并且速度很快,您也可能需要支持处理速度较慢的较大文件的异常情况。
听起来您的工作流程是(同步):
- 客户端使用 Excel 文件向服务器发送 HTTP 请求
- PHP 服务器运行文件解析
- 服务器 returns 一个 HTTP 200(正常)和解析完成后的文件。如果请求花费 > 600 秒(或任何超时时间),它将超时并且 returns 504.
我同意建议删除第 2 步并将其放入 background-job processing 的评论。这将使您的工作流程看起来像:
- 客户端使用 Excel 文件向服务器发送 HTTP 请求
- 服务器将 Excel 文件异步发送到后台作业处理器,开始处理但不等待它完成。
- 服务器 returns HTTP“201 已创建”表示服务器已开始处理文件。
- 客户端每
n
秒轮询一次服务器上的作业状态端点以检查作业是否完成
有很多不同的方法可以做到这一点(上面的后台处理 link 详细介绍了一些 Azure-esque 方法)。
我能想到的一个 Azure-centric 方法是使用 function app triggered by a queue。在这种情况下,您的服务器可以接受一个 Excel 文件,将其保存在某处(或者您的客户端可以将其直接上传到 Azure Blob 存储),然后向您的队列添加一个条目,说明要处理的文件在哪里.使用队列触发器,这可以自动触发您的功能应用程序代码,它可以从您的队列中提取最旧的消息,找到要处理的文件,在尽可能多的时间内处理它,然后上传“处理过的” " 文件返回到 blob 存储以供客户端使用。
我对 PHP 后台作业工具知之甚少,因此 Azure-ness 以上建议,但肯定有许多其他方法可以完成上面提出的相同基本工作流,并且好处以上是你可以使用基本上任何你想要的语言来实现它,核心架构保持不变。