利用PHP的curl采集数据内存溢出问题咨询

键盘浪人 发布于 2017/03/17 10:05
阅读 1K+
收藏 1

最近在做采集api数据程序,这个api会不断更新数据,而我要不断去采集以获取全部最新数据。我用的是一个死循环加sleep不断去执行,代码如下所示:

public function test(){
		ignore_user_abort(true);
		set_time_limit(0);
		
		while (true){
			$ch = curl_init();	
			curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
			curl_setopt($ch, CURLOPT_URL, 'http://api.****.com/Data');
			$result = null;
			$result = curl_exec($ch);
			if($result === false) {
				return curl_error($ch);
			}
			curl_close($ch);

			$result = json_decode($result, true);
			foreach($result['data'] as $key=>$v){
				$toTime = time();
				$this->db->Query("INSERT INTO `test_data` (`data_oid`, `data_key`, `data_add_time`) VALUES ('$v[orderID]', '$v[orderKey]', '$toTime')");
			}
			unset($result);
			sleep(2);
		}
	}

代码如上所示

我运行后可正常执行,但每次执行几个小时后,就报:

PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 56847 bytes) in /var/www/test.php on line 19

19行中就是:$result = json_decode($result, true);    这里,老是报内存溢出。有时候$result = curl_exec($ch);该处也报内存溢出。加了unset($result);,还是一样,其中memory_limit默认是128M的,后面由于内存溢出我就加了ini_set('memory_limit', '512M');,把memory_limit改成了512M,后面执行后就是执行的时间比之前128M,时间长点而已,但还是报内存溢出,然后程序中止运行了。各位大牛,帮帮忙,这一般是什么原因,unset也加了,为什么还是报内存溢出。急,

加载中
0
文帅营
文帅营

能看到的代码,没有问题,推断是那些看不到的代码有问题。

你上面的代码中,只有一个调用是非php原生代码:

$this->db->Query("INSERT INTO `test_data` (`data_oid`, `data_key`, `data_add_time`) VALUES ('$v[orderID]', '$v[orderKey]', '$toTime')");

这里的$this->db,这个对象执行query之后,是不是把结果缓存了一份,需要确认。

 

现在有一个办法来判断$this->db这个对象是否有问题:


$m1 = memory_get_usage();
$this->db->Query("INSERT INTO `test_data` (`data_oid`, `data_key`, `data_add_time`) VALUES ('$v[orderID]', '$v[orderKey]', '$toTime')");
$m2 = memory_get_usage();
echo "\n写入数据库之后,内存变化:".($m2 - $m1);

 

如果输出:“写入数据库之后,内存变化:0”,表示$this->db没有问题

其它情况,说明$this->db这个类库封装的有问题

 

键盘浪人
键盘浪人
仁兄,详细,这么细心。感谢感谢,谢谢你,我试下。
文帅营
文帅营
如果你使用的是phalcon,这个问题很好解释。 phalcon的db操作类库会自动将数据库查询过的结果缓存一份到。不确定你用的框架db类是否有此功能。
0
键盘浪人
键盘浪人

顶,各位老司机支支招啊。

0
记住一座城
记住一座城

$result内容有多大

记住一座城
记住一座城
回复 @键盘浪人 : 看代码找不出问题,把while里的代码提取为子函数调用试试
键盘浪人
键盘浪人
$result,是json格式字符串,长度大概有:24599。不算很大啊,都可以执行,但就是执行几个小时后,报内存溢出
0
mickelfeng
mickelfeng

对变量赋值null试试,可以用memory_get_usage和memory_get_peak_usage函数监测内存的使用

键盘浪人
键盘浪人
看下如上代码,我已经复制null了,使用后也销毁了
0
mickelfeng
mickelfeng
mickelfeng
ignore_user_abort(true); set_time_limit(0); 这两行去掉吧,没必要加
mickelfeng
mickelfeng
你换一个版本试试,php5.5 或者5.6看是不是版本原因。 还有你测试下其他函数,比如file_get_contents, fread,fsockopen,等函数。
键盘浪人
键盘浪人
PHP Version 5.4.16
0
大賢者
大賢者

死循环里 不断init curl.. 结尾没释放!!

$ch = curl_init();	
大賢者
大賢者
回复 @键盘浪人 : - - 没看到
键盘浪人
键盘浪人
curl_close($ch); 不是释放了吗?
0
键盘浪人
键盘浪人

还没决解,各位老司机,有谁懂的或或遇到过类似问题的。急

0
Tuesday
Tuesday

首先, 凡是phper在项目, 工作, 日常生活, 有用到ignore_user_abort这个函数,  我都觉得这人是SB, 是脑残,是应该立即被炒鱿鱼. 

不解释. 

 

键盘浪人
键盘浪人
勿喷,决解问题才是硬道理。仁兄是否知道该问题怎么决解。感激不尽
0
xinson
xinson

干嘛要写在一起啊!分开写不行吗??采集程序采集数据的保存在redis,另外写程序跑保存数据。而且没必要使用数据库操作类,直接使用原生数据库操作。

键盘浪人
键盘浪人
回复 @xinson : 回复 @键盘浪人 : 我是把接口返回来的json格式数据用json_decode 转成数组嘛。程序可正常运行的,且就是每次运行几个小时后自动停止,日志显示是内存溢出了Allowed memory size of 536870912 bytes exhausted (tried to allocate 56847 bytes)
键盘浪人
键盘浪人
回复 @xinson : 接口返回的数据,接口返回的是json格式的。json_decode,json格式的字符串,哥
xinson
xinson
回复 @键盘浪人 : json_decode 什么类型数据
键盘浪人
键盘浪人
回复 @xinson : 谢谢你,我试下。对了,现在回到问题,我这个我都加到了内存,也销毁了变量,为什么还报内存溢出啊。我看了,返回的json不是很大,而且开始都可以运行,偏偏是运行几小时后自动关闭报内存溢出。难道是变量没销毁到或循环json_decode会有问题?
xinson
xinson
回复 @键盘浪人 : 干嘛不独立写一个php文件用cli跑,你是直接浏览器跑的吧(而且你这看起来是框架的方法,每次循环都载入一堆框架的类这多消耗内存啊)。
下一页
0
be-quiet
be-quiet

你这程序是挂着就一直执行?

改成定时执行脚本会比较好.

be-quiet
be-quiet
回复 @键盘浪人 : 这个还真看不出来. 你写个log观察下, 还有你循环操作数据库不知道是否释放了.
键盘浪人
键盘浪人
回复 @be-quiet : 谢谢你,我到时试下。现在回到问题,我这个我都加到了内存,也销毁了变量,为什么还报内存溢出啊。我看了,返回的json不是很大,而且开始都可以运行,偏偏是运行几小时后自动关闭报内存溢出。难道是变量没销毁到或循环json_decode会有问题?
be-quiet
be-quiet
回复 @键盘浪人 : 恩, 就是单独写一个脚本. 通过 crontab 每秒执行一次去定时跑脚本.
键盘浪人
键盘浪人
是说单独写一个php脚本,单独cli运行是吗,还是?望指教
返回顶部
顶部