Nginx篇06——Sendfile指令及其原理

是这样的,想请分析下,Nginx篇06——Sendfile指令及其原理
最新回答
差不多先森丶

2024-09-15 01:29:32

nginx中http模块中的sendfile指令及其原理。

nginx的http模块中有一个 sendfile 指令,默认是开启状态, 官网的文档 对其解释是:

简单来说就是启用sendfile()系统调用来替换read()和write()调用,减少系统上下文切换从而提高性能,当 nginx 是静态文件服务器时,能极大提高nginx的性能表现,而当 nginx 是反向代理服务器时,则没什么用了。下面我们来分析一下这个sendfile的工作原理:

首先我们需要知道sendfile()和read()、write()之间最大的区别就是前者是属于系统调用,而后者是属于函数调用,我们来看下面这幅图

我们不难看出,nginx是属于Applicaiton的,而read()、write()属于函数调用,也就是在Lib Func这一层,sendfile()系统调用,位于System Call这一层,而想要对硬盘进行操作,是kernel才有的权限,上面的那些层都需要往下调用。

作为对比我们先来看一下正常情况下如果nginx调用read()和write()函数的操作过程:

我们都知道数据是存储在硬盘上面的,当数据被调用的时候会被加载进内存再被层层递进最后被CPU使用,这里个这个过程我们进行简化。

这里需要说明两点,一是用户态和内核态之间的切换是需要执行上下文切换操作的,这是十分耗费系统资源和时间的操作,二是因为read()、write()属于函数调用,它们是没有权限在kernel中操作,无法将data直接从Kernel Buffer(Hard Disk)传输到Kernel Buffer(Socket Engine)。

那么使用sendfile()呢?,由于是系统调用,所以在步骤二和步骤三的时候就可以不需要再将数据传输到User Buffer,直接在kernel中进行操作,省去了两次状态切换,也就是省去了两次的上下文切换,从而大幅度提升了性能。

我们来看一下下面的这幅图(灵魂画手上线→_→)

最后我们再来解释一下,为什么当 nginx 是反向代理服务器时, sendfile() 就没什么用了呢。

顾名思义, sendfile() 的作用是发送文件,也就是接收数据的一段是文件句柄,发送数据的那一端是socket。而在做反向代理服务器的时候,两端都是socket,此时无法使用 sendfile() ,也就不存在性能提升这一说了。