WordPressで予約投稿が失敗する
最近、予約投稿ができずに、管理画面上で「予約投稿の失敗」と出ることが増えてきたので、ちょっと調べてみました。
何が起きているのか?
とりあえず、PHP-FPMのエラーログに何か手がかりが無いか見てみる。
[21-Aug-2014 00:43:22] NOTICE: child 30278 stopped for tracing
[21-Aug-2014 00:43:22] NOTICE: about to trace 30278
[21-Aug-2014 00:43:22] NOTICE: finished trace of 30278
(01:10が予約投稿時間)
[21-Aug-2014 01:10:14] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[21-Aug-2014 01:10:16] WARNING: [pool www] child 26864, script '/var/www/wp-cron.php' (request: "POST /wp-cron.php") executing too slow (6.366237 sec), logging
[21-Aug-2014 01:10:16] NOTICE: child 26864 stopped for tracing
[21-Aug-2014 01:10:16] NOTICE: about to trace 26864
[21-Aug-2014 01:10:16] NOTICE: finished trace of 26864
[21-Aug-2014 01:10:54] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[21-Aug-2014 01:11:09] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[21-Aug-2014 01:28:40] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
関連しているかもしれないWARNINGが2種類出てますね。
同時接続数を超えている
[21-Aug-2014 01:10:14] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[21-Aug-2014 01:10:54] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[21-Aug-2014 01:11:09] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
直接の原因はこれっぽい。同時接続数の上限で処理ができなかった。
処理が遅い
[21-Aug-2014 01:10:16] WARNING: [pool www] child 26864, script '/var/www/wp-cron.php' (request: "POST /wp-cron.php") executing too slow (6.366237 sec), logging
同時接続の上限になったのは処理が遅いからのようです。wp-cronが6.3秒もかかっている。
そもそもWordPressのレスポンスはNginxでキャッシュしているので普通のリクエストは来ないため、/wp-cron.php
が呼ばれただけで重たくなっているように思える。
というか、cronっぽい仕組みをユーザーからのリクエストで回しているのがそもそもおかしいんだけど、そういう実装になっているからなぁ……
遅い処理の内訳
PHP-FPMのスロークエリログに何か出ているかも。
[21-Aug-2014 01:10:16] [pool www] pid 26864
script_filename = /var/www/wp-cron.php
[0x00007f71b0d2bcf0] mysql_query() /var/www/wp-includes/wp-db.php:1619
[0x00007f71b0d2b180] _do_query() /var/www/wp-includes/wp-db.php:1523
[0x00007f71b0d2ae80] query() /var/www/wp-includes/wp-db.php:1824
[0x00007f71b0d29fd0] get_var() /var/www/wp-includes/functions.php:504
[0x00007f71b0d294a8] do_enclose() /var/www/wp-content/plugins/wordpress-ping-optimizer/cbnet-ping-optimizer.php:327
[0x00007fffbf76a470] cbnetpoPingServices() unknown:0
[0x00007f71b0d28d28] call_user_func_array() /var/www/wp-includes/plugin.php:546
[0x00007f71b0d28340] do_action_ref_array() /var/www/wp-cron.php:100
見方がよくわからないけど、WordPress Ping Optimizerプラグインがいたので消そう。以前にPingはオワコンと書いておきながらプラグインを消してなかったのか……
このプラグインが遅かっただけかもしれないので、これで様子を見よう。
予約投稿の失敗対策
プラグインにリカバリーさせる
WP Missed Schedule Fix Failed Future Postsというプラグインがあって、予約投稿のもので現在時刻を過ぎてたら公開処理をする、ということをしてくれます。
wp-missed-schedule.php
function wpms_init()
{
global $wpdb;
$qry = <<<SQL
SELECT ID FROM {$wpdb->posts} WHERE ( ( post_date > 0 && post_date <= %s ) ) AND post_status = 'future' LIMIT 0,10
SQL;
$sql = $wpdb->prepare( $qry, current_time( 'mysql', 0 ) );
$scheduledIDs = $wpdb->get_col( $sql );
if ( !count( $scheduledIDs ) )
return;
foreach ( $scheduledIDs as $scheduledID )
{
if ( !$scheduledID )
continue;
wp_publish_post( $scheduledID );
}
}
このプラグインを使えば、投稿時間は後ろにずれるものの、いずれ投稿してくれます。
PHP-FPMの設定を見直す
そもそも同時リクエスト数が足りてないから問題が起こるわけで、設定の見直しは必要ですね。
こっちは別の設定と合わせてPHP-FPMの設定見直しとして記事を書く予定。