在 BAE 3.0 上的 WordPress(四):新的缓存设想 中,我提到了使用 BCS 缓存,目前我就已经实现了!
但是,问题还是有的,就是:有时候,文章发布、评论发表要自己手动更新缓存,无法自动更新。
很简单,在根目录创建一个 index-with-bcs.php,写入:
<?php // 模式设置 $debug = 1; //开关 DeBug 模式(0:Off;1:On) $display_cached_by_bcs = 1; //显示 Cache By BCS(0:Off;1:On) $start = microtime(); // 计算页面加载时间 // BAE 获取真实 IP $RealIP = str_replace(", ", "", str_replace(getenv('REMOTE_ADDR'), "", getenv('HTTP_X_FORWARDED_FOR'))); if (false === getenv('HTTP_X_FORWARDED_FOR')) { $_SERVER['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR']; } else { $_SERVER['REMOTE_ADDR'] = $RealIP; } define('WP_USE_THEMES', true); // 不这样,主题就没了。 require_once ('bcs.class.php'); // 载入 BCS SDK $cache_bucket = 'bucket'; // 缓存所用的 Bucket,建议使用“私有”模式和单独 Bucket,不要混用 $cache_ak = 'AK'; // API Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_AK') $cache_sk = 'SK'; // Scret Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_SK') $baidu_bcs = new BaiduBCS($cache_ak, $cache_sk); $refresh_key = 'r'; // 单页缓存刷新 Key,默认 r,刷新方式就是访问你要刷新的页面 + ?r=y,强烈建议更改此选项 $clean_key = 'c'; // 缓存清空 Key,默认 c,刷新方式就是访问站点任意页面 + ?c=y,强烈建议更改此选项 $url = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $url = str_replace('?' . $refresh_key . '=y', '', $url); $url = str_replace('?' . $clean_key . '=y', '', $url); $key = md5($url); $object = '/' . md5($url); // 检查 WordPress 是否处于登录状态下 $cookie = var_export($_COOKIE, true); $loggedin = preg_match("/wordpress_logged_in/", $cookie); // 如果已经缓存,且为游客访问(非登陆状态下),就直接加载缓存内容 if ($baidu_bcs->is_object_exist($cache_bucket, $object) && !$loggedin && !strpos($url, '/feed/') && !isset($_GET[$refresh_key]) && !isset($_GET[$clean_key])) { echo $baidu_bcs->get_object($cache_bucket, $object)->body; $cached = 1; $msg = '<!-- Page cached -->'; // 如果检测到刷新指令,就清空该页缓存 } elseif ($_GET[$refresh_key] == 'y') { require('./wp-blog-header.php'); $baidu_bcs->delete_object($cache_bucket, $object); $msg = '<!-- Page cache deleted -->'; // 如果检测到清空指令,就清空所有缓存 } elseif ($_GET[$clean_key] == 'y') { require('./wp-blog-header.php'); $list_opt = array('start' => 0); $list_cache = json_decode($baidu_bcs->list_object($cache_bucket, $list_opt)->body, true); $i = 0; while($i < 1000){ $object= $list_cache["object_list"][$i]["object"]; $baidu_bcs->delete_object($cache_bucket, $object); $i++; } $msg = '<!-- Cache flushed -->'; // 如果登录的情况下,就不缓存 } elseif ($loggedin) { require('./wp-blog-header.php'); $msg = '<!-- Page not cached -->'; // 否则,缓存该页面 } else { ob_start(); require('./wp-blog-header.php'); $html = ob_get_contents(); ob_end_clean(); echo $html; // 如果是 404 页面 或 搜索结果 页面就不缓存 if (!is_404() && !is_search()) { // 缓存 7 天,但不知过期是否会自动处理 $cache_opt = array('header' => array( 'Expires' => 'modify plus 7 days', 'Content-Type' => 'text/plain' ) ); $baidu_bcs->create_object_by_content($cache_bucket, $object, $html, $cache_opt); $msg = '<!-- Page is cached -->'; } } $end = microtime(); // 得到加载完成时间 if ($cached && $display_cached_by_bcs) { echo "\n" . '<!-- Dynamic page generated in ' . t_exec($start, $end) . ' seconds -->' . "\n"; echo '<!-- Cached page generated by Nikbobo BCS Cache -->' . "\n"; echo '<!-- BCS Cache: ' . $key . ' -->' . "\n"; } // 如果 DeBug 模式开启,就显示 DeBug 信息 if ($debug) { echo "\n" . $msg . "\n"; } // 时间比对 function t_exec($start, $end) { $t = (getmicrotime($end) - getmicrotime($start)); return round($t,5); } // 获取页面加载时间 function getmicrotime($t) { list($usec, $sec) = explode(" ",$t); return ((float)$usec + (float)$sec); } ?>
就可以了。
但是,记住 BAE 3.0 服务的 SDK 需要开发者自己安装到环境中,所以自己下载 BCS SDK 扔到根目录。
我们还要做的是修改 App.Conf 将伪静态修改到 index-with-bcs.php,具体步骤是:
编辑 App.Conf,将:
- url : / script : index.php - url : (.*) script : /index.php
替换为:
- url : / script : index-with-bcs.php - url : (.*) script : /index-with-bcs.php
然后,为了尽可能避免发布文章不自动更新、发表评论不自动更新,我们需要在主题的 Functions.php 中添加如下代码:
/* * BCS 缓存清空 (当发布文章、评论时) */ function bcs_cache_refresh() { global $batcache; $post = get_post($post_id); if ( $post->post_type == 'revision' || get_post_status($post_id) != 'publish' ) return; bcs_cache_refresh_url( get_option('home') ); bcs_cache_refresh_url( trailingslashit( get_option('home') ) ); bcs_cache_refresh_url( get_permalink($post_id) ); } add_action( 'wp_trash_post', 'bcs_cache_refresh', 0 ); add_action( 'publish_post', 'bcs_cache_refresh', 0 ); add_action( 'edit_post', 'bcs_cache_refresh', 0 ); // leaving a comment called edit_post add_action( 'delete_post', 'bcs_cache_refresh', 0 ); add_action( 'publish_phone', 'bcs_cache_refresh', 0 ); add_action( 'clean_post_cache', 'bcs_cache_refresh' ); function bcs_cache_refresh_url($url) { if ( empty( $url ) ) return false; require_once ('bcs.class.php'); $cache_bucket = 'Bucket'; // 缓存所用的 Bucket,建议使用“私有”模式和单独 Bucket,不要混用 $cache_ak = 'AK'; // API Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_AK') $cache_sk = 'SK'; // Scret Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_SK') $baidu_bcs = new BaiduBCS($cache_ak, $cache_sk); $cache_object = '/' . md5( $url ); $baidu_bcs->delete_object($cache_bucket, $cache_object); return true; }
话说,SiteMap.XML 改一改,也可以缓存一下。敬请期待。
有人问这个有什么用,不是有 Cache 么?但是我想说,等到 Cache 收费时,用处就来了。
好像还是有问题,发布文章不会自动更新。
对的,貌似原因来自于 WordPress 的 URL 与 index-with-bcs.php 的不一致,多了“/”,但是有些又没问题。
建议博主参考下 WP Super Cache 这类缓存插件。
那有什么解决办法么?我现在已经不用BAE了,就先不折腾了。
mark,现在在用阿里云和AWS,AWS赠送了一年的ElasticCache,支持Redis~~~~
半成品,谢谢关注。另:请不要直接添加链接,谢谢。