【问题标题】:Return response to client before running event Laravel在运行事件 Laravel 之前向客户端返回响应
【发布时间】:2019-02-22 05:39:52
【问题描述】:

有没有更丑陋的方法来做到这一点:

ignore_user_abort(true);
set_time_limit(0);

ob_start();
echo $response; // send the response
header('Connection: close');
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();

在 Laravel 中?基本上我需要服务器在运行事件之前向用户返回响应,我不能使用队列来执行此操作,因为要完成很多事情,并且很多客户端同时执行此操作,而这些事情需要完成瞬间,所以不能一一执行。这些事件包括发送邮件、警报、更新网站表格上的数据等。

【问题讨论】:

  • 您的反应如何?通过 API/Web/控制台?多提供一点上下文。顺便说一句,要在完成任务之前回复用户,请使用Queued Jobs。这样,您可以在服务器在后台处理您的工作时继续做您的事情(例如发送电子邮件、延迟操作)。
  • 您能否就您要解决的问题提供一些背景信息?从标题中我可能会建议可终止的中间件或排队的作业,但从问题中不清楚您要实现什么。 (另外,标头总是需要在响应正文之前发送)
  • @TravisBritz Terminable Middleware 是一个选项,我将确切搜索它是如何工作的。但客户端不能等待所有这些事情,我也不能把它放在 com 队列中,因为它会每 1 次完成,但我需要这些脚本同时在服务器上运行多次。
  • 你真的在使用 Laravel 的内置事件调度器吗?如果是这样,你也可以将 implements ShouldQueue 添加到你的事件监听器类中,Laravel 将自动使用作业队列而不是立即运行监听器。
  • 是的,我读过这个问题。 “我不能使用队列”并不具体;为什么某些操作(例如发送电子邮件和警报)不能排队?实现事件/侦听器系统的方法有很多,但是已经探索和排除了哪些选项?您的事件是否有多个侦听器,是否可以将特定的侦听器排队?我只是想更好地了解您的系统的结构,因为一如既往,答案是“视情况而定”。

标签: laravel laravel-5 laravel-5.4 laravel-5.5


【解决方案1】:

我在创建跟踪像素的项目中也有类似的需求。我想立即回复他们,然后 Laravel 继续运行。我把它作为index.php中的第一件事:

if($_SERVER['REQUEST_URI'] == '/pixel'){
    require "pixel.php";
}

然后在该文件中(其中一些可能与您无关,我需要确保他们没有缓存它以便继续加载像素:

ignore_user_abort(true);

// turn off gzip compression
if ( function_exists( 'apache_setenv' ) ) {
    apache_setenv( 'no-gzip', 1 );
}

ini_set('zlib.output_compression', 0);

// turn on output buffering if necessary
if (ob_get_level() == 0) {
    ob_start();
}

// removing any content encoding like gzip etc.
header('Content-encoding: none', true);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    echo ' ';
} else {
    header("Content-type: image/gif");
    header("Content-Length: 42");
    header("Cache-Control: private, no-cache, no-cache=Set-Cookie, proxy-revalidate");
    header("Expires: Wed, 11 Jan 2000 12:59:00 GMT");
    header("Last-Modified: Wed, 11 Jan 2006 12:59:00 GMT");
    header("Pragma: no-cache");

    echo sprintf('%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%',71,73,70,56,57,97,1,0,1,0,128,255,0,192,192,192,0,0,0,33,249,4,1,0,0,0,0,44,0,0,0,0,1,0,1,0,0,2,2,68,1,0,59);
}

// flush all output buffers. No reason to make the user wait for OWA.
ob_flush();
flush();
ob_end_flush();

就是这样。现在,Laravel 继续运行,但是用户的浏览器已经结束了它的请求。因此,我在/pixel 添加了一条正常的路线,并完成了我需要做的所有事情(添加到数据库、触发事件等)。

【讨论】:

    猜你喜欢
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 2016-10-10
    相关资源
    最近更新 更多