Nginx功能篇21—代理缓冲

概述

本章,您将学习到 Nginx 的代理缓冲功能。

代理缓冲:缓冲指的是在写入数据时,先把分散的数据写入操作保存到内存当中,达到一定程度后再集中写入到硬盘,减少磁盘碎片和硬盘的反复寻道,加速数据的写入过程。而在 Nginx 中,代理缓冲指的是将来自后端服务器的响应数据临时存储在内存或磁盘中,然后再逐步发送给客户端,这种 "先暂存,后逐步发送" 的机制主要是为了解耦上下游的读写速度(后端服务器的响应速度远快于客户端从网络接收数据的速度)。若没有代理缓冲,后端服务器会被慢速客户端 "拖慢",TCP 连接被长时间占用,对应系统资源容易出现被耗尽的问题。

代理缓存 指的是当 Nginx 作为 反向代理 时,将后端服务器返回的频繁请求内容存储在 Nginx 本地的内存或磁盘中,以便在后续请求相同内容时快速响应,而无需再次从后端服务器获取,减少对后端服务器的请求次数,提升性能与用户体验。

从概念上可知代理缓存与代理缓冲的区别:

特性 代理缓存 代理缓冲
触发时机 客户端请求到达 Nginx 时,Nginx 会查找是否存在对应缓存条目 后端返回响应后,Nginx转发给客户端的过程中生效
资源占用 占用特定的内存块与存储区域 当前请求所占用的对应临时内存或磁盘空间
核心目的 存储重复响应,降低后端服务器的总请求量 解耦上下游的读写速度
配置启用要求 必须在配置文件中显式配置 Nginx 中默认开启
适用场景 读多写少或内容不频繁变化的静态资源 大文件下载,后端服务器性能有限而客户端请求量大

相关指令

核心开关控制指令:

  • proxy_buffering 指令 - 代理缓冲总开关,默认为 proxy_buffering on;,可配置在 http 、server、location 上下文中
  • proxy_request_buffering 指令 - 是否缓冲客户端发送的请求体(Request Body),默认为 proxy_request_buffering on;,可配置在 http 、server、location 上下文中。开启之后,Nginx 代理服务器会在接收完整个客户端请求体后再一次性转发给后端服务器

响应头与响应体缓冲指令(需要 proxy_buffering on; 才生效):

  • proxy_buffer_size 指令 - 设置响应头缓冲区大小,该缓冲区专门用于存储后端返回的 HTTP 响应头,默认为 proxy_buffer_size 4k (或者 proxy_buffer_size 8k,取决于内存页大小),可配置在 http 、server、location 上下文中
  • proxy_buffers 指令 - 设置响应体内存缓冲区的数量与大小,默认为 proxy_buffers 8 4k;(或 proxy_buffers 8 8k;,取决于内存页大小),即 Nginx 默认会分配 8 个响应体缓冲区,每个缓冲区的大小为 4KB 或 8KB
  • proxy_busy_buffers_size 指令 - 设置 "忙碌" 缓冲区的总大小。所谓 "忙碌" 缓冲区,指的是一种状态。当 Nginx 从后端服务器接收数据并暂存在 proxy_buffers 中时,这些缓冲区处于 "空闲" 或 "待发送" 状态。一旦 Nginx 开始向客户端发送数据,那些‌已经接收但尚未完全发送给客户端‌的缓冲区就被标记为 "忙碌"(Busy)。通常而言,指令参数建议设置为 proxy_buffers 总大小的 1/4 或 1/2,但是需要注意不能超过 proxy_buffer_size + proxy_buffers 总大小这个明确限制

磁盘临时文件指令(当响应体大小超过了 proxy_buffers 定义的内存总量时,Nginx 会将一部分响应数据写入到磁盘临时文件中):

  • proxy_max_temp_file_size 指令 - 设置临时文件的上限大小
  • proxy_temp_file_write_size 指令 - 每次写入到临时文件的数据大小
  • proxy_temp_path 指令 - 设置临时文件的存放目录。需要注意 Nginx worker 进程用户(我的环境中是 nginx 用户)对设置的目录有读写权限

使用场景示例

典型场景:大文件下载

# 创建特定的目录
Shell > mkdir -p /var/buffer/nginx/temp

# 变更所有者所属组以及目录权限
Shell > chown nginx:nginx /var/buffer/nginx/temp && chmod 755 /var/buffer/nginx/temp

示例配置:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器(未指定任何负载策略,默认使用轮询)
    upstream backend1 {
        server 192.168.100.30;
        server 192.168.100.35;
        server 192.168.100.40;
    }
    ...
    # 代理缓存核心配置
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:50m inactive=1h max_size=1g use_temp_path=off;
    ...
    server {
        listen 192.168.100.20:80;
        server_name my-tests.com www.my-tests.com;
        # 重定向跳转
        return 301 https://www.my-tests.com$request_uri;
    }

    server {
        listen 192.168.100.20:443 ssl http2 backlog=8000 reuseport;
        server_name www.my-tests.com;

        # SSL/TLS 证书相关的配置
        ssl_certificate /usr/local/nginx/ssl/fullchain.pem;
        ssl_certificate_key /usr/local/nginx/ssl/my_privkey.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 15m;
        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8 8.8.4.4 valid=300s;
        resolver_timeout 5s;

        # 在代理层统一设置压缩响应
        gzip on;
        gzip_vary on;
        gzip_buffers 32 4K;
        gzip_comp_level 5;
        gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/xhtml+xml image/svg+xml application/x-font-ttf application/x-font-opentype application/vnd.ms-fontobject font/woff;
        gzip_min_length 256;

        # 在请求转发给后端服务器之前对 HTTP 请求头进行统一设置
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Accept-Encoding "";  # 禁止后端压缩

        # 连接优化相关统一设置
        proxy_connect_timeout 20s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        proxy_next_upstream error timeout http_502 http_504;

        # 安全风险控制统一设置
        proxy_hide_header X-Powered-By;
        proxy_hide_header Server;

        location / {
            ...
            # 下面是前面文档代理缓存中的内容(以 proxy_cache 开头的指令),应该很熟悉了
            proxy_cache my_cache;
            proxy_cache_key "$scheme$host$request_uri";

            proxy_cache_valid 200 302 10m;
            proxy_cache_valid 404 1m;
            proxy_cache_valid 500 502 503 504 10s;

            proxy_cache_lock on;
            proxy_cache_lock_timeout 5s;
            proxy_cache_background_update on;
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;

            # 添加自定义的调试响应头
            add_header X-Cache-Status $upstream_cache_status always;

            # 指向一组服务器
            proxy_pass http://backend1;
        }

        ## 注意这里的 URL 是末尾不带斜杠的普通前缀匹配
        location /download {
            proxy_pass http://backend1;

            # 代理缓冲相关指令
            proxy_buffering on;
            proxy_request_buffering on;
            proxy_buffer_size 4k;
            proxy_buffers 16 8k;
            proxy_busy_buffers_size 32k;
            proxy_max_temp_file_size 1024m;
            proxy_temp_file_write_size 8k;
            proxy_temp_path /var/buffer/nginx/temp;
        }
    }
}

下一篇会介绍 Nginx 作为反向代理的代理服务器时所涉及到的负载策略(负载规则、负载算法)以及对应使用场景。

Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇