nginx共享内存机制实例分析


这篇文章主要介绍“nginx共享内存机制实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nginx共享内存机制实例分析”文章能帮助大家解决问题。1. 使用示例
nginx声明共享内存的指令为:这里只是声明的一个名称为one,最大可用内存为10g的共享内存。这里面各个参数的含义如下:/users/mike/nginx-cache:这是一个路径参数,指定了将共享内存所缓存的文件的存储位置。这里为什么会生成文件的原因在于,对于上游服务发出的响应,是可以将其生成一个文件存储在nginx上的,后续如果有同样的请求,就可以直接读取该文件或者读取共享内存中的缓存以响应客户端;levels:在linux操作系统中,如果所有文件都放在一个文件夹中,那么当文件数量非常多的时候,可能一个磁盘驱动就无法读取这么多文件了,如果放置在多个文件夹中,那么就能够利用多个驱动并且读取的优点。这里的levels参数指定的就是如何生成文件夹。假设nginx为上游服务的某个响应数据生成的文件名为e0bd86606797639426a92306b1b98ad9,那么对于上面的levels=1:2,其就会从文件名的最后开始取值,先取1位(也即9)作为一级子目录名,然后取2位(也即ad)作为二级子目录名;keys_zone:该参数指定了当前共享内存的名称,这里为one,后面的10m表示当前共享内存用于存储key的内存大小为10m;max_size:该参数指定了当前共享内存可用的最大内存;inactive:该参数指定了当前共享内存的最长存活时间,如果在这段时间内都没有任何请求访问该内存数据,那么其就会被lru算法淘汰掉;use_temp_path:该参数指定了是否先将生成的文件放入临时文件夹,后续再移动到指定文件夹下;2. 工作原理
共享内存的管理工作主要分为如下图所示的几个部分:可以看到,其主要分为初始化、共享内存的管理、共享内存的加载和共享内存的使用等几个方面。在初始化的过程中,首先会解析proxy_cache_path指令,然后分别启动cache manager和cache loader进程;这里cache manager进程主要是进行共享内存的管理的,其主要是通过lru算法清除过期数据,或者当资源紧张时强制删除部分未被引用的内存数据;而cache loader进程的主要工作是在nginx启动之后,读取文件存储目录中已有的文件,将其加载到共享内存中;而共享内存的使用主要是在处理请求完成之后对响应数 香港云主机据的缓存,这一部分的内容将在后面的文章中进行讲解,本文主要讲解前面三部分的工作原理。按照上面的划分,共享内存的管理主要可以分为三个部分(共享内存的使用将在后面进行讲解)。如下是这三个部分的处理流程的示意图:从上面的流程图中可以看出,在主流程中,主要进行了解析proxy_cache_path指令、启动cache manager进程和启动cache loader进程的工作。而在cache manager进程中,主要工作则分为两部分:1. 检查队列尾部元素是否过期,如果过期并且引用数为0,则删除该元素和该元素对应的文件;2. 检查当前共享内存是否资源紧张,如果资源紧张,则删除所有引用数为0的元素及其文件,无论其是否过期。在cache loader进程的处理流程中,主要是通过递归的方式遍历存储文件的目录及其子目录中的文件,然后将这些文件加载到共享内存中。需要注意的是,cache manager进程在每次遍历完所有的共享内存块之后会进入下一次循环,而cache loader进程在nginx启动之后60s的时刻执行一次,然后就会退出该进程。3. 源码解读
3.1 proxy_cache_path指令解析
对于nginx各个指令的解析,其都会在相应的模块中定义一个ngx_command_t结构体,该结构体中有一个set方法指定了解析当前指令所使用的方法。如下是proxy_cache_path所对应的ngx_command_t结构体的定义:可以看到,该指令所使用的解析方法是ngx_http_file_cache_set_slot(),这里我们直接阅读该方法的源码:从上面的代码可以看出,在proxy_cache_path方法中,主要是初始化了一个ngx_http_file_cache_t结构体。而该结构体中的各个属性,则是通过解析proxy_cache_path的各个参数来进行的。3.2 cache manager与cache loader进程启动
nginx程序的入口方法是nginx.c的main()方法,如果开启了master-worker进程模式,那么最后就会进入ngx_master_process_cycle()方法,该方法首先会启动worker进程,以接收客户端的请求;然后会分别启动cache manager和cache loader进程;最后进入一个无限循环中,以处理用户在命令行向nginx发送的指令。如下是cache manager和cache loader进程启动的源码:对于cache manager和cache loader进程的启动,可以看到,其主要是在ngx_start_cache_manager_processes()方法中,如下是该方法的源码:上面的代码其实比较简单,首先检查是否有任何一个路径指定了使用cache manager或者cache loader,如果有,则启动对应的继承,否则是不会创建cache manager和cache loader进程的。而启动这两个进程所使用的方法都是:这里的ngx_spawn_process()方法的作用主要是创建一个新的进程,该进程创建之后就会执行第二个参数所指定的方法,并且执行该方法时传入的参数是这里第三个参数所指定的结构体对象。观察上面两个启动进程的方式,其在新进程创建之后所执行的方法都是ngx_cache_manager_process_cycle(),只不过调用该方法时传入的参数不一样,一个是ngx_cache_manager_ctx,另一个则是ngx_cache_loader_ctx。这里我们首先看一下这两个结构体的定义:可以看到,这两个结构体主要是分别定义了cache manager和cache loader两个进程的不同行为。下面我们来看一下ngx_cache_manager_process_cycle()方法是如何调用这两个方法的:上面的代码中,首先创建了一个事件对象,ev.handler = ctx->handler;指定了该事件所需要处理的逻辑,也即上面两个结构体中的第一个参数所对应的方法;然后将该事件添加到事件队列中,即ngx_add_timer(&ev, ctx->delay);,需要注意的是,这里的第二个参数就是上面两个结构体中所指定的第三个参数,也就是说这里是以事件的延迟时间的方式来控制hander()方法的执行时间的;最后,在一个无限for循环中,通过ngx_process_events_and_timers()方法来不断检查事件队列的事件,并且处理事件。3.3 cache manager进程处理逻辑
对于cache manager处理的流程,通过上面的讲解可以看出,其是在其所定义的cache manager结构体中的ngx_cache_manager_process_handler()方法中进行的。如下是该方法的源码:这里首先会获取所有的路径定义,然后检查其manager()方法是否为空,如果不会空,则调用该方法。这里的manager()方法所指向的实际方法就是在前面3.1节中对proxy_cache_path指令进行解析中进行定义的,也即cache->path->manager = ngx_http_file_cache_manager;,也就是说该方法是管理cache的主要方法。在调用完了管理方法之后,接下来会继续将当前的事件添加到事件队列中,以进行下一次cache管理循环。如下是ngx_http_file_cache_manager()方法的源码:在ngx_http_file_cache_manager()方法中,首先会进入ngx_http_file_cache_expire()方法,该方法的主要作用是检查当前共享内存队列尾部的元素是否过期,如果过期,则根据其引用次数和是否正在被删除而判断是否需要将该元素以及该元素对应的磁盘文件进行删除。在进行这个检查之后,然后会进入一个无限for循环,这里循环的主要目的是检查当前的共享内存是否资源比较紧张,也即是否所使用的内存超过了max_size定义的最大内存,或者是当前所缓存的文件总数超过了总文件数的7/8。如果这两个条件有一个达到了,就会尝试进行强制清除缓存文件,所谓的强制清除就是删除当前共享内存中所有被引用数为0的元素及其对应的磁盘文件。这里我们首先阅读ngx_http_file_cache_expire()方法:可以看到,这里的主要处理逻辑是首先会火嘴队列尾部的元素,根据lru算法,队列尾部的元素是最有可能过期的元素,因而只需要检查该元素即可。然后检查该元素是否过期,如果没有过期,则退出当前方法,否则检查当前元素是否引用数为0,也就是说如果当前元素已经过期,并且引用数为0,则直接删除该元素及其对应的磁盘文件。如果当前元素引用数不为0,则会检查其是否正在被删除,需要注意的是,如果一个元素正在被删除,那么删除进程是会将其引用数置为1的,以防止其他的进程也进行删除操作。如果其正在被删除,则当前进程不会处理该元素,如果没有被删除,则当前进程会尝试将该元素从队列尾部移动到队列头部,这么做的主要原因在于,虽然元素已经过期,但是其引用数不为0,并且没有进程正在删除该元素,那么说明该元素还是一个活跃元素,因而需要将其移动到队列头部。下面我们来看一下,当资源比较紧张时,cache manager是如何强制清除元素的,如下是ngx_http_file_cache_forced_expire()方法的源码:可以看到,这里的处理逻辑比较简单,主要是从队列尾部开始往前依次检查队列中的元素的引用次数是否为0,如果为0,则直接删除,然后检查下一个元素。如果不为0,则检查下一个元素,如此往复。这里需要注意的是,如果检查总共有20次元素正在被引用过程中,则跳出当前循环。3.4 cache loader进程处理逻辑
前面已经讲到,cache loader的主要处理流程在ngx_cache_loader_process_handler()方法中,如下是该方法的主要处理逻辑:这里cache loader与cache manager的处理主流程是非常相似的,主要是通过调用各个路径的loader()方法进行数据加载的,而loader()方法的具体实现方法也是在proxy_cache_path配置项解析的时候定义的,具体的定义如下(在3.1节最后一部分):cache->path->loader = ngx_http_file_cache_loader;
这里我们继续阅读ngx_http_file_cache_loader()方法的源码:在加载过程中,首先将目标加载目录封装到一个ngx_tree_ctx_t结构体中,并且为其指定加载文件所使用的方法。最终的加载逻辑主要是在ngx_walk_tree()方法中进行的,而整个加载过程也是通过递归来实现的。如下是ngx_walk_tree()方法的实现原理:从上面的处理流程可以看出,真正的加载文件的逻辑在ngx_http_file_cache_manage_file()方法中,如下是该方法的源码:这里的加载逻辑整体而言比较简单,主要过程就是将该文件加载到共享内存中,并且会判断加载的文件数量是否超限,如果超限了,则会休眠指定的时长;另外,也会判断加载文件的总耗时是否超过了指定时长,如果超过了,也会休眠指定的时长。关于“nginx共享内存机制实例分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注开发云行业资讯频道,小编每天都会为大家更新不同的知识点。

相关推荐: Windows10中怎么改变鼠标的指针形状

这篇文章给大家分享的是有关Windows10中怎么改变鼠标的指针形状的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体步骤:1.点击桌面右下角的开始菜单标志,随后选择“设置”图标进入。2.在弹出的设置界面中点击“个性化”进入。3.左…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 07/05 21:31
下一篇 07/05 21:31

相关推荐