NginX多进程模型中,Master进程管理其派生的子进程,Worker进程处理连接请求。在某些情况下,NginX Master进程会启动两个与Cache相关的进程,即:Cache Manager/Cache Loader用于缓存上游服务器的数据(譬如:ngx_http_proxy_module中设置proxy_cache_path)。本文将介绍Cache Manager/Cache Loader的内部运行机制。
NginX中cache的原理是:将上游服务器返回的数据缓存在本地文件中,如果请求命中缓存,则直接通过sendfile将缓存文件的内容发送给下游。以ngx_http_proxy_module为例来说明cache的原理。ngx_http_proxy_module通过proxy_cache_path指令完成file cache的初始化。
1. Cache的管理
Cache的管理由Cache Loader/Cache Manager两个进程合作完成;Cache Manager的功能是定期清理过期缓存(基本策略为LRU);Cache Loader的功能是将已经缓存文件映射到内存中。
1.1 初始化
通过调用ngx_http_file_cache_set_slot函数,NginX能获得一个Cache管理的目录实例;NginX在ngx_init_cycle阶段完成目录创建工作。
ngx_start_cache_manager_processes函数是触发Cache Loader/Cache Manager进程启动的入口。接下来将分别进行介绍。
1.2 Cache Manager
Cache Manager进程的核心逻辑是一个定时器任务处理;其回调函数为ngx_cache_manager_process_handler。接下来分析一下代码:
static void
ngx_cache_manager_process_handler(ngx_event_t *ev)
{
time_t next, n;
ngx_uint_t i;
ngx_path_t **path;
next = 60 * 60; /// 默认为1小时
path = ngx_cycle->paths.elts;
for (i = 0; i < ngx_cycle->paths.nelts; i++) {
if (path[i]->manager) {
n = path[i]->manager(path[i]->data); /// 执行回调(ngx_http_file_cache_manager) 返回n表示下一个过期检查时间点。
next = (n <= next) ? n : next;
ngx_time_update();
}
}
if (next == 0) {
next = 1;
}
<strong> ngx_add_timer(ev, next * 1000); /// 再次将任务追加到定时器中。</strong>
}
ngx_http_file_cache_manager回调函数功能为:(1)删除时间过期的缓存文件 (2) 缓存文件大小超限,删除最近最久的缓存文件。接下来看一下代码:
static time_t
ngx_http_file_cache_manager(void *data)
{
ngx_http_file_cache_t *cache = data;
off_t size;
time_t next, wait;
next = ngx_http_file_cache_expire(cache); /// 删除时间过期的缓存文件
cache->last = ngx_current_msec;
cache->files = 0;
for ( ;; ) {
ngx_shmtx_lock(&cache->shpool->mutex);
size = cache->sh->size;
ngx_shmtx_unlock(&cache->shpool->mutex);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"http file cache size: %O", size);
if (size < cache->max_size) {
return next;
}
wait = ngx_http_file_cache_forced_expire(cache); /// 缓存文件大小超限,删除最近最久的缓存文件
if (wait > 0) {
return wait;
}
if (ngx_quit || ngx_terminate) {
return next;
}
}
}
首先看一下ngx_http_file_cache_expire函数,代码分析如下:
static time_t
ngx_http_file_cache_expire(ngx_http_file_cache_t *