想问一个关于在 laravel 里异步执行代码的简单方法 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zengguibo
V2EX    PHP

想问一个关于在 laravel 里异步执行代码的简单方法

  •  
  •   zengguibo 2023-06-21 19:37:03 +08:00 3020 次点击
    这是一个创建于 847 天前的主题,其中的信息可能已经有所发展或是发生改变。

    class AdminController extends BaseAdminController {

    public function __construct() { } public function store(Request $request) { //下面的代码放在后台运行 UserModel::insert($data); //直接返回成功 $this->succss(['desc' => '成功']); } 

    } 就是前台调用这个 api 的时候,UserModel::insert($data);这一段放在后台运行,而函数直接返回成功,用队列什么的有点重了,有没有简单点的方法

    20 条回复    2023-07-07 17:24:58 +08:00
    ysc3839
        1
    ysc3839  
       2023-06-21 19:43:44 +08:00 via Android   2
    没办法。PHP 官方至今还是只支持传统的 CGI 模式,即有请求来了就从头执行脚本,直到脚本退出才算请求完成。因此只要后台执行的代码不退出,客户端的请求就不会完成,会一直等着。
    zengguibo
        2
    zengguibo  
    OP
       2023-06-21 19:46:38 +08:00
    @ysc3839 感谢你的回复,这个问题我研究了很久也没找到方法,对于这种运行时间太长的 api ,只能用队列的方式了吗
    yesC
        3
    yesC  
       2023-06-21 19:48:53 +08:00
    Laravel 的中间件中有个 terminate 方法,可以在把数据响应给客户端后,做一些逻辑处理。
    wangxinhui419
        4
    wangxinhui419  
       2023-06-21 19:49:31 +08:00   2
    vjnjc
        5
    vjnjc  
       2023-06-21 19:57:36 +08:00
    PHP 的本质上是单个 request 走到底,没有线程池
    异步依赖于 redis 这种中间件
    xiaoxuan6
        6
    xiaoxuan6  
       2023-06-21 20:02:18 +08:00
    为什么最近老是遇到问这种问题的?既然用 php 了就别纠结这个问题,直接用队列简单方便
    https://learnku.com/laravel/t/78187
    via
        7
    via  
       2023-06-21 22:06:43 +08:00 via iPhone
    我把队列包装了一下,直接把一个函数传递过去就可以了,下面是调用方法:

    Async::run(function(){ /* your code here */ });
    dedemao
        8
    dedemao  
       2023-06-21 22:25:35 +08:00
    dedemao
        9
    dedemao  
       2023-06-21 22:32:03 +08:00
    ```
    $pid = pcntl_fork();
    if ($pid == -1) {
    die('could not fork');
    } else if ($pid) {
    //下面的代码放在后台运行
    UserModel::insert($data);
    pcntl_wait($status);
    } else {
    //直接返回成功
    $this->success(['desc' => '成功']);
    }
    ```
    james122333
        10
    james122333  
       2023-06-21 22:40:22 +08:00 via Android
    楼上正解 不过不只如此
    楼上应该不用讲 框架使用者通常都这样
    westoy
        11
    westoy  
       2023-06-21 22:42:29 +08:00
    扔队列, 让消费者去消化

    就算原生协程的方案, 这种操作一样是扔队列的

    不然被人 C 一下, 这种高耗操作不做任何限制就直接打到上游了
    james122333
        12
    james122333  
       2023-06-21 22:44:21 +08:00 via Android
    对他们而言 没招可放是很常见的 偏偏混的很好
    westoy
        13
    westoy  
       2023-06-21 23:19:53 +08:00
    @james122333

    当年 php 官方的态度就是,pcntl 你在 cli 下面用用就好了, 别拿去在 web 下面跑

    我还以为十几年没写过 php , 官方转性了, 也没啊

    这种常识现在都成冷知识了?

    https://www.php.net/manual/en/intro.pcntl.php


    """
    Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination. Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.
    """

    --enable-pcntl Enable pcntl support (CLI/CGI only)
    james122333
        14
    james122333  
       2023-06-21 23:25:55 +08:00 via Android
    @westoy

    不是冷门 但对某些人想破头都不知 他们的知识面被限
    james122333
        15
    james122333  
       2023-06-21 23:28:28 +08:00 via Android
    不管如何他们都还是会解决 只是解法很不漂亮然后不怎么好而已
    veike
        16
    veike  
       2023-06-21 23:48:41 +08:00
    insert 放在后置操作方法里,但是这样要解决什么问题?
    demoshengxw
        17
    demoshengxw  
       2023-06-21 23:53:23 +08:00 via iPhone
    我看到有多进程的,但是多进程是不可以宅 fpm 里使用的。但是有一个把 insert 那段代码放在 fastcgi_finish_request 之后执行
    thinkingbullet
        18
    thinkingbullet  
       2023-06-22 09:24:23 +08:00
    public function store(Request $request)
    {
    //直接返回成功
    $this->success(['desc' => '成功']);
    // 此函数会让后面的操作在后台静默运行,仅限于 nginx+php
    fastcgi_finish_request();
    //下面的代码放在后台运行
    UserModel::insert($data);

    }
    flyqie
        19
    flyqie  
       2023-06-22 15:30:06 +08:00 via Android
    php 执行异步代码想不做队列还是歇歇吧。

    任何语言执行异步请求最稳妥的办法都是搞队列或者任务池。。
    guanguans
        20
    guanguans  
       2023-07-07 17:24:58 +08:00
    简单一点 afterResponse 就可以了。也可以用 terminate 中间件。原理一样都是 fastcgi_finish_request 。

    ```php
    dispatch(function () {
    // UserModel::insert($data);
    })->onConnection('sync')->afterResponse();
    ```
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2991 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 51ms UTC 00:29 PVG 08:29 LAX 17:29 JFK 20:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86