本篇内容主要讲解“Nginx线程池模式怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Nginx线程池模式怎么理解”吧!
nginx的IO模型,大家应该都有所了解。简单而言,就是一个master进程和多个worker进程(进程数由配置决定);master进程负责accept请求并队列化,最后转发给worker进程并由其进行请求处理和响应的整个过程。
nginx是以多进程模式运行的。nginx在1.7.11版本提供了多线程特性(multi-threading),不过这个多线程仅用在aio模型中对本地文件的操作上,出发点就是以非阻塞模式,来提高文件IO的效率和并发能力。
所以这个多线程,并不是nginx通过多线程的方式处理proxy request(这部分是通过epoll模式),而是用来处理本地的一些静态文件。
这里涉及到几个基本指令:sendfile、aio和directio,它们均与本地文件的操作有关,接下来我们分别看看它的意义。
sendfile
这个指令与系统函数sendfile()具有相同的语义,sendfile的目的就是提高本地文件通过socket发送的效率。官方的博客介绍了如何利用nginx 线程池aio,实现9倍的性能。
它还有一个比较好记的名称,叫做零拷贝。那与传统的文件读取然后发送到网络上,有什么区别呢?
磁盘、网络驱动器、内存是三种不同的传输介质,如果从本地读取一个文件并通过socket发送出去,通常情况下是进过如下几个步骤:
1)磁盘驱动器从根据CPU的调度,从磁盘读取一定长度(chunk)的字节数据
2)字节数据copy到内核内存中
3)将内核内存中的数据copy到进程工作区内存
4)进程通过socket将数据copy到网络驱动器缓存, 并通过相应的传输协议发送出去。
可以看到,数据的发送过程涉及到多次copy,这受限于计算机系统的设计问题。
sendfile的主要出发点,就是要减少数据的copy以提高发送效率,sendfile是linux系统级的调用,socket可以通过DMA(直接内存访问)方式直接访问文件数据,并通过传输协议发送,减少了2次数据copy(磁盘到内核,内核到工作区)。
sendfile_max_chunk参数用于限定每次sendfile()调用发送的最大数据尺寸,如果不限制大小的话,将会独占整个worker进程,默认为“无限制”。这也太霸道了。
对于nginx而言,代理静态本地的静态文件资源(通常是小文件)将是非常高效的,建议对一些静态文件比如html、图片等,开启此参数。
location /video { sendfile on; sendfile_max_chunk 128k; aio on; }
directio
这个指令用于开启对O_DIRECT标记(BSD,linux)的使用,对应directio()这个系统调用。
此参数是针对大文件而设定的,sendfile针对的是小文件。通过directio可以指定限定的尺寸大小,对于超过此size的文件,将会使用directio(而不再使用sendfile)。
根据directio的设计初衷,它具备sendfile的基本原理,只是不使用内核cache,而是直接使用DMA,而且使用之后内存cache(页对齐部分)也将被释放。
因此directio通常适用于大文件读取,而且通常读取频率很低。因为对于高频的读取,它并不能提高效率(因为它不会重用cache,而是每次都DMA)。由于存在性能权衡问题,此参数默认为off。
location /video { sendfile on; directio 8m; aio on; }
aio
谈到aio模型,其实语义也基本相同,就是异步文件IO,nginx默认关闭此特性,它需要在高版本的linux平台上才支持(2.6.22+)。
在linux上,directio只能读取基于512字节边界对齐的blocks,文件结束的那些未对齐的block将使用阻塞模式读取。
同样,如果文件在开头没有对齐,整个文件都将阻塞式读取。这里所谓的对齐,就是文件数据在内存页中的cache情况。
当aio和sendfile都开启时,将会对那些size大于directio设定值的文件使用aio机制:即当小于directio设定值的文件将直接使用sendfile(aio不参与)。
aio,简单而言,就是使用多线程异步模式读取较大的文件,以提高IO效率,但是事实上可能并没有任何提高。因为大文件的读取,并不能使用cache、而且本身也是耗时的,即使是多线程,对于request的等待时间也是无法预估的,特别是并发请求较高的时候。但是aio能够提高IO的并发能力,这个是确定的。
默认情况下,多线程模式是关闭的,我们需要通过--with-threads配置来开启,此特性尽在支持epoll、kqueue的平台上兼容。对于线程池的设置,我们可以通过thread_pool来声明,并在aio指令中指定。
我们的配置文件近一步丰富了一些。
thread_pool default_pool threads=16;##main上下文 ... location /video { sendfile on; sendfile_max_chunk 128k; directio 8M; aio threads=default_pool; }
当线程池中所有的线程都处于busy状态,那么新的task请求将会加入到等待队列。我们可以在thread_pool中使用max_queue参数来指定队列的大小,默认队列大小为65536,当队列已满后续的请求将会抛出error。
到此,相信大家对“Nginx线程池模式怎么理解”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。