Maison développement back-end tutoriel php nginx的cache系统设计原理

nginx的cache系统设计原理

Aug 08, 2016 am 09:20 AM
cache nbsp nginx proxy store

这里我们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怎么处理的。

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

    扩展阅读:

    http://www.pagefault.info/?p=123

    http://www.pagefault.info/?p=375

以上就介绍了nginx的cache系统设计原理,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment vérifier si Nginx est démarré Comment vérifier si Nginx est démarré Apr 14, 2025 pm 01:03 PM

Comment confirmer si Nginx est démarré: 1. Utilisez la ligne de commande: SystemCTl Status Nginx (Linux / Unix), netStat -ano | Findstr 80 (Windows); 2. Vérifiez si le port 80 est ouvert; 3. Vérifiez le message de démarrage NGINX dans le journal système; 4. Utilisez des outils tiers, tels que Nagios, Zabbix et Icinga.

Comment configurer le nom de domaine du serveur cloud dans nginx Comment configurer le nom de domaine du serveur cloud dans nginx Apr 14, 2025 pm 12:18 PM

Comment configurer un nom de domaine NGINX sur un serveur cloud: Créez un enregistrement A pointant vers l'adresse IP publique du serveur cloud. Ajoutez des blocs d'hôtes virtuels dans le fichier de configuration Nginx, en spécifiant le port d'écoute, le nom de domaine et le répertoire racine du site Web. Redémarrez Nginx pour appliquer les modifications. Accéder à la configuration du test de nom de domaine. Autres notes: Installez le certificat SSL pour activer HTTPS, assurez-vous que le pare-feu autorise le trafic Port 80 et attendez que la résolution DNS prenne effet.

Comment vérifier si Nginx est démarré? Comment vérifier si Nginx est démarré? Apr 14, 2025 pm 12:48 PM

Dans Linux, utilisez la commande suivante pour vérifier si Nginx est démarré: SystemCTL Status Nginx Juges Basé sur la sortie de la commande: si "Active: Active (Running)" s'affiche, Nginx est démarré. Si "Active: Inactive (Dead)" est affiché, Nginx est arrêté.

Comment démarrer le serveur Nginx Comment démarrer le serveur Nginx Apr 14, 2025 pm 12:27 PM

Le démarrage d'un serveur Nginx nécessite différentes étapes en fonction des différents systèmes d'exploitation: Système Linux / Unix: Installez le package NGINX (par exemple, en utilisant Apt-Get ou Yum). Utilisez SystemCTL pour démarrer un service NGINX (par exemple, sudo systemctl start nginx). Système Windows: téléchargez et installez les fichiers binaires Windows. Démarrer Nginx à l'aide de l'exécutable Nginx.exe (par exemple, nginx.exe -c conf \ nginx.conf). Peu importe le système d'exploitation que vous utilisez, vous pouvez accéder au serveur IP

Comment démarrer Nginx dans Linux Comment démarrer Nginx dans Linux Apr 14, 2025 pm 12:51 PM

Étapes pour démarrer Nginx dans Linux: Vérifiez si Nginx est installé. Utilisez SystemCTL Start Nginx pour démarrer le service NGINX. Utilisez SystemCTL Activer Nginx pour activer le démarrage automatique de Nginx au démarrage du système. Utilisez SystemCTL Status Nginx pour vérifier que le démarrage est réussi. Visitez http: // localhost dans un navigateur Web pour afficher la page de bienvenue par défaut.

Comment vérifier la version nginx Comment vérifier la version nginx Apr 14, 2025 am 11:57 AM

Les méthodes qui peuvent interroger la version Nginx sont: utilisez la commande nginx -v; Afficher la directive de version dans le fichier nginx.conf; Ouvrez la page d'erreur Nginx et affichez le titre de la page.

Comment configurer Nginx dans Windows Comment configurer Nginx dans Windows Apr 14, 2025 pm 12:57 PM

Comment configurer Nginx dans Windows? Installez Nginx et créez une configuration d'hôte virtuelle. Modifiez le fichier de configuration principale et incluez la configuration de l'hôte virtuel. Démarrer ou recharger nginx. Testez la configuration et affichez le site Web. Activer sélectivement SSL et configurer les certificats SSL. Définissez sélectivement le pare-feu pour permettre le trafic Port 80 et 443.

Comment résoudre nginx403 Comment résoudre nginx403 Apr 14, 2025 am 10:33 AM

Comment corriger l'erreur interdite Nginx 403? Vérifier les autorisations de fichier ou de répertoire; 2. Vérifier le fichier .htaccess; 3. Vérifiez le fichier de configuration NGINX; 4. Redémarrer Nginx. D'autres causes possibles incluent les règles de pare-feu, les paramètres de Selinux ou les problèmes d'application.

See all articles