你也许知道WordPress 内置 CRON 的工作方式与传统 CRON 不同。
它不是在指定时间触发,而是仅在有人访问该网站时触发。因此,如果没有访问,则不会触发 wp-cron,因此不会执行任何任务。
反之亦然,如果您在您的网站上吸引了大量访问者,则每次有人查看任何页面并检查计划任务时,WordPress CRON 系统都会被触发。这样 WordPress CRON 会导致额外的服务器负载(CPU 使用率增加),这可能会严重损害网站性能。
当谈到 WordPress Multisite Cron时,您的问题会随着安装的网站数量而增加。
wp-cron 是如何工作的?
Multisite 上的 WordPress CRON 在每个博客上独立工作。
比如说,您在网站 A 和 B 上安排了帖子。
当有人访问网站 A 时,博客 A 上的预定帖子虽然有延迟,但最终会发布。但是网站 B 上的帖子永远不会发布,除非有人也访问网站 B。
错过网络每个站点的计划问题可能是一件相当烦人的事情。当您在多站点安装中获得大量流量时,您可能会遇到另一个问题。
根据网络中网站的数量,CPU 使用率问题也会成倍增加。这就是为什么多站点使用内置 CRON根本不是一个好主意。相反,我们应该设置一个真正的 CRON 作业。
如何为 WordPress Multisite 设置 CRON 作业并修复跨网络的延迟计划问题?
一个明显的方法
为了降低 CPU 使用率并让任务执行,无论博客是否有点击,我们应该用真正的 CRON 替换 WordPress Multisite CRON。
在这里,我详细描述了如何为单个安装执行此操作。
Multisite 的步骤非常相似,除了我们需要在网络的每个站点上触发 CRON(因为它们是独立工作的)。
1. 在整个网络中禁用 WordPress CRON wp-config.php
:
define('DISABLE_WP_CRON', true);
2. 我们将借助foreach循环触发每个站点的发布。
trigger.php
在您拥有wp-config.php
.
我有一个很棒的包装器,可以在 WordPress Multisite 中执行批量操作,这为我节省了大量时间。让它也为你工作:
if ( is_multisite()) { | |
$sites=get_sites(); | |
foreach ($sitesas$site ) { | |
$blog_id=$site->blog_id; | |
//if ($blog_id < 6 ){ //if we need just certain blogs | |
switch_to_blog( $blog_id ); | |
wp_suspend_cache_addition(true); | |
//here's what we're gonna do… | |
wp_suspend_cache_addition(false); | |
restore_current_blog(); | |
//} //endif $blog_id | |
sleep(3); // this should be paused for 3 seconds before every other blog | |
}//endforeach | |
}//endif multisite |
所以我们只需将这段代码放在该行之后//here's what we're gonna do...
$site_url = get_site_url($blog_id); $command = $site_url.'/wp-cron.php?doing_wp_cron'; wp_remote_get($command);
它将自动触发我们网络的每个站点。
整个trigger.php
看起来像这样:
if ( is_multisite()) { | |
$sites = get_sites(); | |
foreach ($sites as $site ) { | |
$blog_id = $site->blog_id; | |
//if ($blog_id < 6 ){ //if we need just certain blogs | |
switch_to_blog( $blog_id ); | |
wp_suspend_cache_addition(true); | |
//here's what we're gonna do… | |
$site_url = get_site_url($blog_id); | |
$command = $site_url.'/wp-cron.php?doing_wp_cron'; | |
wp_remote_get( $command ); | |
wp_suspend_cache_addition(false); | |
restore_current_blog(); | |
//} //endif $blog_id | |
sleep(3); // this should be paused for 3 seconds before every other blog | |
}//endforeach | |
}//endif multisite |
3. 您现在所需要的只是在您的服务器上为您的主博客添加一个CRON 作业:
wget -O /dev/null https://network-main-blog.com/trigger.php
另外,我要设置一个合理的时间间隔。
根据指定的周期(例如每天一次),Unix CRON 将命中trigger.php
-> 将命中wp-cron.php
网络中的每个博客 -> 将检查是否有任何计划的任务,并执行它们。
这是在 WordPress 多站点安装上设置计划任务的充分且清晰的方法。
但是,如果您拥有相当大的网络并且服务器资源紧张,您会怎么做?
更好的方法
WordPress 中的所有计划任务都存储在wp_options
表中。
当您安排一个任务每天发布 50 个草稿时,50 个任务将保存在您的 wp_options 表中。此表的大部分(包括 CRON 作业)在每次页面加载时加载。这对于单个安装来说没问题,但它会显着降低您在 WordPress 多站点网络上的站点速度。
比如说,您有一个由 100 个站点组成的中型网络,这导致我们在wp_options
表中增加了 50*100=5000 行(请注意,这是同一个数据库!)。此外,您的网络访问次数越多,服务器资源消耗就越多。
为了晚上安然入睡而不用担心您的 MySQL 服务器随时崩溃,我们希望跳过 WordPress cron。 我们将设置一个 CRON 作业来直接发布帖子,而不是用于发布计划帖子的 CRON 作业。
此外,我将提供有关如何安排的详细说明,但在您继续之前,请记住这种方法可能并不适合每个项目。例如,如果特定的发布时间对您来说非常重要,那么这不是您想要做的。
但是如果你有高负载网络并且你需要每天发布草稿,节省服务器资源并且不介意发布时间是 +- 几个小时,你绝对应该尝试一下。
1. 首先,我们需要能够实际发布 50 份草稿的函数。
在WordPress根目录下创建publishing.php
内容如下:
if (!defined(‘ABSPATH')) {require_once(dirname( __FILE__ ) . ‘/wp-load.php');} | |
global $wpdb; | |
$blog_id = get_current_blog_id(); | |
$args = array(‘post_type' => ‘post', ‘post_status' => ‘draft' , ‘numberposts' => 50, ‘fields' => ‘ids'); | |
$future_posts = get_posts( $args ); | |
foreach ($future_posts as $future_post) { | |
$my_post = array(‘ID' => $future_post, ‘post_status' => ‘publish'); | |
$upd = wp_update_post( $my_post, true ); | |
} |
这段简单的代码将直接发布草稿,无需计划。
2. 现在我们需要触发它publishing.php
以在整个网络中执行。我们正在用服务器 CRON 替换 WP CRON,就像我们在上一个选项中所做的一样。
只是注意的地方是 publishing.php
,而不是wp-cron.php?doing_wp_cron
$command = $site_url.'/publishing.php';
瞧!我们通过在网络上用真正的 CRON 作业替换 WP Multisite CRON 并完全跳过了调度计划,设法减少了 CPU 和内存使用。很酷,是吗?
但…
正如我已经说过的,对于小型网络,这种方法非常好,但如果您有 100 多个博客,这意味着发布功能将一次执行 50*100 = 5000 次。这将减慢网站速度,对吧?
我为高负载 WordPress 多站点网络设置 CRON 的方法
如何在 100 多个博客上每天发布 50 篇文章而不至使您的服务器崩溃?
概述:由 100 多个博客组成的 WordPress 多站点网络。每个博客每天应该发布 50 篇文章。它导致我们每天应该由 CRON 发布 50*100=5000 个帖子。
目标:应该以最小的服务器负载执行,因为网络在发布过程中是分开加载的。
在这里,我使用另一种可以显着降低 CPU 使用率的方法。这样我们就有了:
- 没有 CRON 事件来计划发布帖子
- 没有发布 50 个帖子的 CRON 事件
- CRON 在网络的每个网站上每天触发一次 (!)
- 批量发布不会超载,一次仅发布 50 个帖子
这种方法对于开发人员来说可能有些棘手,但这是我们使用尽可能少的服务器资源的方式。
我们将为网络中的每个网站添加一个单独的 CRON 作业,并为其提供直接执行的命令 publishing.php
。
我们已经准备好这个文件,现在我们需要为网络中的每个站点添加一个单独的 CRON 作业。
每个 cronjob 应该以 1 分钟的间隔安排。想象一下,您的网络中有 3 个站点,因此 CRON 作业应该像这样执行:
站点 A — 00:01
站点 B — 00:02
站点 C — 00:03
每个人每天在准确的时间执行一次。
这样一分钟内只有一个站点被触发,没有超载,没有问题。
因此,您需要将 3 个命令添加到您的 crontab:
wget -O /dev/null http://siteA.com/publishing.php
wget -O /dev/null http://siteB.com/publishing.php
wget -O /dev/null http://siteC.com/publishing.php
在网络中有 100 多个站点! 你要我手动添加 100 多个 cronjobs 吗?
当然,不是!你可以用Linux 中的 Cron 作业批量调度实现。