Chinaunix首页 | 论坛 | 博客
  • 博客访问: 263433
  • 博文数量: 19
  • 博客积分: 1608
  • 博客等级: 上尉
  • 技术积分: 335
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-10 10:05
文章分类

全部博文(19)

文章存档

2012年(3)

2011年(6)

2010年(7)

2009年(3)

分类:

2009-09-01 14:53:46

PURGE操作

Squid接受一种客户请求方式,用于删除cache对象。PURGE方式并非官方HTTP请求方式之一。它与DELETE不同,对后者,squid将其转发到原始服务器。PURGE请求要求squid删除在uri里提交的目标。squid返回200(OK)或404(Not Found)。

注意某个单独的URI不唯一标明一个缓存响应。Squid也在cache关键字里使用原始请求方式。假如响应包含了不同的头部,它也可以使用其他请求头。当你发布PURGE请求时,Squid使用GET和HEAD的原始请求方式来查找缓存目标。而且,Squid会删除响应里的所有variants,除非你在PURGE请求的相应头部里指定了要删除的variants。Squid仅仅删除GET和HEAD请求的variants。


purge流程
// 处理squidclient发过来的请求
clientProcessRequest()
{
if (r->method == METHOD_PURGE) 
{
//处理PURGE请求,在一次purge操作中会两次进入该函数
clientPurgeRequest(http)
{
// 如果ACL设置不允许PURGE,则直接返回LOG_TCP_DENIED(拒绝访问)信息
if (!Config2.onoff.enable_purge)
{
errorAppendEntry(http->entry, err);
return;
}
// 释放IPcache数据(IP——hostname)
ipcacheInvalidate(http->request->host);
// 进入一次,处理支持vary的情况,首先需要找到base Entry
if (!http->flags.purging)
{
// 保证只进入一次,初始值为0
http->flags.purging = 1;
// 搜索是否存在这个entry
entry = storeGetPublicByRequestMethod(http->request, METHOD_...);
if (entry)
{
http->entry = entry;
// 设置为PURGE方法,才能保证会二次进入cliengPurge函数
http->entry->mem_obj->method = http->request->method;
http->sc = storeClientRegister(http->entry, http);
storeClientCopyHeaders(http->sc, http->entry, clientCacheHit, http)
{
......
clientCacheHit()
{
......
// vary支持处理,如果没有vary则进入case VARY_NONE跳出
switch (varyEvaluateMatch(e, r)
{
case VARY_NONE:
break;
......
}
// 前面已经设置了方法为METHOD_PURGE,所以二次进入clientPurge函数
if (r->method == METHOD_PURGE)
{
// 置空,在后面再进行设置
http->entry = NULL;
storeClientUnregister(http->sc, e, http);
http->sc = NULL;
storeUnlockObject(e);
// 再次进入,此时http->flags.purging=1,不在进入vary处理流程
clientPurgeRequest(http);
return;
}
}
}
}
}
http->log_type = LOG_TCP_MISS;
//得到准备删除的storeEntry
entry = storeGetPublicByRequestMethod(http->request, METHOD_GET);
if (entry)
{
// 释放storeEntry
storeRelease(entry)
{
// 如果该storeEntry已被其它流程所用,则不直接删除,而是采用过期方式
if (storeEntryLocked(e))
{
// 设置过期时间为当前时间
storeExpireNow(e);
// 释放请求
storeReleaseRequest(e)
{
EBIT_SET(e->flags, RELEASE_REQUEST);
EBIT_CLR(e->flags, ENTRY_CACHABLE);
// 设置为私有,后续的请求将不会被HIT
storeSetPrivateKey(e);
}
return;
}
// 在重建过程当中,删除需要考虑冲突问题
if (store_dirs_rebuilding && e->swap_filen > -1)
{
if (e->swap_filen > -1)
{
//统一由LateReleaseStack来处理
}
else
// 释放storeEntry节点
destroy_StoreEntry(e);
}
// 存在文件进行文件删除操作
if (e->swap_filen > -1)
{
// 删除文件操作,由各个文件系统负责
storeUnlink(e);
// 如果不是一个私有的storeEntry,则在swap.state中添加一条删除的记录
if (!EBIT_TEST(e->flags, KEY_PRIVATE))
storeDirSwapLog(e, SWAP_LOG_DEL);
}
// 从内存中的hot object中置换出来
storeSetMemStatus(e, NOT_IN_MEMORY);
//删除storeEntry节点
destroy_StoreEntry(e);
}
status = HTTP_OK;
}
// 删除head方法得到的storeEntry
entry = storeGetPublicByRequestMethod(http->request, METHOD_HEAD);
if (entry)
{
// 释放storeEntry
storeRelease(entry);
status = HTTP_OK;
}
// 如果base下的storeEntry全部已删除,则删除base storeEntry
if (http->request->vary_headers && !strstr(http->request->vary_headers, "="))
{
.......
}
// 回复标准的数据给squidclient
// 生成新的storeEntry用于回复,在释放请求时释放该storeEntry
http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags);
httpReplyReset(r = http->entry->mem_obj->reply);
httpReplySetHeaders(r, status, NULL, NULL, 0, -1, squid_curtime);
httpReplySwapOut(r, http->entry);
storeComplete(http->entry);
}
return;
}

总结:
1、squidclient的purge操作会删除内存中storeEngry下的mem_obj,storeEntry以及在disk中的文件;
2、在删除过程中如果storeEntry已被其它流程所有(判断看lock锁),则purge操作仅设置storeEntry的过期时间为当前时间,并且设置storeEntry为私有,以防后续请求HIT;
3、通过设置过期后的storeEntry将在cache_mem老化时再进行删除。
阅读(6205) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~