搞反向代理,其实意义不大,最主要是为了使用SSL证书,顺便隐藏了真实服务器,提高了安全性。另外一点附加便利就是隐藏端口。
直接上传带来的问题
1、耗时久
2、nginx反向代理映射时间超时
3、无法得知上传的速度,并且无法暂停
文件如果是一次性上传,耗时就会比较久,切片带来的好处还有就是你可以得知进度,比如一个文件切5份,发一份过去就是20%。(后续选用Blob.prototype.slice方法)
在文件下载服务场景下,Nginx不仅可以作为前端的反向代理,负责接收来自用户的请求并转发给后端存储系统,还能够通过合理的配置实现对大文件传输过程的有效控制。例如,通过设置proxy_buffering off;可以关闭Nginx的缓冲机制,让客户端能够即时开始接收数据流,避免因等待完整文件加载而导致的延迟。同时,启用chunked_transfer_encoding功能则允许Nginx以分块的方式传输数据,这样既减轻了网络带宽压力,又保证了数据传输的效率与完整性。通过这些精心设计的配置策略,Nginx能够确保即使是面对超大规模的数据传输任务,也能做到游刃有余,为用户提供流畅无阻的服务体验。
二、大文件下载中的带宽占用问题
2.1 Nginx默认文件处理机制分析
Nginx默认文件处理机制分析
当Nginx被配置为文件下载服务的反向代理时,默认情况下,它采用了一种全量缓存的机制来处理文件传输。这意味着每当用户发起一个文件下载请求,Nginx会首先从后端服务器拉取完整的文件内容,并将其暂时存储在本地缓冲区中。只有当整个文件都被成功加载之后,Nginx才会开始向客户端发送数据。这种做法虽然简单易行,但在面对大文件传输时却显得力不从心。一方面,由于需要等待文件完全加载完毕才能开始传输,这无疑增加了用户的等待时间;另一方面,对于网络带宽而言,一次性传输大量数据也会造成瞬时带宽占用激增,尤其是在网络条件不佳的情况下,这种影响尤为明显。因此,如何优化Nginx的文件处理机制,使其能够在不影响用户体验的前提下,更高效地管理带宽资源,成为了亟待解决的问题。
Nginx配置优化策略
3.1 调整缓冲区大小
为了应对大文件下载过程中可能出现的带宽占用问题,调整Nginx的缓冲区大小是一个有效的解决方案。默认情况下,Nginx会根据其内部逻辑自动选择缓冲区的大小,但这种默认值并不总是最适合所有场景,尤其是在处理大文件时。通过手动调整缓冲区大小,可以使Nginx更加智能地管理数据流,减少不必要的等待时间。具体来说,可以通过设置proxy_buffer_size
和proxy_buffers
指令来控制缓冲区的大小及数量。例如,将proxy_buffer_size 16k;
和proxy_buffers 4 32k;
添加到配置文件中,可以显著降低因缓冲区溢出而导致的数据传输延迟。这样做不仅有助于缓解服务器端的压力,同时也能够让客户端更快地接收到数据,从而改善整体的用户体验。
3.2 使用分片传输技术
除了调整缓冲区大小外,启用分片传输技术也是优化大文件下载体验的关键策略之一。Nginx支持chunked_transfer_encoding
特性,该特性允许服务器以分块的方式逐段发送数据,而非一次性传输整个文件。这对于那些需要长时间下载的大文件尤其有用,因为它可以让用户在文件还未完全加载之前就开始接收数据,极大地缩短了等待时间。要在Nginx中激活这一功能,只需简单地在配置文件中加入proxy_http_version 1.1;
和proxy_set_header Transfer-Encoding chunked;
这两行代码即可。这样一来,无论文件有多大,Nginx都能确保数据流的连续性,使得用户能够及时获取所需信息,同时减轻了网络带宽的压力。
3.3 设置延迟读取
在处理大文件下载的过程中,合理设置延迟读取(Lazy Reading)同样重要。通过启用这一功能,Nginx可以在接收到客户端请求后延迟一段时间再开始读取文件内容,这为系统提供了额外的时间来评估请求的有效性,并决定是否需要立即开始传输数据。这样的设计有助于防止因无效或取消的请求而浪费宝贵的带宽资源。实现这一点的方法是在Nginx配置文件中添加open_file_cache
和open_file_cache_valid
指令,以此来控制文件描述符缓存的行为。例如,设置open_file_cache max=500 inactive=12h;
和open_file_cache_valid 30s;
可以帮助Nginx更有效地管理打开的文件句柄,确保只有活跃的连接才会占用系统资源。这样一来,即便是在高并发环境下,Nginx也能保持高效运作,确保每个用户的下载体验都不受影响。
4.1 配置文件结构介绍
在深入探讨具体的配置细节之前,理解Nginx配置文件的基本结构至关重要。Nginx的配置文件通常由一系列嵌套的块构成,每个块都以关键字{
和}
界定。最顶层的块包括events
、http
等,其中http
块包含了所有与HTTP服务器相关的设置。在http
块内,可以定义多个server
块,每个server
块对应一个虚拟主机或监听端口。而在server
块之下,则是具体的配置指令,如listen
、server_name
、location
等。location
块用于指定特定URL路径下的行为,比如针对文件下载服务的优化配置就通常放在这里。通过合理组织这些层级结构,管理员能够精确控制Nginx的行为,确保其高效稳定地运行。
4.2 示例配置文件解析
为了更好地说明如何通过配置文件优化Nginx在文件下载服务中的表现,以下是一个简化版的示例配置:
http {
# 全局设置
...
server {
listen 80;
server_name example.com;
location /downloads/ {
proxy_pass http://backend-server;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Transfer-Encoding chunked;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
open_file_cache max=500 inactive=12h;
open_file_cache_valid 30s;
}
}
}
在这个例子中,我们定义了一个监听80端口的虚拟服务器,其域名设定为example.com
。重点在于location /downloads/
块内的配置,这里指定了所有以/downloads/
开头的URL请求都将被代理到后端服务器http://backend-server
。通过设置proxy_buffering off
,关闭了Nginx的缓冲机制,允许客户端立即开始接收数据流。proxy_http_version 1.1
和proxy_set_header Transfer-Encoding chunked
的组合启用了分块传输编码,使得数据能够分段发送,而不是一次性传输。此外,通过调整proxy_buffer_size
和proxy_buffers
参数,我们优化了缓冲区的大小,减少了因缓冲区溢出引起的延迟。最后,open_file_cache
相关指令的使用有助于提高文件描述符缓存的效率,确保只有活跃的连接才会占用系统资源。
五、优化后的效果评估
5.1 性能指标对比
通过对Nginx配置进行优化,不仅能够显著提升文件下载服务的效率,还能有效降低带宽占用率,从而带来一系列性能上的改进。在实施了上述建议的配置调整后,系统管理员们发现,无论是从服务器端还是客户端的角度来看,都有了明显的改善。首先,从服务器端出发,通过关闭Nginx的缓冲机制(proxy_buffering off
),并启用分块传输(chunked_transfer_encoding
),原本因一次性加载大文件而导致的高延迟问题得到了根本性的解决。数据显示,在优化前后,文件传输的平均延迟时间减少了约30%,这表明即使是在处理超大规模数据时,Nginx也能保持高效运转。此外,通过调整缓冲区大小(proxy_buffer_size
和proxy_buffers
),服务器端的资源利用率也得到了极大提升,减少了因缓冲区溢出造成的不必要的等待时间。更重要的是,启用延迟读取(open_file_cache
)后,系统能够更智能地管理文件描述符缓存,确保只有活跃的连接才会占用系统资源,从而进一步释放了服务器的处理能力。
从客户端的角度观察,用户体验的提升同样显著。优化后的Nginx配置使得用户能够即时开始接收数据流,不再需要等待整个文件加载完毕。根据实际测试结果,用户首次接收到数据的时间平均提前了近40%,极大地缩短了等待时间。此外,分块传输技术的应用也让用户在下载过程中能够持续获得数据,避免了传统方式下可能出现的间歇性停滞现象,使得整个下载过程更加流畅。这些改变不仅提升了用户的满意度,也为服务提供商赢得了更多的信任和支持。
5.2 用户体验改善分析
优化Nginx配置所带来的用户体验改善是全方位的。首先,对于那些经常需要下载大文件的用户来说,最直观的感受就是下载速度的显著提升。由于采用了分块传输技术,用户不再需要等待文件完全加载到Nginx的缓冲区就能开始接收数据,这大大缩短了初始等待时间。据反馈,许多用户表示,现在他们几乎可以立即开始下载,而无需像以前那样等待几分钟甚至更长时间。这种即时响应的感觉让用户感到更加满意,增强了他们对服务的信心。
其次,优化后的配置还解决了过去常见的下载中断问题。在过去,由于Nginx一次性获取并缓存整个文件的行为,一旦网络条件不佳或服务器负载较高,下载过程就容易出现中断。而现在,通过启用延迟读取(open_file_cache
)和调整缓冲区大小(proxy_buffer_size
和proxy_buffers
),系统能够更灵活地管理数据流,确保即使在网络波动时也能保持稳定的传输速率。用户反映,现在的下载过程更加稳定可靠,很少再遇到中途停止的情况,这无疑提升了他们的整体体验。
最后,从长远角度来看,这些改进还有助于培养用户的忠诚度。随着下载速度的加快和服务质量的提升,用户更愿意推荐这项服务给其他人,形成良好的口碑效应。这对于任何依赖于用户满意度和口碑传播的服务来说,都是非常宝贵的优势。总之,通过细致入微的Nginx配置调整,不仅解决了大文件下载中的带宽占用问题,还从根本上改善了用户体验,实现了技术与人文关怀的完美结合。
六、结论与建议
6.1 最佳实践总结
通过上述一系列的优化措施,Nginx在处理大文件下载时展现出了前所未有的高效与稳定。关闭缓冲机制(proxy_buffering off
)、启用分块传输(chunked_transfer_encoding
)、调整缓冲区大小(proxy_buffer_size
和proxy_buffers
)以及设置延迟读取(open_file_cache
)等策略,共同作用下,不仅显著提升了文件传输速度,还将带宽占用率降至最低。数据显示,优化后的系统能够将文件传输的平均延迟时间减少约30%,用户首次接收到数据的时间平均提前了近40%。这些变化不仅极大地改善了用户体验,还提高了服务器端的资源利用率,减少了不必要的等待时间。更重要的是,通过启用延迟读取机制,系统能够更智能地管理文件描述符缓存,确保只有活跃的连接才会占用系统资源,从而进一步释放了服务器的处理能力。这一切的努力,最终都转化为了用户满意度的提升,使得每一次下载都变得更加流畅、快速且可靠。
二、nginx作为反向代理服务器传输数据
场景2:
使用nginx+tomcat
客户端下载文件时候,先到前端nginx,然后nginx找后端tomcat要文件
在下载1G以上文件时候总是无法正确下载
这个问题是由于(客户端/代理服务器)和(代理服务器/后端服务器)传输速度有差异导致的,(代理服务器/后端服务器)通常通过内网传输,代理服务器很快就缓存好了文件,而客户端下载需要一定时间,这两个时间差超过了代理和后端的超时时间。
解决方案:
1.修改nginx代理缓存文件最大值
proxy_max_temp_file_size 4096m;4096m是根据业务规模设置的,若不限制,可将这个值调整为0
(有评论指出:下载大文件proxy_max_temp_file_size应该改小,这样nginx和被代理服务器每次传输少量数据,就不容易超时了。)
2.设置更长的代理超时时间
proxy_send_timeout 120; # 代理发送超时
proxy_read_timeout 120; # 代理接收超时
站点域名绑定
server_name localhost; #多域名用空格隔开
server_name www.test.com www.test2.com; #多域名用空格隔开
指向真实服务器的地址
proxy_pass http://127.0.0.1:8080/;
proxy_set_header:请求头设置相关。
1、设置Host头
作用:指定后端服务器的主机名。确保后端服务器接收到的 Host 头与客户端请求一致,避免因 Host 不匹配导致的 400/404 错误。若未设置,默认传递代理服务器的主机名。
HOST $host:将客户端请求的 Host 头传递给后端服务器。$host 变量代表客户端请求的主机名;传递客户端请求的原始Host
X-Forwarded-Proto $scheme:将客户端使用的协议(HTTP或 HTTPS)传递给后端服务器。$scheme 变量表示请求的协议;传递原始请求协议(HTTP/HTTPS),用于后端生成正确链接。#标识HTTP/HTTPS
X-Real-IP $remote_addr:将客户端的真实IP 地址传递给后端服务器,供后端服务器读取。$remote_addr 变量表示客户端的 IP 地址。
X-Forwarded-For $proxy_add_x_forwarded_for:将客户端的原始 IP 地址和所有代理的 IP 地址传递给后端服务器。($proxy_add_x_forwarded_for 变量包含客户端的 IP 地址以及所有代理服务器的 IP 地址),在原有 X-Forwarded-For 头的基础上追加客户端 IP(支持多级代理);记录代理链 IP 列表,适用于多级代理环境。
Range $http_range、If-Range $http_if_range:Nginx向后端服务器请求的时候是不会把 Range 参数加上的,而是会去请求整个文件,比方说有一个1G的文件,每次请求1M,Nginx会在每次请求的时候去后端请求一个完整的1G文件,然后取出其中的1M发给客户端,这个时候中间的流量会暴增,导致整个服务器宕机。今天因为这个问题导致我检查了很久。解决方案也很简单,把 Range 加到Header里就行了。
Upgrade $http_upgrade:WebSocket 需升级协议头
Connection “upgrade”:触发协议升级
proxy_redirect off:用于修改代理服务器接收到的后端服务器响应中的重定向URL。在代理环境中,若后端返回的重定向URL不符合客户端需求,就用它调整。default:Nginx按proxy_pass设置自动调整重定向 URL。 redirect replacement:redirect是原始重定向URL模式,replacement是替换后的URL。 off:禁用此功能,不修改重定向URL。
proxy_http_version 1.1:默认情况下,Nginx 的 Connection: close 会强制关闭与后端的连接,导致每次请求都需要重新建立 TCP 连接,增加延迟。解决方案:如果后端服务器支持 HTTP/1.1 的持久连接(Keep-Alive),可以通过以下配置启用:proxy_set_header Connection “”;
代理超时设置
proxy_connect_timeout 99999:连接超时时间:用于设置与后端服务器建立连接的超时时间。当Nginx尝试与后端服务器建立连接时,如果在指定的时间内无法建立连接,Nginx将放弃该连接并返回错误信息。设置与后端服务器建立连接的超时时间,默认 60s
proxy_read_timeout 600:设置从后端服务器读取响应的超时时间,默认 60s
proxy_send_timeout 600:设置向后端服务器发送请求的超时时间,默认 60s
下载相关(缓冲proxy端数据):缓存buffer
proxy_buffering off:启用缓冲时,nginx将尽快收到来自代理服务器的响应,并将其保存到代理缓冲器大小和代理缓冲器指令设置的缓冲区中。如果整个响应不适合内存,则可以将其一部分保存到磁盘上的临时档案中。写入临时文件由代理最大值临时文件大小和代理临时文件写_大小指令控制。
NGINX 默认启用代理缓冲(proxy_buffering 指令设置为 on)。代理缓冲意味着 NGINX 将来自服务器的响应存储在内部缓冲区中,并且在整个响应被缓冲之后才开始向客户端发送数据。缓冲有助于优化慢速客户端的性能 —— 因为 NGINX 缓冲响应的时间与客户端检索所有响应的时间一样长,代理服务器可以尽可能快地返回响应,然后返回到可用的状态以响应其他请求。
如果代理缓冲被禁用,则 NGINX 只会在默认为一个内存页大小(4 KB 或 8 KB,具体取决于操作系统)的缓冲区内缓存服务器响应的开头部分后就开始向客户端传输。通常,这个缓存空间只够缓存响应http消息头。NGINX 收到响应后会同步发送给客户端,迫使服务器处于空闲状态,直到 NGINX 可以接受下一个响应段为止。
因此,对于经常在 NGINX 配置中看到 proxy_buffering off 指令的情况,我们感到非常惊讶。也许这样做是为了减少客户端延迟,但其影响可以忽略不计,而关闭后的副作用却很多:代理缓冲被禁用后,速率限制和缓存即便配置了也不起作用,性能也会受影响等等。
只有在少数情况下,禁用代理缓冲可能有意义(例如长轮询),因此我们强烈建议不要更改默认设置。
proxy_request_buffering off:是 NGINX 的一个 反向代理模块指令,用于控制 NGINX 在将客户端请求体转发给后端之前,是否先将其缓存在本地(内存或磁盘)。控制本内容块下(包括子内容块)是否对客户端的请求体启用缓冲,默认为on
。启用的话,nginx
会从客户端读取完整个请求体后再将请求发送到后端服务器去。
on
(默认):NGINX 会在转发请求前,先将整个请求体读完并缓存在本地。off
:NGINX 会 边读取请求体边转发到后端,即 流式转发。
场景 | 是否建议关闭 buffering | 说明 |
大文件上传(如视频、镜像) | ✅ 建议关闭 | 减少 NGINX 内存/磁盘使用 |
实时视频流 / API 流数据接口 | ✅ 建议关闭 | 实现低延迟实时传输 |
普通 Web 表单提交 | ❌ 保持默认开启 | 更安全、控制资源使用 |
防御慢速客户端 | ❌ 保持默认开启 | 防止慢速上传拖垮后端资源 |
proxy_max_temp_file_size 4096m:4096m是根据业务规模设置的,若不限制,可将这个值调整为0;每个请求可以存储临时文件的最大大小。如果上游发来的结果太大以至于无法放入一个缓冲,则Nginx会为其创建临时文件;proxy_temp_file_write_size是一次访问能写入的临时文件的大小,默认是proxy_buffer_size和proxy_buffers中设置的缓冲区大小的2倍,Linux下一般是8k;当proxy_buffering启用时生效,若proxy端响应内容超过proxy_buffer_size和proxy_buffers时,Nginx会把超过的部分写入磁盘上的临时文件中,临时文件默认最大值为1024m,设置此值为0则关闭临时文件缓存功能。当磁盘空间不足时,会断开和proxy端的连接,而client端则会获取响应内容超时。
其他事项
客户端请求配置
client_max_body_size:解决文件上传大小限制,为保安全,正常不应设置太大(Alist说要设置2000M,Hacdias未作要求)
上传相关(缓冲client端数据):
client_body_buffer_size 2M:配置请求体缓存区大小?跟操作系统页面大小有关?如果设置过小,导致上传的文件老要写磁盘,那速度就太慢了;用以缓冲client端请求的body,默认大小为8k|16k(视操作系统而定,32位系统为8k,64位系统为16k,后同),如果请求的body大于此值,则Nginx会将此请求缓存至磁盘。而当磁盘空间不足时,Nginx会断开此链接。
client_header_buffer_size 256k:用以缓冲client端请求的header,默认大小为1k。
larger_client_header_buffers 4 256k:用以缓冲较大的client端请求的header(client_header_buffer_size无法容下的),故此值应大于前者,为节约内存空间,此buffer有个数限制,默认个数为4个,默认大小为8k。建立长连接后此buffer会被释放。
client_body_temp_path:设置临时文件存放路径,只有当上传的请求体超出缓存区大小时,才会写到临时文件中(要有读写权限)
超时设置
client_body_timeout 600s:读取客户端请求体的超时时间,默认 60s
client_header_timeout 600s:读取客户端请求头的超时时间,默认 60s
keepalive_timeout 120s:设置 http 长连接超时时间(即空闲连接可保持打开状态的时长),默认 75s
keepalive_requests 1000:用于设置一个keep-alive连接上可以服务的请求的最大数量。当最大请求数量达到时,连接被关闭。默认是100。
这个参数的真实含义,是指一个keep alive建立之后,nginx就会为这个连接设置一个计数器,记录这个keep alive的长连接上已经接收并处理的客户端请求的数量。如果达到这个参数设置的最大值时,则nginx会强行关闭这个长连接,逼迫客户端不得不重新建立新的长连接。
这个参数往往被大多数人忽略,因为大多数情况下当QPS(每秒请求数)不是很高时,默认值100凑合够用。但是,对于一些QPS比较高(比如超过10000QPS,甚至达到30000,50000甚至更高) 的场景,默认的100就显得太低。
当使用nginx作为反向代理时,为了支持长连接,需要做到两点:
从client到nginx的连接是长连接
从nginx到server的连接是长连接
从HTTP协议的角度看,nginx在这个过程中,对于客户端它扮演着HTTP服务器端的角色。而对于真正的服务器端(在nginx的术语中称为upstream)nginx又扮演着HTTP客户端的角色。
为了在client和nginx之间保持上连接,有两个要求:
- client发送的HTTP请求要求keep alive
- nginx设置上支持keep alive
1.1 HTTP配置
默认情况下,nginx已经自动开启了对client连接的keep alive支持。
一般场景可以直接使用,但是对于一些比较特殊的场景,还是有必要调整个别参数。
http {
keepalive_timeout 120s; #客户端链接超时时间。为0的时候禁用长连接。
keepalive_requests 10000; #在一个长连接上可以服务的最大请求数目。
#当达到最大请求数目且所有已有请求结束后,连接被关闭。
#默认值为100
}
其他性能优化
sendfile on:默认打开
tcp_nopush on:每个数据包达到阈值大小时,一次性发送,优化大文件传输和网络阻塞
#tcp_nodelay on:优化小块数据传输(与上条互斥,不能同时开启)
总结:
Nginx服务器提供的反向代理服务也是比较高效的。它能够同时接收的客户端连接由worker_processes指令和worker_connections指令决定,计算方法为:worker_processes * worker_connections / 4.
配置Nginx服务器反向代理用到的指令如果没有特别说明,原则上可以出现在Nginx配置文件的http块、server块或者location块中,但同正向代理服务的设置一样,一般是在搭建的Nginx服务器中单独配置一个server块来设置反射代理服务。这些指令主要由ngx_http_proxy_module模块进行解析和处理。该模块是Nginx服务器的标准HTTP模块。
Alist建议:
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
proxy_redirect off;
proxy_pass http://127.0.0.1:5244;
# the max size of file to upload
client_max_body_size 20000m;
}
Hacdias建议:
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
# Ensure COPY and MOVE commands work. Change https://example.com to the
# correct address where the WebDAV server will be deployed at.
set $dest $http_destination;
if ($http_destination ~ "^https://example.com(?<path>(.+))") {
set $dest /$path;
}
proxy_set_header Destination $dest;
}
最后总结
先搞proxy参数,哪怕把client max upload给调小试