下面是参考文献[1]的翻译
简介
ATS既可以用作HTTP代理,也可以用作HTTP缓存,ATS能够缓存任何字节流,虽然它当前只支持HTTP协议传输的字节流,当这样的流缓存时,会带一个HTTP协议头部,会命名为缓存中的一个对象object。每个对象通过一个名为cache key的全局唯一值识别。
该文档的目的是描述ATS缓存的基本结构和实现细节。缓存的配置只讨论到需要理解内部机制的程度。这篇文档对ATS源码和插件(codebase or plugins)开发者很有帮助。该文档假定读者对管理员文档已经比较熟悉,特别是对其中的HTTP Proxy Caching[2]和Configuring the Cache[3]以及相关的配置和值比较熟悉。
很遗憾内部术语并不特别一致,所以该文档将会频繁使用不同方式的术语,以达到某种一致性。
缓存结构Cache Layout
下面的小节描述了持久缓存数据persistent cache data的组织细节。ATS将它的持久存储视作一个毫不加区分的字节的集合,假设再没有其它结构描述它。特别地,它并不会用到操作系统的文件系统。
假如使用一个file,仅是表明要用到它所含的字节集合。
Cache storage
ATS缓存的原生storage在storage.config中配置,文件中的每行描述了一个cache span,它被视作一个统一的持久存储。
该storage进一步被组织成一个cache volumes的集合,在volume.config文件中配置,它被用作其它管理级别配置的单位。
cache volumes可以定义为total storage的百分比,或者storage的绝对量。为了稳妥,默认每个cache voluem分散到所有的cache span。
cache volume和cache span的交集是cache stripe。每个cache span分割为cache stripes,每个cache volumes可以定义为total是这些stripes的集合。
假如这个cache spans例子中的cache volumes定义如下
那么实际的结构layout形如
cache stripes是该实现的缓存基础单元,一个cached object完整存放在单个stripe中,因而也在单个cache span中。缓存对象绝不会分割后存放到多个span红色volumes中。
Objects被指定到一个stripe,因而被指定到一个cache volume,自动基于URI的hash去检索来自源站的object。可以在hosting.config中做配置来限制对象的广度。
该配置文件支持将指定的hosts和域名存放到特定的cache volumes。从4.0.1版本后,也可以控制哪些cache spans,因而哪些cache stripes包含在指定的cache volumes中。
cache spans,cache volumes和cache stripes(组成前两者)的结构(layout and structure)完全来自storage.config和cache.config的配置,当traffic_server启动时
会从头重新计算。因此,那些配置文件的任何变化都能(差不多总是)导致现存缓存的完整性失效。
Stripe Structure
ATS将与cache stripe相关的storage视作一个不加区分的字节带(span of bytes).在内部,每个stripe视作毫不相关。本节描述的数据结构仅针对stripe内部。
在源码中术语volume用作cache stripe,主要在Vol中实现,读者称作volume的东西(本文档称作cache volume),这里表示为CacheVol。
注意
stripe划分必须在处理object之前,因为object所在的目录在stripe内部,当stripe划分改变时,其中所含的任何缓存对象cached objects必定会丢失,因为它们的目录数据不会在新stripe中找到。
缓存目录Cache Directory
stripe中的内容通过目录directory追踪,目录中的每个元素就是directory entry,表示为Dir。每个元素引用缓存中的一段连续存储区,它们有各种称呼,比如fragments,segments,docs,documents,和其它说法。总体来说,目录就是以cache ID为key的一个hash。参见directory probing去了解如何使用cache ID来定位一个directory entry。cache key是content的URL,cache ID由cache key计算得到。
directory用作内存中的驻留结构memory resident structure,这意味着directory entry要尽可能小,当前为10个字节。这迫使存放的数据做某些妥协。另一方面,这意味着,绝大多数cache miss不要求磁盘I/O,这样将会有相当大的性能优势。
目录总是完全划分好的,一旦stripe初始化好,对应的directory大小就是固定的,绝不会再改变,并与stripe大小(近似线性)相关。这就是ATS内存footprint与磁盘缓存大小紧密相关的原因。因为目录大小不变,对内存要求也不变,所以ATS随着缓存中存放内容的增多并不会再消耗更多的内存。假如当缓存为空时,运行ATS足够,那么当缓存存满后,运行ATS也是足够的。
每个directory entry中存放了在stripe中的offset和size,size是fragment中实际数据大小的近似值(至少大于),精确的size data存放在磁盘中fragment header中。
注意
HTTP headers中的数据不经过磁盘I/O并不能检查。这包括对象的original URL, cache key没有精确存放,因而不能可靠地检索到。
……
缓存初始化Initialization
缓存初始化会开启一个Store实例,通过读storage配置文件,默认为storage.config。对该配置文件中的每个合法元素,会创建一个Span实例,基本上有四种类型的实例:File,Directory,Disk,Raw device。
在生成所有的Span实例后,它们按device ID分组到内部链表中并挂接到Store::disk数组上。引用同一个目录,磁盘或裸盘的那些Spans被组合进同一个span中。引用同一个文档但是偏移重叠的Spans也被组合起来,这些工作都在ATS启动时调用ink_cache_init()完成。
span logic也被HostDB使用到,不止一个莫名其妙的feature在那个模块中出现。
在配置初始化后,cache processor调用CacheProcessor::start(),它做了许多事情:
对每个合法的span,创建一个CacheDisk实例,CacheDisk类是一个continuation,能在span上用来执行阻塞操作,该类的主要作用就是传递到AIO线程作为I/O操作完成时的回调函数,然后会传递到AIO薪酬执行storage unit的初始化,在所有这些工作完成后,在cplist_reconfigure()中,得到的storage会分发到volumes中,那时再生成CacheVol实例。
(未完待续……)
单词表
parcel out 分配,把…分成几份
coalesce 使…联合,使…合并
inexplicable 费解的,莫名其妙的
rationale 基本原理
ballpark 大致的,大约的
millage 税率
wholly unjustified 完全不合理
false negative 误报
参考文献
[1].https://docs.trafficserver.apache.org/en/latest/developer-guide/architecture/architecture.en.html
[2].https://docs.trafficserver.apache.org/en/latest/admin/http-proxy-caching.en.html#http-proxy-caching
[3].https://docs.trafficserver.apache.org/en/latest/admin/configuring-cache.en.html#configuring-the-cache
[4].https://github.com/portl4t/trafficserver-doc-zh/blob/master/arch/cache/cache-arch.md