事实:后台程序在处理繁重的任务时,调用外部程序异步执行的简单实现

优采云 发布时间: 2020-10-23 12:00

  当后台程序正在处理繁重的任务时,通过调用外部程序来实现异步执行的简单实现

  在开发Web应用程序时,无论是网站还是服务接口,我们都可能遇到来自客户端的特定请求。在此请求的背后,有许多繁重的任务要执行。如果我们在后台程序中同步进行处理,则程序执行时间比较长,用户体验不好,甚至可能导致502执行超时。针对这种情况,有许多成熟的解决方案(根据我的肤浅知识,使用队列是一种更好的解决方案),但是实现略微复杂且麻烦。如果我们对异步执行的任务没有特殊要求(例如异步任务完成后的失败重试或事件回调),那么我们可以通过一种非常简单的方法简单地实现它:nohup命令要执行> / dev / null 2>&1&。

  如果您看到此内容并认为它没有什么新意,则表示您非常擅长,至少[比我更好]。我也希望在您离开之前,告诉我们是否有更好的方法并分享。

  应用场景

  目前,我实际上在两种特定情况下使用了这种异步任务执行方法。

  1、之前是网站,该数据是来自第三方采集的另一位同事的数据,采集需要导入到我的数据库中,所以我在网站中提供了功能,一个用于文件上传和导入的按钮。当同事通过文件上传将采集数据保存在服务器上时,后台程序将读取该文件的内容并基于该数据进行必要的分析,最后通过SQL将分析后的数据写入数据库。此过程的速度或速度取决于数据文件的大小。对于具有数千行数据的文件,最后可能需要一分钟以上的时间才能执行。如果使用传统的同步执行,则从文件上载->数据分析->写入数据库。在整个过程中,浏览器处于圆圈中。如果时间较长,执行将超时并且所有先前的工作都将丢失。因此,这里我采用了异步任务执行方法。数据文件成功上传后,服务器直接响应浏览器,显示“数据导入成功,正在处理”提示,整个前端交互在此处结束。以后的数据分析和对数据库的写入将移交给另一个单独的过程进行处理。

  2、就在两天前,我就是这样写的。我们制作了一个APP(使用API​​Cloud制作的非流入APP)。用户使用APP发布内容后,需要调用百度AI的内容查看界面,以自动查看用户发布的文字和图片。如果发现其中收录错误信息,则不会自动对其进行审核。调用百度界面的过程比较耗时,它主要取决于用户发布的内容中收录的图片数量。自然,百度界面响应速度很慢。同样,如果用户以同步方式发布内容->调用百度界面->等待该界面返回数据->判断评论是否通过,则太耗时,因此从用户的角度来看,内容被发送出去并等待了几秒钟,甚至十秒钟,直到最后没有响应为止,这种用户体验太糟糕了。因此,可以实现,当用户发布内容时,立即提示“发布成功且正在审核中”,几秒钟后,用户将看到他刚刚发布的内容已被批准并出现在内容列表。时间,多么自然的过程。

  实现思路

  因此,有时有必要异步处理任务。正如我们在开始时提到的那样,在Web应用程序的开发中,不可能跳出Linux服务器。如今,除了.NET系统,它也可能部署在Windows上[似乎没有Blog Garden]。其他后端应用程序基本上将部署在Linux上,而我们开头提到的实现方法是在Linux下执行命令。

  首先,实现程序异步执行的方式大致有两种:线程和进程[关于它,因为我听说有些语言也支持协程。好?我勒个去? -_- !!!]。对于支持线程的Java之类的编程语言,异步执行可以通过线程或进程[Runtime.exec()]实现;对于PHP,默认情况下没有线程,这对每个人都是通用的,而且不要在PHP下使用线程,因此,这只能通过其内部函数调用外部进程来实现异步任务。

  在PHP下,执行一个外部程序,并要求该外部程序在后台运行,并且不会让您的宿主程序挂起[宿主是执行对外部命令的调用的PHP程序],有一点特别之处,请注意,这在官方手册的exec函数中有专门提及:

  如果使用此功能启动程序,则要使其在后台继续运行,必须将程序的输出重定向到文件或其他输出流。否则,PHP会挂起,直到程序执行结束。

  表示为了使外部程序在后台运行,此外部程序的输出[指标准输出[如Python中的打印,PHP中的echo和Java中的System.out.print]和标准错误]必须重定向到文件或另一个输出流。否则,宿主程序可能会挂起并等待外部程序执行完成,然后终止其生命周期。

  因此,文章开头提到的命令中的> / dev / null 2>&1用于重定向标准输出和标准错误,并将它们写入/ dev / null文件,以制作主机程序。调用外部程序并使其在后台运行,它将立即执行后续代码,直到结束为止,并可以快速结束其生命周期。此时,外部程序仍在静默运行。

  在撰写本文文章之前,我还专门检查了Java下使用Runtime.exec()调用外部程序的实现,发现文章提到了这一点:

  这意味着重定向外部程序的输出,这与PHP官方手册中提到的注意事项完全相同。

  具体实现

  接下来,我们将解释nohup将执行的命令> / dev / null 2>&1&此命令的含义。

  首先,它是要执行的命令。例如,如上所述,请致电百度AI进行内容审核,然后该命令就像php / www / wwwroot / app_service / artisan baidu:censor 文章 ID。此处使用的PHP Laravel框架,取决于您使用哪种语言,哪种框架以及如何编写要执行的命令,这取决于您的情况。

  第二,如果要让程序在后台运行,则需要在命令后添加&[即,&],以告诉系统我要执行的命令是需要在其中运行的程序。背景。

  然后,为了防止我们的主机程序等待挂起,我们需要重定向外部程序的输出,因此我们添加了> / dev / null 2>&1,> / dev / null意味着重定向标准输出到/ dev / null文件,以下2>&1表示将标准错误重定向到与先前标准输出相同的位置。 / dev / null是不存在的文件,因此> / dev / null 2>&1的总体含义是,当执行此外部程序时,将生成所有标准输出和标准错误[即错误消息]通过它,不要保存它们。 ,我不想看到。当然,如果您在调用外部程序后发现外部程序未按预期执行,则可能是外部程序报告了错误。您可以将输出重定向到真实文件中,以保存外部程序的输出信息,以方便进行故障排除。

  最后,nohup。当您指定&以使外部程序在后台运行时,如果此时关闭并退出终端[这是黑色的命令行窗口],那么您刚刚在后台运行的外部程序也将终止。为避免此问题,您需要在开始时添加nohup来告诉系统关闭或退出终端时,请勿杀死我刚刚执行的外部程序的后台进程! ! !

  好的,已经明确解释了用于特定实现的命令。如何用各种语言实现它们?我相信每种语言都有一种调用外部程序的方法,您可以自己学习。我再使用PHP,最后我将发布PHP的实现方法:

  exec('nohup php / www / wwwroot / app_service / artisan baidu:censor 文章 ID> / dev / null 2>&1&');【Laravel】

  exec('nohup php /www/wwwroot/app_service/baidu_censor.php 文章 ID> / dev / null 2>&1&');

  参考文章

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线