在谈论它们的共存问题前,我们先来分别理解一下sendfile和gzip。
sendfile
Sendfile" 这个术语通常用于描述在不同的计算机系统或网络环境中发送文件的过程。
用以上图片来讲解一下未使用sendfile的处理流程。用户想要读取welcome.html时,在浏览器输入地址,浏览器将请求发给服务端的nginx。nginx就包含在这个应用程序中。nginx收到请求后,将向操作系统发送read指令,操作系统接收指令后,即从磁盘中读取welcome.html这个静态资源,welcome.html将copy到内核缓冲区,之后将再次将内核缓冲区的welcome.html copy到应用程序缓冲区。为了发送静态资源给浏览器,系统将发送write指令至Socket缓冲区,这时处于应用程序缓冲区的静态资源(welcom.html)将再次copy到Socket缓冲区。底层将通过网卡把welcom.html发送出去,这时又涉及到了一次copy,即从Socket缓冲区到网卡,当网卡得到数据时,通过网络将数据发回给客户端,经过客户端的解析,最终得到内容。所以没有使用sendfile时,涉及到了四次从copy,这时文件的传输效率是非常低的。
当nginx开启sendfile后,磁盘资源就不需要经过应用程序缓冲区,而是将数据copy到内核缓冲区,而在sendfile中,指定了要将数据给哪个Socket,所以系统能直接在内核缓冲区找到对应的Socket缓冲区,以将数据直接交给Socket,Socket再将文件copy给网卡,最终将数据以网络的方式发送回客户端。可以看出,开启senfile后只经过了两个copy,还少了用户态和内核态间的进程切换,此时传输文件的效率是较高的。
gzip
在 Nginx 中,gzip
是一个非常重要的模块,用于启用或配置 HTTP 压缩。通过使用 gzip
,Nginx 可以压缩从服务器发送到客户端(如浏览器)的响应体。这种压缩通常可以显著减少发送的数据量,提高网页加载速度,并减少带宽消耗。
当一个客户端(如浏览器)向服务器请求一个资源时,它会在 HTTP 请求的 Accept-Encoding
头部中指明它支持的压缩格式,如 gzip
。如果 Nginx 配置为启用 gzip
压缩,并且客户端支持,那么 Nginx 会压缩响应体,并在响应头中包含 Content-Encoding: gzip
,表明所发送的数据已被压缩。
共存问题
由于当启动sendfile时,数据的传输不会经过用户态,即到达nginx。这意味着nginx无法对数据进行gzip压缩。此时gzip_static
模块可以解决这一问题。gzip_static
模块提供了一种解决方案。它允许 nginx 发送事先压缩的文件,而不是在每个请求上动态压缩内容。使用 gzip_static
,你可以预先生成压缩版本的文件(通常具有 .gz
扩展名),并将它们存储在服务器上。当请求到来时,如果客户端支持 gzip
,nginx 将直接发送这个预压缩的文件。gzip_static
模块的安装可以使用nginx平滑升级增加模块来完成。