11.2 eJet系统Cache存储架构
eJet系统是否启动缓存由配置信息来设定。如果是反向代理,HTTP请求对应的HTTPLoc下的反向代理开关cache是否开启,即cache=on,cache file项是否设置,来决定是否启动缓存功能;如果是正向代理,在send request选项中,是否启动cache,以及cache file命名规则是否设置,决定是否启动缓存管理。
启动了cache功能,还需要根据当前请求转发给Origin后,返回的响应头中,是否有Cache管理的头信息,来确定当前返回的响应体是否缓存,以及确定当前缓存的相关信息。
缓存的Raw文件内容存储在上述配置中以cache file命名的文件中,当文件所有内容全都下载并存储起来前,文件名后需要增加扩展名.tmp,以表示当前存储文件正在下载中,还不是一个完整的文件,但已经缓存的内容则可以被命中使用。
cache管理信息则存储在缓存信息管理文件(Cache Information Management File)中,简称为CacheInfo文件,CacheInfo文件的存储位置在Raw缓存文件所在目录下建立一个隐藏目录.cacheinfo,CacheInfo文件就存放该隐藏目录下,CacheInfo文件名是在Raw存储文件后增加后缀.cacinf,譬如Raw缓存文件为foo.jpg,则缓存信息管理文件路径为: .cacheinfo/foo.jpg.cacinf
CacheInfo文件的结构包括三部分:Cache头信息(96字节)、Raw存储碎片管理信息。Cache头信息是固定的96字节,其结构如下:
/* 96 bytes header of cache information file */typedef struct cache_info_s { char * cache_file; void * hcache; char * info_file; void * hinfo; uint8 initialized; uint32 mimeid; uint8 body_flag; int header_length; int64 body_length; int64 body_rcvlen; /* Cache-Control: max-age=0, private, must-revalidate Cache-Control: max-age=7200, public Cache-Control: no-cache */ uint8 directive; //0-max-age 1-no cache 2-no store uint8 revalidate; //0-none 1-must-revalidate uint8 pubattr; //0-unknonw 1-public 2-private(only browser cache) time_t ctime; time_t expire; int maxage; time_t mtime; char etag[36]; FragPack * frag; } CacheInfo;
在头信息之后存放的是存储内容碎片管理信息,每个碎片单元为8字节:
typedef struct frag_pack { int64 offset; int64 length;} FragPack;
内存中采用动态有序数组来管理每一个碎片块,相邻块就需要合并成一个块,完整文件只有一个块。将这些碎片块信息按照8字节顺序存储在这个区域中。每当文件有新内容写入时,内存碎片块数组要完成合并等更新,并将最新结果更新到这个区域。碎片块信息管理的是Raw存储文件中从Origin服务器下载并实际存储的数据存储状态,每块是以偏移量和长度来唯一标识,相邻的碎片块合并,完整文件只有一个碎片块。
11.3 eJet系统缓存处理流程
eJet系统作为正向代理或反向代理服务器,实现边下载边缓存、完整缓存时无需代理转发直接返回缓存内容给客户端等功能,可以实现对大大小小的Origin文件的实时缓存功能,包括碎片存储、随机存储等。
(1)全局管理CacheInfo对象
系统维护一个全局的CacheInfo对象哈希表,以Raw缓存文件名作为唯一标识和索引,如果存在多个用户请求同一个需要缓存的Origin文件时,只打开或创建一个CacheInfo对象,该对象成员由互斥锁来保护。而每个对同一Origin文件的HTTP请求,请求位置、偏移量、读写Raw缓存文件的句柄等都保存在各自的HTTPMsg实例对象中。
CacheInfo对象是管理和存放Raw缓存文件的各项元信息,对外暴露的主要接口是: cache_info_open, cache_info_create, cache_info_close, cache_info_add_frag等
用户发起Origin文件请求时,先调用cache_info_open打开CacheInfo对象,如果不存在,则在收到Origin的成功响应后,调用cache_info_create创建CacheInfo对象。每次调用cache_info_open时,如果CacheInfo对象已经在内存中,则将count计数加1,只有count计数为0时才可以删除释放CacheInfo对象。当HTTPMsg成功返回给用户后,需要关闭CacheInfo对象,调用cache_info_close,首先将count计数减1,如果count大于0,直接返回不做资源释放。