PHP:当循环很长的函数没有响应时退出并显示警报

发布于 2024-09-09 22:03:31 字数 777 浏览 3 评论 0原文

我有一个大函数(1300 多行代码),它从网络获取数据并将其插入本地数据库。每次该函数运行大约需要 20 秒才能完成,我需要运行该函数一百万次,因此我使用 set_time_limit(0) 将 PHP 时间限制设置为无限,然后循环该函数一百万次,例如这:

for ($ID= '01'; $ID < '999999'; $ID++) {
    getDataFromWeb($conn, $ID);
}

那么问题出在哪里呢?问题是有一百万个地方可能会出错,而且总是会出错,例如,代码突然卡在 ID 23465 中,它只是停止获取数据,但我没有收到任何类型的错误,它就像循环继续但没有向数据库插入任何内容一样,并且由于我为 PHP 设置了“无时间限制”,因此它永远不会停止。

我想知道如何检测此类问题、停止所有并显示警报。如果我在函数开始之前设置时间,然后在函数结束时检查它,如下所示:

for ($ID= '01'; $ID < '999999'; $ID++) {
    $time_start = microtime();
    getDataFromWeb($conn, $ID);
    $time_end = microtime();
    if ($time_alert - //... somehow check how time does it takes and stop if its taking too much
}

它将不起作用,因为如果函数永远不会完成,则 $time_end 将永远不会被设置等等...

所以,请帮忙?

I have this big function (1300+ lines of code) that takes data from the web and insert it into a local database. Each time the function runs its takes something like 20 seconds to complete and I need to run this function like a million times, so I use set_time_limit(0) to set the PHP time limit to infinite and I loop the function a million times, like this:

for ($ID= '01'; $ID < '999999'; $ID++) {
    getDataFromWeb($conn, $ID);
}

So whats the problem? The problem is that there are a million things that can go wrong and it always does go wrong, and suddenly the code gets stuck in ID 23465 for example, and it just stop getting data but I don't get any kind of error, its like the loop continues but without inserting anything to database, and because of the 'no time limit' I set to PHP then it never stops.

I want to know how I can detect this kind of problem, stop all and show alert. If a I set the time before the function starts and then check it when the function ends, like this:

for ($ID= '01'; $ID < '999999'; $ID++) {
    $time_start = microtime();
    getDataFromWeb($conn, $ID);
    $time_end = microtime();
    if ($time_alert - //... somehow check how time does it takes and stop if its taking too much
}

It will not work because if the function never completes then $time_end will never be set and so on...

So, help please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

韵柒 2024-09-16 22:03:31

旁注:提供的代码不会循环 1,000,000 次。以下内容将:

for( $id=1 ; $id<=1000000 ; $id++ ) {
    getDataFromWeb( $conn , $id );
}

此外,关于您需要不断运行此脚本以将内容加载到数据库中,我建议您执行以下操作:

  • 我假设您正在使用 SQL 表来保存要抓取的 URL,
  • 添加一个字段使用名为“loadAttempted”的时间戳,
  • 将 PHP 脚本尝试执行该操作的次数限制为 5 次,
  • 将脚本尝试抓取 URL 的时间记录到“loadAttempted”字段中,
  • 让脚本的每个循环执行搜索任何“loadAttempted”为空或大于 X 分钟前的 URL,
  • 添加 CRON 作业来触发脚本

这意味着,最多每一分钟,脚本都会被触发并尝试加载 5 个 URL。如果一个 URL 需要异常长的时间来加载(这意味着脚本在尝试抓取它时超时),它将循环回来并再次尝试。

您还可以使用此方法或该想法的变体来获取比其他页面慢的页面的统计信息和/或 URL 的平均加载时间。

另外,如果您想让它不断运行,我建议限制 PHP 脚本尝试运行 getDataFromWeb() 函数的次数较少(例如 5)

Side note: The supplied code will not loop 1,000,000 times. The following will:

for( $id=1 ; $id<=1000000 ; $id++ ) {
    getDataFromWeb( $conn , $id );
}

Also, with regards to your need to have this script run constantly to load content into a database, I would suggest the following:

  • I presume that you are using an SQL Table to hold the URLs to be crawled,
  • Add a field with a timestamp called 'loadAttempted',
  • Limit the PHP Script to try and perform the action to maybe 5 times,
  • Record the Time the Script attempt to crawl the URL into the 'loadAttempted' field,
  • Have each loop of the Script perform a search for any URLs where 'loadAttempted' is empty, or where it is greater than X minutes ago,
  • Add a CRON Job to trigger the Script

This would mean that, up to every minute, the script will be triggered and will try and load 5 URLs. If a URL takes an abnormally long period of time to load (which would mean that the script timed out whilst trying to crawl it) it will cycle back around and be tried again.

You could also use this, or variants on the idea, to get stats for pages which are slower than the rest and/or the average loadtime for the URLs.

Also, if you are wanting to have this running constantly, I would suggest that limiting the PHP script to try and run the getDataFromWeb() function a smaller number of times (like 5)

反话 2024-09-16 22:03:31

如果 getDataFromWeb($conn, $ID); 使用像 libcurl 或类似的库,那么在那里设置连接时间限制可能是个好主意?
或者,对于调试,只需 echo '.' 即可知道该函数已完成并退出。

If getDataFromWeb($conn, $ID); uses libs like libcurl or similar, than maybe it's a good idea to set connection timelimit there?
Or for debug just echo '.' to know that function've been finished and exited.

寄人书 2024-09-16 22:03:31

好吧 - 在我看来,这里有几件事是危险信号。

首先 - 当你说你循环了 100 万次时,你不是在开玩笑。这让我很惊讶。

第二 - 这个循环对我来说看起来很奇怪:

for ($ID= '01'; $ID < '999999'; $ID++)

为什么不这样做:

for ($ID = 1 ; $ID < 999999; $ID++)

我不明白你为什么使用字符串进行整数计数。

第三——你是如何执行这个的?是来自浏览器还是来自 CLI

最后 - 如果没有看到代码,很难说发生了什么,但是该函数在完成时是否返回 true/false 布尔值,或者是它们的其他触发器,例如 echo 语句(至少)函数将打印调试信息,以便您可以跟踪进度。

您可能想要简化 getDataFromWeb 函数中的代码,听起来它正在运行某种 cURL 请求,解析该数据并将其放入“$conn”数据库中。如果您将该函数中的特定任务分块为单独的函数(或创建一个类),一个用于获取数据,一个用于“清理”数据,一个用于将数据输入数据库,则可能会更容易理解和阅读。如果一个函数有太多任务,那么像这样的问题(调试)就会成为一场噩梦。

Okay - there are several things here that are red flags in my mind.

First - You weren't kidding when you said you were looping this 1 million times. That surprised me.

Second - This loop looks weird to me:

for ($ID= '01'; $ID < '999999'; $ID++)

Why not instead do:

for ($ID = 1; $ID < 999999; $ID++)

I don't see why you're using Strings for Integer counting.

Third - How are you executing this? Is it from a browser or from CLI

Lastly - Without seeing the code it's hard to say what's going on, but does the function return a true/false boolean when complete, or are their other triggers like echo statements (at the minimum) in the function that will print debug information so you can track the progress.

You may want to simplify the code in the getDataFromWeb function it sounds like it's running some kind of cURL request, parsing that data, and placing it into the "$conn" database. Might be easier to not only understand but read if you chunked specific tasks from that function into separate functions (Or made a class) One for getting the data, one for "cleaning" the data, and one for entering the data into the database. If a function has too many tasks then issues like this (Debugging) become a nightmare.

不一样的天空 2024-09-16 22:03:31

getDataFromWeb() 函数中是否有 mysql_error()/mysql_errno() 函数?例如

if(mysql_errno($conn))
{ 
  echo mysql_errno($conn) . ": " . mysql_error($conn);
}

来自 http://php.net/manual/en/function.mysql -error.php

要停止该函数,请用 die 替换 echo。

Do you have any mysql_error()/mysql_errno() functions in your getDataFromWeb() function? Such as

if(mysql_errno($conn))
{ 
  echo mysql_errno($conn) . ": " . mysql_error($conn);
}

From http://php.net/manual/en/function.mysql-error.php

To stop the function replace the echo with die.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文