有很多方法可以做到这一点。您使用哪一种在很大程度上取决于您的特定需求和技能(例如,您需要多快完成后台进程以便将输出提供给用户,您的整个应用程序中包含哪些其他技术,您的技能是什么)是,等等)
我知道这不是一个完整的答案,但我会告诉你前段时间遇到类似问题时我做了什么。我希望它可以作为一个起点或至少作为一个想法。
问题:
就像您自己一样,我需要用户能够将一些数据发布到我的后端。这些数据(不是大块,只有 5-7 个字段)在发布时需要首先存储在一个表中,然后触发一个需要大约 30 秒才能完成的巨大过程。在这 30 秒内,我需要用户能够继续使用应用程序(而不是坐在那里等待控制器完成 30 秒的过程)。
为了让它更复杂一点,我的客户要求在发布时,用户应该留在当前页面(所以不要发布,然后在用户的浏览器中重新绘制视图)。
方法:
1.- 我的客户的请求相当简单:表单将通过 Ajax 发布。我不喜欢复杂的 JS 库,这些库对我的大多数项目来说都是多余的(而且有点老派的人),我只是让表单由一个简单的 vanilla JS 脚本处理,该脚本将采用表单数据,将其发布到我的控制器,并在控制器成功响应后(大约 100 毫秒),会提醒用户一切都很好,让他继续。
为了获得快速响应,接收 Ajax 数据的控制器只需执行以下操作:
一个。运行表单验证(从不相信用户输入)
湾。将表单数据存储到表中
C。安排硬处理,使其异步发生。下一节将详细介绍这一点
2.- 异步处理更具挑战性。以下是我的做法。
我创建了一个信号量表,它引用了另一个表上的表单数据(我们称它们为semaphore 和user_posts)。信号量表相当简单:一个唯一 ID 字段、一个引用数据所在的唯一 ID user_posts 的字段、一个状态字段(可能的状态为pending、working、complete、failed)插入日期和最后更新日期。
接下来,我设置了一个单独的控制器(创造性地命名为 Cron),该控制器仅在从 CLI 调用时才起作用(Codeigniter 文档解释了如何做到这一点),并使用各种可以完成实际工作的方法。每当 cron 守护进程醒来并调用主要的 manager 方法时,该方法将检查 semaphore 表中的任何 pending 行并选择最旧的行。然后它会将其交给worker 方法,然后将其标记为working 并开始处理数据。处理后,该行将被标记为complete(或failed,这将触发我不需要在这里解释的其他操作)并重新进入睡眠状态。
更多信息
cron 守护进程每 5 分钟唤醒一次 manager。最初,当我的客户端的应用程序流量较低时,处理负载已经绰绰有余(大多数时候,manager 会醒来,看到没有待处理的东西并重新进入睡眠状态)。随着流量的增长和信号量开始成为一个不断增长的待处理项目队列,我们做了一些工作以允许worker 的多个实例由manager 产生并并行运行,每个实例都在不同的信号量行上工作.最终,每 5 分钟唤醒 cron 守护程序之间排队的工作量变得如此之大,以至于我们需要将调度更改为 1 分钟间隔,并设置一个专用的 cron 服务器来处理负载而不影响站点的性能(请记住,处理每个数据集大约需要 30 秒)。
嗯,这可能不是您期望的答案(我对此有保密协议,因此我无法提供具体代码),但正如我之前所说,这至少可以让您了解如何解决这。还有许多其他方法可以解决此类问题。这只是其中之一