请教关于 PHP foreach 长时间运行中断的一个问题

2018-03-26 00:06:08 +08:00
 swuhvxee

接触 PHP 不久,正在学习。现在碰到了这么一个问题。

有一批数据需要读取本地文件,并根据读取出来的每个 id 来请求 API 获取值,然后把值写入数据库。不可避免的用到了 foreach。

但是每次运行一会的时候,浏览器就提示 500---Internal Server Error 错误。php 代码也加上了 set_time_limit(0);ini_set('memory_limit', '-1')。

那么请问,这种情况是因为什么原因呢?是浏览器有默认的超时时间吗,脚本长时间不返回,浏览器就默认给超时了?还是因为超出了内存限制,给中断了?

大家碰到这种需要长时间处理大量数据的时候,是怎么解决的呢?因为是自学,所以没有人指点。有没有函数或者办法,可以解决以下 2 个问题。

1:浏览器超时(可能我描述不准确,但是说的就是浏览器获取不到返回值默认 500 )

2:这种循环太多了,内存肯定不够用的。那么是否可以随用随丢?

4852 次点击
所在节点    PHP
24 条回复
jhdxr
2018-03-26 00:15:24 +08:00
1. 超时不光在 php 这有限制,web server 那同样可能有限制。当然这种场景你现在这么处理的做法可以说就是错的,正确做法(之一)是把任务写到一个队列里去,然后另外在命令行里开一个专门读取然后处理。

2. 可以。文件读取参考 fopen 及相关函数,避免将文件一次性读入内存中。部分场景可以考虑用 generator 来减少内存的使用。占大量内存的数组在不需要时可以手动 unset,这样 GC 就会及时回收了。
swuhvxee
2018-03-26 00:21:50 +08:00
@jhdxr 谢谢,我去查一查
Weny
2018-03-26 00:25:20 +08:00
队列
akira
2018-03-26 00:28:54 +08:00
长时间运行的话,在 php 这边先提前响应数据给页面,然后继续执行后续逻辑代码。
参考 https://www.jianshu.com/p/398792cf0ed5

但是在你这个情况里面,个人感觉不是这个问题,更多的像是你代码出错了,检查下错误日志吧
root123
2018-03-26 00:35:56 +08:00
这种场景就不应该用浏览器去执行,是错的。

1、用 cli 守护进程,如果要提高效率就的配合 pcntl_fork 子进程。

2、用 while (!feof($file)) 分段读取
lsido
2018-03-26 00:51:41 +08:00
这种场景就应该用 Python,捂脸捂脸捂脸捂脸(手动滑稽)
swuhvxee
2018-03-26 02:24:58 +08:00
@akira 代码没错的,500 中断之前,所有的数据处理全部正确,500 之后的数据处理如果分批次执行也正确。应该不是代码的问题
swuhvxee
2018-03-26 02:26:12 +08:00
@root123 谢谢提醒,刚才 google 到了这个问题,跟你说的差不多
shiji
2018-03-26 02:49:06 +08:00
这种情况我一般都是直接在终端里运行 PHP。
DavidNineRoc
2018-03-26 07:13:31 +08:00
PHP 生成器了解一下
mcfog
2018-03-26 07:55:47 +08:00
你应该先学会开 /看 /查错误日志
linzhoulxyz
2018-03-26 08:38:10 +08:00
先查下日志是什么原因造成的 500
solupro
2018-03-26 11:35:03 +08:00
可以试试加上
ignore_user_abort
silencefent
2018-03-26 11:37:45 +08:00
用命令行 php path/index.php XXX/XXX/api 执行 php 方法
dangyuluo
2018-03-26 12:47:07 +08:00
beanstalkd,搞个伺服程序
yytsjq
2018-03-26 13:15:37 +08:00
php-fpm 的 request_terminate_timeout 太小?
eslizn
2018-03-26 13:18:28 +08:00
cli 了解一下
xuechaoc
2018-03-26 15:40:45 +08:00
长时间运行的脚本不应该出现在 web 请求里面,建议使用消息队列等异步方式。或者直接在终端运行脚本。
另外 500 错误一般也不是由于超时导致的,执行时间过长导致的超时,nginx 会返回错误码 504 Gateway Time Out
qce7
2018-03-26 16:56:00 +08:00
500---Internal Server Error

这是代码写错了,开启一下 error_display=on;
swuhvxee
2018-03-26 18:40:37 +08:00
@shiji
@DavidNineRoc
@silencefent
@eslizn
好的,感谢解惑

@qce7
哥,虽然我感谢你的回答,但是你的回答是全部答案里最不靠谱最水的一个。代码错没错我能不知道吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/441331

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX