`
nanjingjiangbiao_T
  • 浏览: 2594192 次
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

缓存服务器设计与实现(一)

 
阅读更多
这里我们nginx的cache系统为线索,来探讨一个缓存服务器的设计和相关细节,我尽量站在设计和框架的角度来分析,限于篇幅这里不再去撸代码了,相关的细节,欢迎大家一起参与讨论。

一个cache服务器中从后端取得文件之后,要么直接发送给客户端(学名叫透传),要么缓存在本地,后续相同的请求访问到cache服务器时,就可以直接拿本地的拷贝来用了,如果可以用的话。如果本地缓存的文件被后续的请求访问到,在cache中叫做命中(即Hit)。如果本地还没有文件的缓存拷贝,那么cache服务器需要根据配置或者做解析域名,去后端获取文件,这时称为缓存miss,即未命中。关于cache服务器更多的知识,我们在分析nginx的缓存系统时再深入讨论。

nginx的存储系统分两类,一类是通过proxy_store开启的,存储方式是按照url中的文件路径,存储在本地。比如/file/2013/0001/en/test.html,那么nginx就会在指定的存储目录下依次建立各个目录和文件。另一类是通过proxy_cache开启,这种方式存储的文件不是按照url路径来组织的,而是使用一些特殊方式来管理的(这里称为自定义方式),自定义方式就是我们要重点分析的。那么这两种方式各有什么优势呢?

按url路径存储文件的方式,程序处理起来比较简单,但是性能不行。首先有的url巨长,我们要在本地文件系统上建立如此深的目录,那么文件的打开和查找都很会很慢(回想kernel中通过路径名查找inode的过程吧)。如果使用自定义方式来处理模式,尽管也离不开文件和路径,但是它不会因url长度而产生复杂性增加和性能的降低。从某种意义上说这是一种用户态文件系统,最典型的应该算是squid中的CFS。nginx使用的方式相对简单,主要依靠url的md5值来管理,后面我们会分析。

缓存离不开从后端取内容,然后发送给客户端。具体的处理方式大家很容易就会想到,肯定是一边接收一边发送,其他的方式都太低效了,如读完再发等等。这里提一下nginx边收边发,使用的结构是ngx_event_pipe_t,它是沟通后端和客户端的媒介。由于该结构是一个通用组件,所以需要一些特殊的标记来处理涉及存储的相关功能,那么成员cacheable就担当了这份重任。
p->cacheable = u->cacheable || u->store;
即cacheable为1,则需要存储,否则不存储。那么u->cacheable跟u->store代表什么?他们分别代表前面说的两种方式,即proxy_cache和proxy_store。

(补充一些知识,nginx在取后端数据时,它的行为受proxy_buffering控制,作用是为后端的服务器启用应答缓冲。如果启用缓冲,nginx假设被代理服务器能够非常快的传递应答,并将其放入缓冲区,可以使用proxy_buffer_size和proxy_buffers设置相关参数。如果响应无法全部放入内存,则将其写入硬盘。如果禁用缓冲,从后端传来的应答将立即被传送到客户端。)

这里都是一些擦边球,我们还没有接触nginx cache功能的核心。从实现上看,在nginx upstream结构中有个成员叫cache,它的类型是ngx_shm_zone_t。如果我们开启cache功能,cache成员用来管理共享内存(为什么用到了共享内存?),而其他方式的存储该成员都为NULL。另外有一点需要说明一下,在cache系统中一个文件通常被称为store object,即缓存对象,所以进行cache之前必然需要先创建一个store object。一个重要的问题就是如何选择创建的时机,这点大家有什么看法?首先我们需要检查一个文件是否是需要缓存,很明显GET方法请求的文件一般需要缓存,所以我们在请求处理的前期,看到了GET方法,就可以先创建一个对象。但是很多时候,即使是一个GET方法请求的文件也不能缓存,那么你过早的创建对象,不仅浪费时间也浪费了空间,到头来还要将它销毁。那么什么会影响GET请求的存储呢?那就是响应头中的Cache-control字段,这个字段就告诉代理或者浏览器,该文件能否被缓存。一般的cache服务器面对响应头中没有Cache-control字段的请求,默认都是要缓存的。

基于这一点的考虑,我们开发的cache服务器就是在响应头解析完成,拿到可缓存的足够证据之后,才会创建缓存对象。遗憾的是,nginx没有这么去做。
nginx在ngx_http_upstream_init_request函数中完成缓存对象的创建,这个函数处在http处理的什么阶段呢?在跟后端建立连接之前。这个地方,我个人认为不太合适。。。大家认为呢?

关于创建过程,大家可以去读函数ngx_http_upstream_cache。这里我拿我们的cache跟nginx对比来分析吧。我们的request中使用一个名叫store的成员,来跟缓存对象建立联系。nginx也差不多,它的request结构体中有个cache成员来做同样的事情。区别在于我们的store成员对应的空间在共享内存中,而nginx则是在r->pool里申请的(我们为什么这么做?)。

下一步,nginx需要根据配置来生成缓存对象的key,此处一般都是用md5来算的。这个key作为一个缓存对象在系统中的唯一标识,很多人可能担心md5碰撞的问题。这个我认为要求如果不是特别苛刻,这里完全可以接受的,而且处理也相对简单。

后面要处理的是,文件到底应该已怎样的形式存储在磁盘?
我们拿前面用过的一个例子:/file/2013/0001/en/test.html,它对应的md5值是8ef9229f02c5672c747dc7a324d658d0,实际上nginx就用它当做文件名。这样就可以了?如果我们找一个目录来存放文件,里面都是一堆这样的文件,那么会怎样?我们知道,大多数文件系统下,都对单个目录下的文件数量有限制,所以这样简单粗暴的处理是不行的。那怎么办?nginx通过配置可以让你使用多级目录,来解决这个问题。简单来说,nginx通过levels这个指令指定目录层数(冒号分隔)和每个目录名字的字符个数,在我们的例子中,假设配置levels=1:2,意思是说使用两级目录,第一级目录名是一个字符,第二级用两个字符。但是nginx最大支持3级目录,即levels=xxx:xxx:xxx。

那么构成目录名字的字符哪来的呢?假设我们的存储目录为/cache,levels=1:2,那么对于上面的文件 就是这样存储的:
/cache/0/8d/8ef9229f02c5672c747dc7a324d658d0
看到0和8d这两个目录名怎么来的了吧,不用解释了。

对象创建完成之后,就需要缓存对象管理结构中去了,这个ngx_http_file_cache_exists去处理的。

如果在创建这个文件时,当前目录及文件已经存在,那如何处理?大家可以去翻翻代码,看nginx怎么处理的。

讨论先告一个段落,其实现在都是一些准备工作,下次讨论后端内容到来的处理。

扩展阅读:
分享到:
评论

相关推荐

    web代理服务器缓存设计

    web代理服务器缓存技术设计方案,几种常用算法策略,原理实现。

    网络代理服务器的设计与实现

    本文首先介绍了代理服务器的工作原理和功能以及HTTP协议,从理论上和实践上论证了设计和实现代理服务器的可行性,然后重点在于分析和设计一个应用于局域网的代理服务器,其中详细讨论了安全机制、缓存技术以及管道流...

    论文研究-一种新型流媒体代理服务器的设计与实现 .pdf

    一种新型流媒体代理服务器的设计与实现,刘玮哲,,本文结合CDN完全缓存和流媒体前缀缓存技术,设计和实现一种新型流媒体代理缓存服务器。该代理服务器处在网络边缘,对用户请求的节

    基于Python实现的HTTP代理服务器设计.zip

    (1)设计并实现一个基本HTTP代理服务器。要求在指定端口(例如8080)接收来自客户的HTTP请求并且根据其中的URL地址访问该地址所指向的HTTP服务器(原服务器),接收HTTP服务器的响应报文,并将响应报文转发给对应的...

    基于C++设计与实现HTTP代理服务器【100011743】

    设计并实现一个基本 HTTP 代理服务器。要求在指定端口(例如 8080)接收来自客户的 HTTP 请求并且根据其中的 URL 地址访问该地址所指向的 HTTP 服务器(原服务器),接收 HTTP 服务器的响应报文,并将响应报文转发给...

    Fikker设计与实现V3

    Fikker缓存加速服务器设计与实现,包含了详细的网络设计,缓存技术设计,容错处理,gzip 设计,防盗链设计,主机管理设计,转向设计等。采用 C 语言实现。 目录: 1. 系统说明 2. 全非阻塞(non-block)网络设计 ...

    基于Android的天气预报应用系统设计与实现.zip

    界面采用了viewpager与fragment结合的方式进行设计,每个fragment对应一个城市页面,可以通过滑动进行翻页控制。且为防止多页面造成的卡顿,app会首先进行fragment的初始化缓存,使软件响应速度得到提升。详细介绍...

    基于SpringCloud的绿植养护软件的设计与实现.docx

    目录 第一章绪论 1.1研究背景 1.2研究现状 1.3论文创新点 1.4论文内容与结构 第二章系统需求分析 2.1系统业务需求 2.1.1用户模块 ...4.2. 2 Redis缓存数据库设计 4.3 EMQ服务器部署 4.4业务微服务实现 ......

    服务器概要设计说明.docx

    服务器概要设计说明全文共5页,当前为第1页。服务器概要设计说明全文共5页,当前为第1页。 服务器概要设计说明全文共5页,当前为第1页。 服务器概要设计说明全文共5页,当前为第1页。 目录 功能概述 2 网络通信层 3 ...

    基于HTTP代理服务器的实现的毕业设计,Socket编程技术,借助第三方库实现HTTP协议的解析和封装,使用多线程技术实现并发

    同时,代理服务器还能够实现Web缓存和内容过滤等功能,提高网络性能和安全性。 该代理服务器主要包括三个模块:请求处理模块、响应处理模块和管理模块。其中,请求处理模块用于拦截客户端请求,并将请求转发到真实...

    服务器硬件技术方案.docx

    服务器虚拟化建设方案 1)建设原则 在系统设计中我们遵循以下原则: ·系统设计的前瞻性: 充分考虑未来5-8年的业务发展的需要。 ·系统设计的先进性: 在经费和技术许可的范围内,引进、吸收和应用先进技术。在...

    <配置服务器概要设计>

    软件描述 配置服务器(Profile Server)管理企业即时通讯系统中的各种配置数据,这些配置数据均是对系统内...因此,配置服务器还负责与对等机的配置数据进行实时同步管理。配置服务器通过实现SPMP协议来实现上述管理。

    服务器硬件组件-RAID控制器、PCI-E.pptx

    RAID卡就是用来实现RAID功能的板卡,通常是由I/O处理器、硬盘控制器、硬盘连接器和缓存等一系列零组件构成的 write through:系统的写入请求直接写入硬盘, 安全性很高,性能很低 write back:系统的写入请求先存放...

    基于SSM框架的高并发电子商务平台设计与实现_吴倩.pdf

    为了解决电子商务平台中高并发带来的难题,改善用户体验,本文融入当前业界的主流技术Nginx负载均衡、Redis缓存和MySQL数据库的主从复制等,搭建了一个具有推荐功能的电商平台。该平台整体采用SSM框架;后端使用高性能...

    基于Web的客户关系管理系统的设计与实现 毕业论文

    进入21世纪,随着企业信息化的发展,CRM(Customer ...在.NET平台上设计实现一套CRM软件管理系统,代码逻辑呈三 层垂直结构,功能模块基本实现,并成功部署在IIS服务器上,可 以在客户端通过浏览器进行访问。

    基于SpringBoot的下沉市场交易平台的设计与实现.docx

    运用面向对象思想和面向服务设计思想完成系统的框架设计,研究以 Zookeeper 作为 Dubbo 服务的注册中心来实现远程服务的调用,并配合使用 Nginx 负载均衡来实现后台服务器的合理调度、研究利用 Mycat 数据库中间件...

    nedomi:HTTP媒体缓存服务器

    我们打算实现一种将所有这些因素都考虑在内的缓存算法,并提供更好的缓存性能和吞吐量。内容演算法nedomi的设计旨在使我们可以更改其工作方式。 对于内部的每个主要部分,它都使用。 希望这将使交换算法时更容易。 ...

    服务器虚拟化部署方案.doc

    1 服务器虚拟化部署方案 2 数据库服务器设计说明 在数据库服务器的配置中,对数据库服务器性能影响较大的有: CPU:数据库查询和修改操作都需要消耗大量的CPU资源,另外数据库都是多线程 应用程序,使用SMP〔对称多...

    论文研究-JavaServlet模式的WebGIS性能优化研究.pdf

    因此对WebGIS服务器端性能问题进行了深入研究,提出了JVM(Java虚拟机)性能调优、建立并改进缓存服务器、使用tmpfs(一种基于内存的文件系统)存储缓存图片等从根本上解决服务器端性能问题的一系列方案,同时设计了...

    基于netty与Springboot实现的编程游戏服务器源码+项目说明.zip

    基于netty与Springboot实现的编程游戏服务器源码+项目说明.zip 使用netty与spring-boot编程游戏服务器。项目结构类似spring-mvc。有一个Dispatch类分发请求到目标类方法 目前。框架集成了redis。mongodb。protocol...

Global site tag (gtag.js) - Google Analytics