
接触 PHP 不久,正在学习。现在碰到了这么一个问题。
有一批数据需要读取本地文件,并根据读取出来的每个 id 来请求 API 获取值,然后把值写入数据库。不可避免的用到了 foreach。
但是每次运行一会的时候,浏览器就提示 500---Internal Server Error 错误。php 代码也加上了 set_time_limit(0);ini_set('memory_limit', '-1')。
那么请问,这种情况是因为什么原因呢?是浏览器有默认的超时时间吗,脚本长时间不返回,浏览器就默认给超时了?还是因为超出了内存限制,给中断了?
大家碰到这种需要长时间处理大量数据的时候,是怎么解决的呢?因为是自学,所以没有人指点。有没有数或者办法,可以解决以下 2 个问题。
1:浏览器超时(可能我描述不准确,但是说的就是浏览器获取不到返回值默认 500 )
2:这种循环太多了,内存肯定不够用的。那么是否可以随用随丢?
1 jhdxr Mar 26, 2018 1. 超时不光在 php 这有限制,web server 那同样可能有限制。当然这种场景你现在这么处理的做法可以说就是错的,正确做法(之一)是把任务写到一个队列里去,然后另外在命令行里开一个专门读取然后处理。 2. 可以。文件读取参考 fopen 及相关函数,避免将文件一次性读入内存中。部分场景可以考虑用 generator 来减少内存的使用。占大量内存的数组在不需要时可以手动 unset,这样 GC 就会及时回收了。 |
3 Weny Mar 26, 2018 队列 |
4 akira Mar 26, 2018 长时间运行的话,在 php 这边先提前响应数据给页面,然后继续执行后续逻辑代码。 参考 https://www.jianshu.com/p/398792cf0ed5 但是在你这个情况里面,个人感觉不是这个问题,更多的像是你代码出错了,检查下错误日志吧 |
5 root123 Mar 26, 2018 这种场景就不应该用浏览器去执行,是错的。 1、用 cli 守护进程,如果要提高效率就的配合 pcntl_fork 子进程。 2、用 while (!feof($file)) 分段读取 |
6 lsido Mar 26, 2018 via iPhone 这种场景就应该用 Python,捂脸捂脸捂脸捂脸(手动滑稽) |
9 shiji Mar 26, 2018 这种情况我一般都是直接在终端里运行 PHP。 |
10 DavidNineRoc Mar 26, 2018 via Android PHP 生成器了解一下 |
11 mcfog Mar 26, 2018 via Android 你应该先学会开 /看 /查错误日志 |
12 linzhoulxyz Mar 26, 2018 先查下日志是什么原因造成的 500 |
13 solu Mar 26, 2018 可以试试加上 ignore_user_abort |
14 silencefent Mar 26, 2018 用命令行 php path/index.php XXX/XXX/api 执行 php 方法 |
15 dangyuluo Mar 26, 2018 beanstalkd,搞个伺服程序 |
16 yytsjq Mar 26, 2018 php-fpm 的 request_terminate_timeout 太小? |
17 eslizn Mar 26, 2018 cli 了解一下 |
18 xuechaoc Mar 26, 2018 长时间运行的脚本不应该出现在 web 请求里面,建议使用消息队列等异步方式。或者直接在终端运行脚本。 另外 500 错误一般也不是由于超时导致的,执行时间过长导致的超时,nginx 会返回错误码 504 Gateway Time Out |
19 qce7 Mar 26, 2018 500---Internal Server Error 这是代码写错了,开启一下 error_display=on; |
20 swuhvxee OP @shiji @DavidNineRoc @silencefent @eslizn 好的,感谢解惑 @qce7 哥,虽然我感谢你的回答,但是你的回答是全部答案里最不靠谱最水的一个。代码错没错我能不知道吗 |
21 joeke Mar 26, 2018 可以尝试一下 迭代器啊 ,占用内存小,再加一个 set_time_limit(0) |
22 感觉楼主的应用是实时渲染,但是又有大量的 IO 请求。实际上可以做成异步,crontab 做个定时。 关于 foreach 的停止,可能是超时或者异常引起的,如果是 php7,可以用 try catch 捕获来防止这种问题。 如果数量非常多的话,可以考虑对文件内容做个分割,通过 fork 子进程来处理。 如果做成异步轻量级的应用,可以考虑用 redis 做个缓存或者直接文件缓存。 |
23 qce7 Mar 27, 2018 nginx 500,你看你现在连是哪行代码抛出异常都不清楚,就去优化,这难道不应该去开错误显示或者日志吗吗。。。 |
24 NowTime Apr 3, 2018 via Android 命令行了解下,你这种效率太低了 写好代码,比如保存为 run.php 执行命令 php run.php |