最近,公司要使用康乐的几台自建CDN换成Nginx,在缓存配置上不会有很多的问题,纠结的问题是:Nginx的如何批量进行缓存清理

 

我们都知道Nginx提供了一个第三方的模块"nginx ngx_cache_purge",作为缓存清理的一个接口,进行Nginx缓存清理,但是这个接口只能基于url进行清理,这几乎是一个致命的缺点。

因为线上web应用:

    1. url很多

    2. 完全url我们几乎是不可能知道

    3. 如果需要整站清理,那如果一个url,一个url清理,几乎是不可能完成的任务

 

为了有效清理Nginx缓存,我整理出了一个思路:

    1. 在每台CDN上面跑一个清理缓存的daemon(这里我是使用php的socket编写的),原理就是删除缓存目录下的所有文件。

    2. 使用一台控制机,这台控制机通过web的php页面,发送指令给CDN上的daemon,由daemon把CDN上面的所有缓存文件删除。

php_daemon.php

<?php
set_time_limit(0);


$ip = '192.168.182.128';
$port = 10000;

if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {
echo "socket_create() 失败的原因是:".socket_strerror($sock)."\n";
}

if(($ret = socket_bind($sock,$ip,$port)) < 0) {
echo "socket_bind() 失败的原因是:".socket_strerror($ret)."\n";
}

if(($ret = socket_listen($sock,4)) < 0) {
echo "socket_listen() 失败的原因是:".socket_strerror($ret)."\n";
}

include('cache_all.php');
do {
if (($msgsock = socket_accept($sock)) < 0) {
echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
break;
} else {
$msg="测试成功!\n";
socket_write($msgsock, $msg, strlen($msg));

$buf = socket_read($msgsock,8192);
if ($buf == 'clear'){
delete_all('/home/cache');
}


}

socket_close($msgsock);

}while (true);
?>

 cache_all.php

function delete_all($dir)
{
$files=array();
$result=array();
if(is_dir($dir))
{
if($handle=opendir($dir))
{
while(($file=readdir($handle))!==false)
{
if($file!="." && $file!="..")
{
if(is_dir($dir."/".$file))
{
$files[$file]=delete_all($dir."/".$file);
}
else
{
$files[]=$dir."/".$file;

unlink($dir."/".$file);
}
}
}
closedir($handle);
}
}
}

使用php命令行,后台执行php_daemon.php: nohup /usr/local/webserver/php/bin/php php_daemon.php &

查看监听是否成功:netstat -nl |grep 10000

tcp 0 0 192.168.182.128:10000 0.0.0.0:* LISTEN                       #监听成功

web客户端代码:test.php

<?php
header("Content-Type:text/html;charset=utf-8");
error_reporting(E_ALL);
set_time_limit(0);
echo "<h2>TCP/IP Connection</h2>\n";

$port = 10000;
$ip = "192.168.182.128";

/*
+-------------------------------
* @socket连接整个过程
+-------------------------------
* @socket_create
* @socket_connect
* @socket_write
* @socket_read
* @socket_close
+--------------------------------
*/

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) {
echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
}else {
echo "OK.\n";
}

echo "试图连接 '$ip' 端口 '$port'...\n";
$result = socket_connect($socket, $ip, $port);
if ($result < 0) {
echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
}else {
echo "连接OK\n";
}

$in="clear";

if(!socket_write($socket, $in, strlen($in))) {
echo "socket_write() failed: reason: " . socket_strerror($socket) . "\n";
}else {
echo "发送指令成功";
}

while($out = socket_read($socket, 8192)) {
echo "接收服务器回传信息成功!\n";
echo "接受的内容为:",$out;
}


echo "关闭SOCKET...\n";
socket_close($socket);
echo "关闭OK\n";
?>

 通过浏览器访问test.php:

连接成功,查看缓存目录,确定缓存是否清理完成...................