cronjob 执行大约 100 个 curl url 的脚本 - 不好的做法?
cronjob executing a script with around 100 curl url's - bad practice?
我正在编写一个 cron 作业,该作业将执行一个脚本,该脚本最多加载约 100 url 秒,每个 url 都有将在执行时被内存缓存的数据。每个 url 到 end/load 的时间可能需要 10 秒到 15 分钟,每个 url 从数据库加载数据并且 returns 结果为 json ,并缓存结果。
这个脚本的主要目的是在早上缓存结果数据(00:00 - 直到缓存所有内容所需的时间),这样早上人们就不必等待数据再次缓存.
url 是 api url。 curl 会等待每次执行结束吗?这被认为是不好的做法吗?到目前为止,还没有缓存,所以我正在尝试实现它,将最常用的 url 数据缓存 24 小时或类似时间。
确保您的脚本不会超时,所以 运行 它来自 BASH 或其他东西,而不是通过服务器(Apache、NGINX 等)。
此外:确保您的 curl 命令等待足够长的时间,查看 curl 规范。
https://unix.stackexchange.com/questions/94604/does-curl-have-a-timeout/94612
最后:如果 100 个中有 1 个出现问题,请确保您不会出错。
如果你能合理satisfy/solve这3个可能的问题,我想你应该没问题。 (我总是将输出发送到我自己的邮箱,以保持关注)
关于 curl
集成 ...
Will curl wait for each execution to end?
这取决于您如何使用 curl 库。您已经用 'php' 和 'php-curl' 标记了问题 - 所以您似乎正在从 PHP.
访问 curl 的例程
如果您按以下方式使用 curl 的 easy
界面:
- 用
$req = curl_init()
初始化一个简易句柄
- 设置URL和其他参数使用
curl_setopt()
- 使用
curl_exec($req)
执行(单个)请求
- 使用
curl_close($req)
或 curl_reset($req)
关闭或重置请求
那么,自然地,您必须等到每个请求完成后再开始下一个请求。
另一种方法是使用 multi
接口(见下文)——它允许多个请求同时运行。
is this considered bad practice?
如果您要发送如此大量的网络请求 - 并且每个请求可能需要很长时间 - 我认为这肯定远非理想。如果可能的话,最好使用 curl 的 multi 接口。
multi
界面
正如 curl's documentation 所解释的那样,多接口(与 'easy' 接口相反)
Enable[s] multiple simultaneous transfers in the same thread without making it complicated for the application ...
我的 PHP 非常薄弱,因此 - 我不会自己发布完整的示例 - 我会推荐您参考 PHP 关于 curl_multi_exec()
和相关函数的文档。
简而言之,想法是您仍然以相同的方式初始化您的 curl 句柄。 (PHP 的文档没有明确提及这一点,但普通卷曲句柄有时被称为 'easy' 句柄 - 以区别于 'multi' 句柄。)
$req1 = curl_init();
$req2 = curl_init();
// Set URL and other options using `curl_setopt(...)`
(为了简洁起见,我在这里省略了所有错误检查。)
但是,您没有调用 curl_exec(...)
,而是创建了一个 multi
实例,
$mh = curl_multi_init();
将 easy
句柄添加到您新创建的 multi
实例,
curl_multi_add_handle($mh, $req1);
curl_multi_add_handle($mh, $req2);
然后(而不是为单个 easy
句柄调用 curl_exec()
)在循环中定期调用 curl_multi_exec(...)
:
curl_multi_exec($mh, $running);
$running
变量将更新以指示是否还有请求仍在进行中,因此 - 只要 $运行 为假 - 您就可以退出循环并结束。
完成后,别忘了收拾一下。
curl_multi_remove_handle($mh, $req1);
curl_multi_remove_handle($mh, $req2);
curl_multi_cleanup($mh);
针对大量请求进行优化
不是为每个请求使用不同的变量 - 如 $req1
、$req2
等 - 您可以使用请求数组 - 也许从加载相关的 URLs一个文本文件(我怀疑你已经在做)。
我正在编写一个 cron 作业,该作业将执行一个脚本,该脚本最多加载约 100 url 秒,每个 url 都有将在执行时被内存缓存的数据。每个 url 到 end/load 的时间可能需要 10 秒到 15 分钟,每个 url 从数据库加载数据并且 returns 结果为 json ,并缓存结果。 这个脚本的主要目的是在早上缓存结果数据(00:00 - 直到缓存所有内容所需的时间),这样早上人们就不必等待数据再次缓存.
url 是 api url。 curl 会等待每次执行结束吗?这被认为是不好的做法吗?到目前为止,还没有缓存,所以我正在尝试实现它,将最常用的 url 数据缓存 24 小时或类似时间。
确保您的脚本不会超时,所以 运行 它来自 BASH 或其他东西,而不是通过服务器(Apache、NGINX 等)。
此外:确保您的 curl 命令等待足够长的时间,查看 curl 规范。
https://unix.stackexchange.com/questions/94604/does-curl-have-a-timeout/94612
最后:如果 100 个中有 1 个出现问题,请确保您不会出错。
如果你能合理satisfy/solve这3个可能的问题,我想你应该没问题。 (我总是将输出发送到我自己的邮箱,以保持关注)
关于 curl
集成 ...
Will curl wait for each execution to end?
这取决于您如何使用 curl 库。您已经用 'php' 和 'php-curl' 标记了问题 - 所以您似乎正在从 PHP.
访问 curl 的例程如果您按以下方式使用 curl 的 easy
界面:
- 用
$req = curl_init()
初始化一个简易句柄
- 设置URL和其他参数使用
curl_setopt()
- 使用
curl_exec($req)
执行(单个)请求
- 使用
curl_close($req)
或curl_reset($req)
关闭或重置请求
那么,自然地,您必须等到每个请求完成后再开始下一个请求。
另一种方法是使用 multi
接口(见下文)——它允许多个请求同时运行。
is this considered bad practice?
如果您要发送如此大量的网络请求 - 并且每个请求可能需要很长时间 - 我认为这肯定远非理想。如果可能的话,最好使用 curl 的 multi 接口。
multi
界面
正如 curl's documentation 所解释的那样,多接口(与 'easy' 接口相反)
Enable[s] multiple simultaneous transfers in the same thread without making it complicated for the application ...
我的 PHP 非常薄弱,因此 - 我不会自己发布完整的示例 - 我会推荐您参考 PHP 关于 curl_multi_exec()
和相关函数的文档。
简而言之,想法是您仍然以相同的方式初始化您的 curl 句柄。 (PHP 的文档没有明确提及这一点,但普通卷曲句柄有时被称为 'easy' 句柄 - 以区别于 'multi' 句柄。)
$req1 = curl_init();
$req2 = curl_init();
// Set URL and other options using `curl_setopt(...)`
(为了简洁起见,我在这里省略了所有错误检查。)
但是,您没有调用 curl_exec(...)
,而是创建了一个 multi
实例,
$mh = curl_multi_init();
将 easy
句柄添加到您新创建的 multi
实例,
curl_multi_add_handle($mh, $req1);
curl_multi_add_handle($mh, $req2);
然后(而不是为单个 easy
句柄调用 curl_exec()
)在循环中定期调用 curl_multi_exec(...)
:
curl_multi_exec($mh, $running);
$running
变量将更新以指示是否还有请求仍在进行中,因此 - 只要 $运行 为假 - 您就可以退出循环并结束。
完成后,别忘了收拾一下。
curl_multi_remove_handle($mh, $req1);
curl_multi_remove_handle($mh, $req2);
curl_multi_cleanup($mh);
针对大量请求进行优化
不是为每个请求使用不同的变量 - 如 $req1
、$req2
等 - 您可以使用请求数组 - 也许从加载相关的 URLs一个文本文件(我怀疑你已经在做)。