博客是玩具,所以有事没事总想折腾下,因为不懂代码和服务器管理,所以只能折腾靠尝试能踩出来途径。目前对于各种炫酷的功能已经无爱,前段时间干掉了主题自带的很多功能,唯一的追求就是想让访问速度更快一些。但因为不懂技术,所以一直在折腾,实际效果略胜于不折腾。
目前博客采用了Memcached、Opcache、W3 Total cache、CDN四种方法来提高访问速度。整体感觉当html文件缓存到CDN时速度就很快,但当CDN的缓存时间过期,需要回源时访问速度就明显变慢,这也是现在想优化的关键所在。
W3 Total cache将页面静态化成html文件,并保存在Memcached,且能在新页面发布,有新评论时刷新相关页面和首页,所以W3 Total cache的页面缓存时间可以设置很长。但CDN不能在有新发布或有新评论被通过时刷新,这就导致CDN对html缓存时间过长就不能及时显示评论等更新,如果缓存时间过短,则要经常回源,而回源就是现在我的博客页面加载慢的主要症结。
这里插个题外话,关于html到底要不要过CDN的问题,请教了大佬天一生水,他认为没有必要,这样会让速度更慢。但我自己测试不用CDN的加载时间比有CDN时更长,用册数网站时就更明显,因为并发太高。同时网上也有人说将html上CDN能够提高安全性,因为隐藏了真实IP,对这一点我不懂,但觉得可能有点小用吧。所以最终还是决定用CDN加速经W3静态化后的html文件。
要解决这一问题有两种思路:
1、让W3等缓存插件直接通过API接口刷新阿里云CDN;
但W3等缓存插件都是老外开发的,压根就没有考虑中国的阿里云、腾讯云等CDN接口,而预设了接口的都是亚马逊云等,没有API自然实现不了更新刷新CDN的功能。
2、用国内大神编写的CDN管理插件;
搜了一圈,只有一款对腾讯云CDN的管理插件,大家评价很好用,但就是没有阿里云的。
逛了帖子很久,灵机一动,问问阿里的通义千问,他家的人工智能应该懂得他家的CDN怎么用。
问通义千问,能适配阿里云CDN的wordpress CDN刷新插件有哪些?
回答,有8中插件,其中阿里云CDN刷新插件 (Aliyun CDN Purge)、阿里云CDN WordPress插件 (Aliyun CDN for WordPress)是专门给阿里云CDN定制的。提供自动缓存清除、手动缓存清除等功能。
高兴坏了,以为问题迎刃而解,于是wordpress插件市场搜索,两个都无果,以为没有上市场。于是改度娘,还是找不到;再换B乎,还是没有人知道。失望之余再返回来问通义千问,结果它告诉我去GitHub和阿里云社区试试,兴冲冲去了,败兴而归。于是再问他,让它直接给下载链接。
这次它承认没有链接可提供了,说如果没有这款插件,那么可提供自定义开发示例。我才弄明白,这伙计从开始就是信口开河,随便编了两个插件名称在糊弄我。不过虽然人品不行,但能力还是有的,随手就给我了一个插件示例,代码直接给出。
SDK+functions法(未使用)
但它给出的代码要使用Composer安装阿里云PHP SDK,代码如下。
composer require alibabacloud/sdk
如果没有安装Composer,需要先安装。
最后将下面代码直接贴到functions.php里即可使用。
SDK方法需要替换your_access_key_id、your_access_key_secret和your_cdn_domain为自己的实际值。
function aliyun_cdn_purge($post_id) {
require_once __DIR__ . '/vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
$accessKeyId = 'your_access_key_id';
$accessKeySecret = 'your_access_key_secret';
$domainName = 'your_cdn_domain';
AlibabaCloud::accessKeyClient($accessKeyId, $accessKeySecret)
->regionId('cn-hangzhou')
->asDefaultClient();
try {
$result = AlibabaCloud::rpc()
->product('Cdn')
->version('2018-05-10')
->action('PushObjectCache')
->method('POST')
->options([
'query' => [
'ObjectPath' => $domainName . '/',
'ObjectType' => 'Directory',
],
])
->request();
if ($result->isSuccess()) {
error_log('CDN Cache Purged Successfully: ' . json_encode($result->toArray()));
} else {
error_log('Failed to Purge CDN Cache: ' . json_encode($result->toArray()));
}
} catch (ClientException $e) {
error_log('Client Exception: ' . $e->getErrorMessage());
} catch (ServerException $e) {
error_log('Server Exception: ' . $e->getErrorMessage());
}
}
add_action('save_post', 'aliyun_cdn_purge');
add_action('deleted_post', 'aliyun_cdn_purge');
SDK+插件法(未采用)
我觉得还是插件方便一些,于是接着问通义千问,怎么把上面代码变成插件,回答如下。
在WordPress安装目录下的 wp-content/plugins/ 文件夹中创建一个新的文件夹,命名为Aliyun CDN Purge;在文件夹里新建一个PHP文件,同样命名为Aliyun CDN Purge,然后把下面代码复制进去即可。
先安装好SDK,在 aliyun-cdn-purge 文件夹中打开以下命令行,并运行以下命令:
composer require alibabacloud/sdk
这会在您的插件文件夹中创建一个 vendor 目录,并下载必要的依赖包。
将以下代码复制进aliyun-cdn-purge.php,即可制成插件。
<?php
/*
Plugin Name: Aliyun CDN Purge
Plugin URI: http://yourwebsite.com/
Description: A simple plugin to purge Aliyun CDN cache on post save and delete.
Version: 1.0
Author: Your Name
Author URI: http://yourwebsite.com/
License: GPL2
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
// 配置信息
define('ALIYUN_ACCESS_KEY_ID', 'your_access_key_id');
define('ALIYUN_ACCESS_KEY_SECRET', 'your_access_key_secret');
define('ALIYUN_CDN_DOMAIN', 'your_cdn_domain');
function aliyun_cdn_purge($post_id) {
require_once __DIR__ . '/vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
AlibabaCloud::accessKeyClient(ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET)
->regionId('cn-hangzhou')
->asDefaultClient();
try {
$result = AlibabaCloud::rpc()
->product('Cdn')
->version('2018-05-10')
->action('PushObjectCache')
->method('POST')
->options([
'query' => [
'ObjectPath' => ALIYUN_CDN_DOMAIN . '/',
'ObjectType' => 'Directory',
],
])
->request();
if ($result->isSuccess()) {
error_log('CDN Cache Purged Successfully: ' . json_encode($result->toArray()));
} else {
error_log('Failed to Purge CDN Cache: ' . json_encode($result->toArray()));
}
} catch (ClientException $e) {
error_log('Client Exception: ' . $e->getErrorMessage());
} catch (ServerException $e) {
error_log('Server Exception: ' . $e->getErrorMessage());
}
}
// 添加自动缓存清除钩子
add_action('save_post', 'aliyun_cdn_purge');
add_action('deleted_post', 'aliyun_cdn_purge');
我只想要个插件,先安装个依赖库,那也太麻烦了。于是问它有没有不需要安装SDK的方法,它说有,让我把SDK库下下来,在插件包里新建一个sdk文件夹,放入下载的库即可。并给出了下载链接。链接如下
https://github.com/aliyun/openapi-sdk-php?spm=5176.28103460.0.0.297c5d27sy4dGg
我一看这个库里有上千个文件,不可能全放在插件里,于是问有没有精简的SDK库,千问给出了一个精简列表。
- AlibabaCloud\Client\AlibabaCloud.php
- AlibabaCloud\Client\Exception\ClientException.php
- AlibabaCloud\Client\Exception\ServerException.php
- AlibabaCloud\Client\Request\RequestOptions.php
- AlibabaCloud\Client\Regions\EndpointProvider.php
- AlibabaCloud\Client\Regions\RegionProviderInterface.php
- AlibabaCloud\Client\Regions\SimpleRegionProvider.php
- AlibabaCloud\Client\Signature\ShaHmac1Signature.php
- AlibabaCloud\Client\Signature\SignatureInterface.php
- AlibabaCloud\Client\Signer\RsaKeyPairSigner.php
- AlibabaCloud\Client\Signer\SignerInterface.php
- AlibabaCloud\Client\Transport\CurlTransport.php
- AlibabaCloud\Client\Transport\TransportInterface.php
- AlibabaCloud\Client\Utilities\ArrayAccessTrait.php
- AlibabaCloud\Client\Utilities\Json.php
- AlibabaCloud\Client\Utilities\Utils.php
- AlibabaCloud\Client\Utilities\Xml.php
- AlibabaCloud\Client\Utilities\HttpHeaders.php
- AlibabaCloud\Client\Utilities\HttpMethod.php
- AlibabaCloud\Client\Utilities\HttpResponse.php
- src/Product/Cdn/Cdn.php
- src/Product/Cdn/CdnApiResolver.php 文件
我看了下这个文件列表,也被劝退了,这样的话插件就太大了。
通义千问给出了依赖这个精简SDK库的插件php文件,虽然我没有使用,但也贴出来,方便大家参考,也备着万一哪天自己想折腾的时候参考。
<?php
/*
Plugin Name: Aliyun CDN Purge
Plugin URI: http://yourwebsite.com/
Description: A simple plugin to purge Aliyun CDN cache on post save and delete.
Version: 1.0
Author: Your Name
Author URI: http://yourwebsite.com/
License: GPL2
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
// 配置信息
define('ALIYUN_ACCESS_KEY_ID', 'your_access_key_id');
define('ALIYUN_ACCESS_KEY_SECRET', 'your_access_key_secret');
define('ALIYUN_CDN_DOMAIN', 'your_cdn_domain');
// 引入阿里云SDK
require_once __DIR__ . '/sdk/autoload.php';
function aliyun_cdn_purge($post_id) {
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
AlibabaCloud::accessKeyClient(ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET)
->regionId('cn-hangzhou')
->asDefaultClient();
try {
$result = AlibabaCloud::rpc()
->product('Cdn')
->version('2018-05-10')
->action('PushObjectCache')
->method('POST')
->options([
'query' => [
'ObjectPath' => ALIYUN_CDN_DOMAIN . '/',
'ObjectType' => 'Directory',
],
])
->request();
if ($result->isSuccess()) {
error_log('CDN Cache Purged Successfully: ' . json_encode($result->toArray()));
} else {
error_log('Failed to Purge CDN Cache: ' . json_encode($result->toArray()));
}
} catch (ClientException $e) {
error_log('Client Exception: ' . $e->getErrorMessage());
} catch (ServerException $e) {
error_log('Server Exception: ' . $e->getErrorMessage());
}
}
// 添加自动缓存清除钩子
add_action('save_post', 'aliyun_cdn_purge');
add_action('deleted_post', 'aliyun_cdn_purge');
由于我们没有使用Composer来管理依赖,我们需要手动创建一个简单的自动加载文件 autoload.php 来加载所有类文件。
在 sdk 文件夹中创建 autoload.php 文件,并添加以下内容:
<?php
spl_autoload_register(function ($class) {
$prefix = 'AlibabaCloud\\Client\\';
$base_dir = __DIR__ . '/';
// 检查是否是我们的命名空间
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
return;
}
// 获取相对类名
$relative_class = substr($class, $len);
// 转换为文件路径
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
// 如果文件存在,则加载它
if (file_exists($file)) {
require $file;
}
});
CLI+插件
突然灵机一动,我以前在老麦帮助下想实现ssl证书自动上传阿里云CDN,安装了CLI,是否在有CLI情况下就不需要SDK依赖?接着问通义千问,它回答可以。
CLI方案只需要设置CDN_DOMAIN即可,也就是自己在阿里云CDN上的域名,非CNAME,其他不用设置。
以下是基于CLI能正常访问的情况下进行的,且web用户具有访问CLI的权限,一般情况下配置CLI可能是用的root用户,需要确认。
ssh登录服务器,执行以下命令。
首先,您需要切换到Web服务器用户。假设您的Web服务器用户是 www-data,您可以使用以下命令切换用户:
sudo su -s /bin/bash www-data
其次. 测试CLI命令
在切换到 www-data 用户后,尝试运行阿里云CLI命令来测试是否可以正常执行。例如:
aliyun cdn RefreshObjectCaches --ObjectPath=/path/to/your/cdn/resource --ObjectType=File
或者,可以运行一个简单的帮助命令来测试CLI工具是否可用:
aliyun help
当CLI可执行时,添加以下插件。
新建插件文件夹aliyun-cdn-purge-cli,在里面新建aliyun-cdn-purge-cli.php,复制进如下代码即可。
<?php
/*
Plugin Name: Aliyun CDN Purge CLI
Plugin URI: http://yourwebsite.com/
Description: A simple plugin to purge Aliyun CDN cache using the Aliyun CLI on post save, delete, and new comment.
Version: 1.0
Author: Your Name
Author URI: http://yourwebsite.com/
License: GPL2
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
// 配置信息
define('ALIYUN_CDN_DOMAIN', 'your_cdn_domain');
function aliyun_cdn_purge_cli($post_id) {
$object_path = ALIYUN_CDN_DOMAIN . '/';
$command = "aliyun cdn RefreshObjectCaches --ObjectPath=$object_path --ObjectType=Directory";
// 执行CLI命令
exec($command, $output, $return_var);
if ($return_var === 0) {
error_log('CDN Cache Purged Successfully: ' . implode("\n", $output));
} else {
error_log('Failed to Purge CDN Cache: ' . implode("\n", $output));
}
}
// 添加自动缓存清除钩子
add_action('save_post', 'aliyun_cdn_purge_cli');
add_action('deleted_post', 'aliyun_cdn_purge_cli');
// 添加评论相关的缓存清除钩子
add_action('comment_post', 'aliyun_cdn_purge_cli_on_comment', 10, 2);
function aliyun_cdn_purge_cli_on_comment($comment_id, $comment_approved) {
// 只有当评论被批准时才清除缓存
if ($comment_approved) {
$comment = get_comment($comment_id);
$post_id = $comment->comment_post_ID;
// 获取文章URL
$post_url = get_permalink($post_id);
$object_path = parse_url($post_url, PHP_URL_PATH);
// 构建CLI命令
$command = "aliyun cdn RefreshObjectCaches --ObjectPath=$object_path --ObjectType=File";
// 执行CLI命令
exec($command, $output, $return_var);
if ($return_var === 0) {
error_log('CDN Cache Purged Successfully for Comment: ' . implode("\n", $output));
} else {
error_log('Failed to Purge CDN Cache for Comment: ' . implode("\n", $output));
}
}
}
配置信息:
ALIYUN_CDN_DOMAIN:定义您的CDN域名。
主要功能函数 aliyun_cdn_purge_cli:
这个函数用于清除整个目录的缓存。
使用 exec 函数执行阿里云CLI命令来清除缓存。
检查命令执行结果并记录日志。
钩子 save_post 和 deleted_post:
当文章被保存或删除时调用 aliyun_cdn_purge_cli 函数。
评论相关的缓存清除钩子 comment_post:
当有新评论时,comment_post 钩子会被触发。
aliyun_cdn_purge_cli_on_comment 函数检查评论是否被批准($comment_approved)。
如果评论被批准,获取评论所属的文章ID,并构建文章的URL。
使用 aliyun cdn RefreshObjectCaches 命令清除特定文章的缓存。
兼容W3 Total cache的CLI+插件方案
因为我使用了W3 Total cache插件,担心插件和W3不兼容,于是问通义千问上面的插件会不会和W3冲突。同时问了怎么增加一个设置界面,以及增加插件说明等功能,大概聊了几万字,最后给的方案如下。
假设您的插件目录结构如下:
新建插件文件夹aliyun-cdn-purge-cli,里面新建aliyun-cdn-purge-cli.php和设置页面文件 settings.php,分别复制进如下代码。
aliyun-cdn-purge-cli
<?php
/*
Plugin Name: Aliyun CDN Purge CLI
Plugin URI: http://www.leitao.cn/
Description: 这是一款在发布新文章和有新评论通过时刷新阿里云CDN缓存的插件.
Version: 1.0
Author: savouer
Author URI: http://www.leitao.cn/
License: GPL2
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
// 定义常量
define('ALIYUN_CDN_PURGE_CLI_PATH', plugin_dir_path(__FILE__));
define('ALIYUN_CDN_PURGE_CLI_URL', plugin_dir_url(__FILE__));
// 引入设置页面
require_once ALIYUN_CDN_PURGE_CLI_PATH . 'settings.php';
// 主要功能函数
function aliyun_cdn_purge_cli($post_id) {
$cdn_domain = get_option('aliyun_cdn_domain', '');
if (empty($cdn_domain)) {
error_log('CDN Domain is not set. Please configure it in the settings.');
return;
}
$object_path = $cdn_domain . '/';
$command = "aliyun cdn RefreshObjectCaches --ObjectPath=$object_path --ObjectType=Directory";
// 执行CLI命令
exec($command, $output, $return_var);
if ($return_var === 0) {
error_log('CDN Cache Purged Successfully: ' . implode("\n", $output));
} else {
error_log('Failed to Purge CDN Cache: ' . implode("\n", $output));
}
}
// 添加自动缓存清除钩子
add_action('save_post', 'aliyun_cdn_purge_cli_check_and_purge');
add_action('deleted_post', 'aliyun_cdn_purge_cli_check_and_purge');
// 添加评论相关的缓存清除钩子
add_action('comment_post', 'aliyun_cdn_purge_cli_check_and_purge_comment', 10, 2);
// 修改钩子函数以检查选项
function aliyun_cdn_purge_cli_check_and_purge($post_id) {
if (get_option('purge_cdn_on_save_delete', false)) {
aliyun_cdn_purge_cli($post_id);
}
}
function aliyun_cdn_purge_cli_check_and_purge_comment($comment_id, $comment_approved) {
if (get_option('purge_cdn_on_new_comment', false) && $comment_approved) {
aliyun_cdn_purge_cli_on_comment($comment_id, $comment_approved);
}
}
function aliyun_cdn_purge_cli_on_comment($comment_id, $comment_approved) {
// 只有当评论被批准时才清除缓存
if ($comment_approved) {
$comment = get_comment($comment_id);
$post_id = $comment->comment_post_ID;
$cdn_domain = get_option('aliyun_cdn_domain', '');
if (empty($cdn_domain)) {
error_log('CDN Domain is not set. Please configure it in the settings.');
return;
}
// 获取文章URL
$post_url = get_permalink($post_id);
$object_path = parse_url($post_url, PHP_URL_PATH);
// 构建CLI命令
$command = "aliyun cdn RefreshObjectCaches --ObjectPath=$object_path --ObjectType=File";
// 执行CLI命令
exec($command, $output, $return_var);
if ($return_var === 0) {
error_log('CDN Cache Purged Successfully for Comment: ' . implode("\n", $output));
} else {
error_log('Failed to Purge CDN Cache for Comment: ' . implode("\n", $output));
}
}
}
// 添加插件页面上的设置按钮
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'aliyun_cdn_purge_cli_settings_link');
function aliyun_cdn_purge_cli_settings_link($links) {
$settings_link = '<a href="' . admin_url('options-general.php?page=aliyun-cdn-purge-settings') . '">设置</a>';
array_unshift($links, $settings_link);
return $links;
}
settings
<?php
// 添加管理菜单
add_action('admin_menu', 'aliyun_cdn_purge_cli_menu');
function aliyun_cdn_purge_cli_menu() {
add_options_page(
'Aliyun CDN Purge Settings',
'Aliyun CDN Purge',
'manage_options',
'aliyun-cdn-purge-settings',
'aliyun_cdn_purge_cli_settings_page'
);
}
function aliyun_cdn_purge_cli_settings_page() {
?>
<div class="wrap">
<h1>Aliyun CDN Purge Settings</h1>
<p>此插件基于服务器已安装阿里云CLI,并且正确配置阿里云访问密钥和区域信息。</p>
<p>此插件允许您在发布、删除文章或批准新评论时自动清除阿里云CDN缓存,请使用以下选项来配置插件设置。</p>
<form method="post" action="options.php">
<?php
settings_fields('aliyun_cdn_purge_cli_settings');
do_settings_sections('aliyun_cdn_purge_cli_settings');
?>
<table class="form-table">
<tr valign="top">
<th scope="row">请输入CDN域名</th>
<td><input type="text" name="aliyun_cdn_domain" value="<?php echo esc_attr(get_option('aliyun_cdn_domain', '')); ?>" class="regular-text" /></td>
</tr>
<tr valign="top">
<th scope="row">在新文章发布或删除时清除阿里云CDN缓存</th>
<td><input type="checkbox" name="purge_cdn_on_save_delete" value="1" <?php checked(get_option('purge_cdn_on_save_delete', false), true); ?> /></td>
</tr>
<tr valign="top">
<th scope="row">在有新评论通过时清除阿里云CDN缓存</th>
<td><input type="checkbox" name="purge_cdn_on_new_comment" value="1" <?php checked(get_option('purge_cdn_on_new_comment', false), true); ?> /></td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
// 注册设置
add_action('admin_init', 'aliyun_cdn_purge_cli_register_settings');
function aliyun_cdn_purge_cli_register_settings() {
register_setting('aliyun_cdn_purge_cli_settings', 'aliyun_cdn_domain');
register_setting('aliyun_cdn_purge_cli_settings', 'purge_cdn_on_save_delete');
register_setting('aliyun_cdn_purge_cli_settings', 'purge_cdn_on_new_comment');
}
插件说明如下:
主插件文件 aliyun-cdn-purge-cli.php:
定义了插件的基本信息。
引入了设置页面的相关代码。
添加了一个过滤器 plugin_action_links_ 来在插件页面上添加一个设置按钮。
在主要功能函数 aliyun_cdn_purge_cli 和 aliyun_cdn_purge_cli_on_comment 中使用 get_option 函数来获取 cdn_domain。
设置页面文件 settings.php:
添加了一个管理菜单项,用于配置插件的选项。
提供了一个表单,允许用户输入 cdn_domain 并选择是否启用特定的缓存清除功能。
注册了设置选项,以便在WordPress后台保存这些选项。
聊天和改进插件的过程很愉快,没感觉到一天时间就过去了,安装后能设置,但就是没有CDN刷新效果。于是又聊了几万字的故障排除,最终也没有解决问题,遂放弃。
不懂代码,又是个实诚人,连续几个小时可把AI给聊爽了。不过作为聊伴,通义千问也很不错,不断地被问小白问题也丝毫不烦,一直耐心的解答,虽然没有最终解决我的问题,但过程中也弄明白了很多事情,这对以后的折腾绝对有帮助。不由感叹,AI还是有其不可替代的优势的,起码很难找一个脾气这么好的技术大牛,连续被问好几个小时的小白问题,还不发脾气。
以上最后一个插件,如果有大佬懂代码,能够指出问题出在那,或者直接帮我修改下,不胜感激。
这次折腾以失败告终,但有了思路,以后可能还会不断寻找和折腾,这就是玩具的意义。
29 条评论