我正在编写一个 cron 作业,它将执行一个脚本,该脚本将加载多达 ~ 100 个 url,每个 url 都有在执行时将被内存缓存的数据。每个 url 的结束/加载时间可能需要 10 秒到 15 分钟,每个 url 从数据库加载数据并将结果作为 json 返回,并缓存结果。 此脚本的要点是在早上(00:00 - 直到缓存所有内容所需的时间(缓存结果数据,因此在早上人们不必等待数据再次缓存。
这些网址是 API 网址。curl 会等待每次执行结束吗?这算不算不好的做法?到目前为止,还没有缓存,所以我正在尝试实现它,将最常用的 url 数据缓存 24 小时或类似时间。
关于curl
集成...
curl 会等待每次执行结束吗?
这取决于您如何使用 curl 库。您已经用"php"和"php-curl"标记了问题 - 所以看起来您正在从PHP访问curl的例程。
如果您以类似于以下方式使用 curl 的easy
接口:
- 使用
$req = curl_init()
初始化简单句柄 - 使用
curl_setopt()
设置 URL 和其他参数 - 使用
curl_exec($req)
执行(单个(请求 - 使用
curl_close($req)
或curl_reset($req)
关闭或重置请求
然后,自然地,您必须等到每个请求完成才能开始下一个请求。
另一种方法是使用multi
接口(见下文( - 它允许多个请求同时运行。
这算不算不好的做法?
如果您要发送如此大量的网络请求 - 并且每个请求可能需要很长时间 - 我认为这肯定远非理想。如果可能的话,最好使用 curl 的多接口。
multi
界面
正如curl的文档所解释的那样,多接口(与"简单"接口相反(
在同一线程中启用多个同时传输,而不会使应用程序变得复杂...
我的PHP非常弱,所以 - 我不会自己发布一个完整的示例 - 而是向您推荐PHP关于curl_multi_exec()
和相关函数的文档。
简而言之,这个想法是你仍然以相同的方式初始化你的卷曲句柄。(PHP 的文档没有明确提到这一点,但普通卷曲句柄有时被称为"简单"句柄 - 以区别于"多"句柄。
$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
变量将被更新以指示是否有请求仍在进行中,因此 - 一旦$running为 false,您就可以退出循环并结束。
完成后,不要忘记整理。
curl_multi_remove_handle($mh, $req1);
curl_multi_remove_handle($mh, $req2);
curl_multi_cleanup($mh);
针对大量请求进行优化
与其为每个请求使用不同的变量 - 如$req1
,$req2
等 - 您可以使用请求数组 - 也许从文本文件加载相关URL(我怀疑您已经在这样做了(。
确保你的脚本不会超时,所以从 BASH 或其他东西运行它,而不是通过服务器(Apache、NGINX 等(。
另外:确保您的 curl 命令等待足够长的时间,查找 curl 规格。
https://unix.stackexchange.com/questions/94604/does-curl-have-a-timeout/94612
最后:确保如果 100 个中有 1 个坏了,请不要出错。
如果你能合理地满足/解决这3个可能的问题,我想你应该没问题。(我总是将输出发送到我自己的邮件中,以密切关注它(