作者GALINE (天真可爱CQD)
看板PHP
标题Re: [请益] 背景执行相关问题
时间Wed Feb 5 03:24:31 2020
※ 引述《b90022790 (PomeloLaLa)》之铭言:
: 各位php板上的各位前辈好!
: 目前在架设一个简单的订单系统,有个功能无法顺利完成,希望前辈们能给些意见,谢谢
: 环境:php7.4.1、 MySQL、CentOS 6.8
: 功能:当商家按钮确认订单後,除了修改MySQL内容外,希望能够寄mail通知客户
: 问题:使用PHPMailer接gmail SMTP,然而速率过慢,商家的client端需要等待执行完毕
: 才能看到确认後的结果,希望能先让商家看到结果,寄信的功能在伺服器背景执行。
: 试过的解决方式:先写一个send.php专门处理寄信的功能,在商家client的页面直接显示
: 确认订单後的结果画面,并在商家该php页面使用system()执行send.php,程式码如下:
: system("php send.php user"); //user为收信者参数
: 然而这仍然会等待执行完才会回responce。
: 使用「php 背景执行 超时」当关键字,采用将结果输出到.out,改system()程式码如下:
: system("php send.php user > MAIL.out");
: 然而这样却变成连寄信都没有执行就结束了。
: 希望前辈们能给一些如何处理该功能的意见,以及为何该system()无法正常执行
: 谢谢各位前辈!还请各位指点!!
php send.php user > MAIL.out
只会把 send.php 的输出(stdout)写进 MAIL.out,没有非同步执行的效果
结果会不一样,也许是 wwwuser 没有资料夹写入权限,所以指令直接喷掉
要非同步执行东西,直觉是 pcntl_fork()
$pid = pcntl_fork();
if ($pid === 0) {
// 我是 fork 出来的 process,不会卡住娘亲 process 执行
// 在这里寄信
system("php send.php user");
exit; // 寄完信就 exit,不然会一路执行到网页内容整个印出来
}
// 我是原本的 process,或是 fork 失败
// 继续做网页该做的事情
缺点是不熟的人容易不小心写出惊人的 bug
像是不小心 fork 了一万个 process 然後整台机器被 process 噎死
这算是妖术,土炮或是很小的东西可以这麽干
如果工作上有人对网页服务发这样的 MR 给我 review,我会热烈地给予关切
推荐做法是,不要在网页里面直接处理这件事
把你要寄信的资料先记录在某个地方,档案也好 DB 也好。
然後跑一只其他的程式在後面等着,或是设定 cron job 定时去读
看到有资料的时候依序寄信然後把资料清空,如果没有新资料就回去睡觉
更上道的做法,是去研究 message queue / job queue
============
另,如果想用 PHP 写 cli 指令,有个小地方可以参考
像这样透过第一行的 hashbang 告诉 shell 要呼叫 php 来执行这只程式
#!/usr/bin/env php
<?php
echo "I am a command\n";
然後把这只 php 设定为可执行档案
$ chmod +x command.php
就可以把这只 code 当成 shell script 来跑了
$ ./command.php
I am a command
--
无重力,万岁
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 111.254.20.150 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/PHP/M.1580844275.A.F02.html
1F:推 b90022790: 非常谢谢您的回文,让我学到不少东西跟想法。目前已经 02/05 16:44
2F:→ b90022790: 确认是我真的忘了更改档案写入的权限XD,然後加一个&在 02/05 16:44
3F:→ b90022790: 指令的後面让Linux在背景执行,这已经可以达成目的。 02/05 16:44
4F:→ b90022790: 其他您提到的方法,在未来我会努力将其实现到我的专案 02/05 16:46
5F:→ b90022790: 里,希望能够成为像您一样有经验、有想法的工程师,谢 02/05 16:46
6F:→ b90022790: 谢您! 02/05 16:46
7F:推 kancu: 我也建议把寄信的部份由另一支程式定期处理,用&来丢背景其 02/06 16:15
8F:→ kancu: 实是一件很恐布的事情,如果寄信的那支php没写好,伺服器上 02/06 16:16
9F:→ kancu: 很有机会不断的累积被强制丢在背景执行的寄信用程式,然後 02/06 16:17
10F:→ kancu: 等累积到一定程度,主机就当了 02/06 16:18
11F:→ kancu: 另一方面,这种丢背景的方式等於提供了一种资安攻击的方法 02/06 16:20
12F:→ kancu: 只要不断的在商店端一直丢完成的讯号,背景执行的程式就会 02/06 16:21
13F:→ kancu: 一直累积(因为你都说接gmail SMTP很慢,所以一定会累积), 02/06 16:22
14F:→ kancu: 然後主机就当掉了 02/06 16:22
15F:推 kancu: 用另一只程式来跑还有可以简单平行处理的优点,用OpenMP来 02/06 16:25
16F:→ kancu: 平行处理寄信的问题,即使累积很多要寄的资料也可以很快 02/06 16:26
修错字...
※ 编辑: GALINE (60.248.122.206 台湾), 02/07/2020 16:34:38
17F:→ JohnRoyer: 我记得原 PO 有 fork 到机器炸掉的记录 XD 04/21 11:35
18F:→ JohnRoyer: Github 其实有一些不错用的套来管理 fork /process 04/21 11:35
19F:→ JohnRoyer: 像是 neovim/neovim 感觉就还不错用 04/21 11:36
20F:推 JohnRoyer: 抱歉贴错了,这个才是处理 fork 的: 04/21 11:45
21F:→ JohnRoyer: github kriswallsmith/spork 04/21 11:45