【问题标题】:How do I close a connection early in laravel?如何在 laravel 中尽早关闭连接?
【发布时间】:2021-08-06 14:19:41
【问题描述】:

我想在 Laravel 中尽早关闭连接,我发现了问题:

How do I close a connection early?

答案是:

<?php
    ob_end_clean();
    header("Connection: close");
    ignore_user_abort(true); // just to be safe
    ob_start();
    echo('Text the user will see');
    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush(); // Strange behaviour, will not work
    flush(); // Unless both are called !
    // Do processing here 
    sleep(30);
    echo('Text user will never see');
?>

但是 echo 在 Laravel Controller 中不起作用,当我更改为 return 时,后面的代码不会执行。

[更新]

我的问题是:

我有一个耗时的任务需要调用 python 脚本。此任务可能需要 30 到 180 秒。如果我使用 Laravel 中的定时任务或者系统的 Conrtab 定时任务,最糟糕的可能是 Python 脚本只能在 1 分钟后运行。这会让用户多等一分钟,用户体验不是很好。

所以希望早点结束连接,让用户先看到响应,同时调用Python脚本进行任务处理。

目前我使用了两个ajax请求来解决这个问题,其中一个是用来调用python脚本的。

我的问题是知道是否可以在没有额外请求的情况下实现相同的目标,或者是否有更好的解决方案。

【问题讨论】:

  • Aghrrr....该代码不是 laravel'sk,您应该使用队列和作业来解决您的问题,并在异步代码完成后获取数据。
  • @mrhn 非常感谢,不过想知道用 Laravel 能不能解决
  • 不久前的一个答案。它是关于 php-cli 的,对于企业风格的编码来说可能有点脏,但它确实工作得很好,这永远不会引起问题。其实最简单直接的方法,见解释stackoverflow.com/a/57697076/2494754
  • 队列和作业是 laravel 的概念,我可以举个例子,但我需要更多的上下文来解决这个问题。你想让我做什么? Tbh,您提供的代码对于 laravel 应用程序来说非常糟糕,不应该那样实现。
  • fastcgi_finish_request() 完成了这项工作。您可能不应该自己调用它。您可以添加一个中间件并将耗时的任务放在 terminate() 函数中。您也可以考虑使用队列和作业。

标签: php laravel


【解决方案1】:

在你的情况下最好使用 Http

use Illuminate\Support\Facades\Http;

在你的函数中使用这个

$response = Http::timeout(30)->get('https://www.example.com');

您也可以添加更多代码来解决问题

【讨论】:

    【解决方案2】:

    我和你遇到过同样的情况。即异步运行某些脚本以保持快速响应时间。有些方法,比如你提到的那些,没有按预期工作。我也使用过 Spatie\Async 但 php 模块在 apache2 中运行时不起作用。 所以解决方案,我使用 exec 函数来运行它在后台运行的命令行。这可能有点冒险,但小心它可能是最佳做法之一。

    exec('(/path/to/script > /dev/null) &');
    

    【讨论】:

      【解决方案3】:

      您可以尝试使用 HTML5 属性服务器发送事件,链接https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

      传统上,网页必须向服务器发送请求以接收新数据;即页面向服务器请求数据。使用服务器发送的事件,服务器可以随时通过向网页推送消息来向网页发送新数据。这些传入的消息可以被视为网页内的事件+数据。
      您需要在服务器上编写一些代码来将事件流式传输到前端,但客户端代码在处理传入事件方面几乎与 websocket 相同。这是单向连接,因此您不能将事件从客户端发送到服务器。

      【讨论】:

        【解决方案4】:

        我建议将dispatchAfterResponse broadcasting 系统结合使用(例如推杆)。这样,您不仅可以通知客户端开始和结束,还可以通知所有中间步骤,并且您不需要额外的 http 请求。所以整个过程看起来更具交互性。 关于 dispatchAfterResponse 有一些注意事项,必须注意文档中提到的内容,但我相信您可以通过正确的服务器配置来通过 dispatchAfterResponse 的限制。如果您不信任 dispatchAfterResponse,请尝试队列作业。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-09
          • 2014-11-09
          • 1970-01-01
          • 2019-05-10
          • 2017-07-22
          相关资源
          最近更新 更多