第二章【NGINX 开源功能】—— HTTP 服务器(下)

本节目录

    • HTTPS
    • [HTTP/2 & HTTP/3](#HTTP/2 & HTTP/3)
    • [HTTP 变量](#HTTP 变量)
    • [HTTP 过滤](#HTTP 过滤)
    • [HTTP 压缩](#HTTP 压缩)
    • 附加

HTTPS

HTTPS 是 HTTP 的安全版本,用于在客户端与服务器之间安全地传输数据,它通过在 HTTP 协议之上加入 SSL/TLS 加密层,确保通信的机密性、完整性和身份认证。

HTTPS 核心由三部分组成:

  • HTTP 应用层协议,负责网页内容的传输;
  • SSL/TLS 安全协议层,提供加密、身份验证、完整性校验;
  • 由权威机构(CA)签发的数字证书,证明服务器身份。

HTTPS 的几大优势:

  • 数据加密可以防止敏感信息(如密码、银行卡等)泄露;
  • 数字证书能确保你访问的是正确的网站,而不是骗子网站;
  • SEO 友好,Google 等搜索引擎会优先收录 HTTPS 网站;
  • 现代网页的一些功能,如位置信息、service worker、pwa 等必须 HTTPS。

HTTPS 握手过程如下图所示:

基于 RSA 传统握手流程(现已几乎淘汰)


基于 TLS1.3 首次握手流程(现代主流)


基于 TLS1.3 会话恢复的握手流程

早期的 HTTPS 握手(如 TLS1.x、RSA 等)流程较为繁琐,而现代 TLS(尤其是 TLS1.2 增强模式和 TLS1.3) 对握手过程进行了大幅优化,显著提升了性能与安全性。TLS1.3 作为现代互联网的推荐标准,其在性能(1-RTT)和安全(强制前向安全)上有质的蜕变,强烈推荐使用,TLS1.2 可以用作兜底手段兼容老设备。

需要编译时添加配置 --with-http_ssl_module,需要使用 TLS1.2及以上,系统版本太低的话需要手动指定 openssl --with-openssl=xxxx

综合配置: 针对生产级别的全站 HTTPS 综合配置案例:

nginx 复制代码
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    location ^~ /.well-known/acme-challenge/ {			# 配置证书自动续证,用于 Let's Encrypt 机构
        root /var/www/certbot;
        default_type "text/plain";
        try_files $uri =404;
    }
    location / {										# 所有其他请求强制跳转到 HTTPS
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;		# SSL 公钥证书配置
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;		# SSL 私钥证书配置
    ssl_protocols TLSv1.2 TLSv1.3;				# 启用现代 TLS 协议(禁用不安全的 SSLv3/TLS1.0/TLS1.1)

    # 使用 Mozilla 推荐的现代兼容加密套件,针对 TLS1.3 无用,因为 openssl 会自动选择
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384;

	# 让客户端选择加密套件(TLS1.3 强制,TLS1.2 下推荐 off 以适应不同客户端硬件)
    ssl_prefer_server_ciphers off;

	# 启用 tls 会话缓存,提升响应和性能(对 TLS1.3 几乎无用,TLS1.3 使用的是 session ticket(PSK)机制)
	ssl_session_cache shared:SSL:10m;
	ssl_session_timeout 10m;
	ssl_session_tickets on;
	# 以下三个 key 需要编写自动化脚本定时轮换(nginx 不会自动轮询和重载它们)
	# key.0 是正在用于加密的 key,后面俩是用于解密旧会话的,自动化脚本轮回过程是 new_key -> 0 -> 1 -> 2 -> 剔除
	ssl_session_ticket_key /etc/nginx/ticket_keys/ticket.key.0;		# 设置三个 ticket_key,防止历史会话被破解,有私钥也没用
    ssl_session_ticket_key /etc/nginx/ticket_keys/ticket.key.1;		# 通过 openssl rand 48 > /xxx/ticket.key.0 创建 key
    ssl_session_ticket_key /etc/nginx/ticket_keys/ticket.key.2;

    # 服务器代替浏览器查询证书状态,避免伪造
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 223.6.6.6 8.8.8.8 valid=3600s;
    resolver_timeout 5s;

    # 强制浏览器未来至少 1 年时间都走 HTTPS 请求
    # 警告:不要盲目开启,除非完全确认未来所有子域名都会永久使用 HTTPS
    # 警告:如果未来想把某个子域名切回 HTTP 或者证书出问题了,用户将完全无法访问你的网站,且申请移除列表需要数周甚至数月
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # 增加安全头,防点击劫持、XSS、MIME嗅探、跨站劫持、跨站窗口攻击等
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
	# 针对现代浏览器模型
	add_header X-XSS-Protection "0" always; 
	add_header Cross-Origin-Opener-Policy "same-origin" always;		# same-origin 和 same-site 可能会影响跨站 iframe、第三方资源嵌入,建议仅在主站启用
	add_header Cross-Origin-Resource-Policy "same-site" always;

  	...
}

https://www.ssllabs.com/ssltest 此网站可以测试你的 HTTPS 服务器的评级,A+为最好评级

HTTP/2 & HTTP/3

HTTP/2 和 HTTP/3 是 HTTP 协议的两个重大演进版本,旨在解决 HTTP/1.1 的性能瓶颈,如队头阻塞、高延迟、低效连接。

HTTP/1 有哪些问题???

  • 在同一 TCP 连接上,所有请求必须按顺序处理,一个慢请求会阻塞后续请求;
  • 多连接开销巨大,HTTP/1 是并行下载,浏览器需打开 6~8 个 TCP 连接,增加延迟和服务器负担;
  • HTTP/1 的每个请求都携带 cookie、user-agent 等冗余头部,浪费带宽。

总结就是同条件下用 HTTP/1 网页加载更慢,高延时网络更甚。

HTTP/2 协议

随着网页变得越来越复杂(脚本多、图片大),HTTP/1.1 用起来已经捉襟见肘了,2009 年 Google 实验室为了提高网页加载速度,开发了试验性协议 SPDY,它引入了多路复用、头部压缩等技术,这显著减少了加载时间。于是 SPDY 协议在 chrome 等浏览器中率先获得支持,之后 IETF 的 HTTPbis 工作组也就决定以 SPDY 为基础制定新一代标准,制定了 HTTP/2 标准,并于 2015 年 5 月正式发布 HTTP/2。在 HTTP/2 标准确立后,google 也随即宣布不再维护 SPDY,全面拥抱 HTTP/2。

相比于 HTTP/1.1,HTTP/2 有哪些实质性的改进呢???

  • 采用二进制分帧技术,将信息分割为更小的帧并采用二进制格式编码;
  • 采用多路复用技术,在同一个 TCP 连接里,可以同时发送多个请求和响应,多个请求和响应交错传输,互不阻塞;
  • 采用头部压缩技术,压缩重复的 HTTP Header,减少了 80% 以上的头部体积,极大提高了有效数据的传输量;
  • 采用服务器推送技术,服务端可以预测客户端需要哪些资源并主动推送,减少了客户端请求的往返时间。(此技术因实现复杂、易滥用,主流浏览器已逐步废弃或默认关闭(chrome 和 edge 已移除,firefox 默认关闭,safari 支持有限))

注意:虽然 HTTP/2 标准本身不强制要求加密,但实际上 chrome、firefox 等主流浏览器都明确表示只支持基于 TLS 的 HTTP/2,因此现在的 HTTP/2 基本上是和 HTTPS 绑定使用的。
需要编译时添加配置 --with-http_v2_module

HTTP/2 配置示例:

nginx 复制代码
listen 443 ssl http2;			# 只需要在监听指令上加上 http2 关键字即可

虽然 HTTP/2 已经很流弊了,但还是有部分 HTTP1.1 的问题并没解决:

  • 虽解它对应用层进行了大刀阔斧的改变,但底层还是基于 TCP 协议的,所以若某个数据包丢失,那么整个连接都会暂停等待重传,这也是 TCP 底层机制所决定的;
  • 由于它依然运行在 TCP 之上,所以每次建立连接都意味着要经历漫长的握手等待,即便现在使用了 Fast Open 等优化技术,但也需要 2 ~ 3 个往返时间才能开始传输真正的数据;
  • HTTP/2 虽然允许给不同的资源(如 css 优先于图片)设置优先级权重,但并没有规定服务器必须如何执行,很多服务器端(包括 nginx)和中间件对优先级的实现各不相同,甚至干脆忽略;
  • 原本被寄予厚望的 "服务器主动推送",在实际应用中却并不理想,开发者很难精准判断什么时候该推、推什么。所以目前很多浏览器已经逐步废弃或限制这一功能了。

HTTP/3 协议

如果说上面的 HTTP/2 是对旧协议的 "大修",那么 HTTP/3 就是一场 "推倒重来" 的革命,它最根本的变化是放弃了传输层的 TCP 协议,改用基于 UDP 的 QUIC 协议。其协议的前身是 Google 于 2012 年发布的 gQUIC,但直到 2021 年 QUIC 才完成标准化,2022 年 6 月才正式发布此协议。

截至目前,根据 Cloudflare / Google 的公开数据,HTTP/3 请求占比约 20% 左右,支持站点占比接近 40%(且持续增长中)。

既然说 HTTP/3 是推倒重来的革命性进步,那么进步在哪了??

  • 采用独立流传输,每个 HTTP 流在 QUIC 中是独立的,丢包只影响该流。这在 HTTP/2 中一个丢包整个连接都会卡死;
  • 0-RTT 合并握手,建立连接只需 1 个 RTT,再次连接甚至可以 0-RTT。HTTP/2 中至少两三次才能建立连接;
  • 连接无感迁移,使用 "连接 ID" 而非 IP 识别用户,ip 变更时连接不断,用户无感。HTTP/2 切换网络 ip 时,连接必须断开重连。
  • TLS1.3 直接集成到 QUIC,无需单独握手;
  • QUIC 运行在用户态,无需 TCP 那样为了升级协议还需要先升级内核,所以迭代和安全修复更快。

需要编译时添加配置 --with-http_v3_module

HTTP/3 配置示例:( nginx-1.25.0 开始支持)

nginx 复制代码
# 如果存在特殊需求或者使用的是 nginx-1.25 一下版本,需要使用 --with-http_v3_module 编译 quic 功能
# nginx-1.25 及之后的主线版本,已将此功能合并进主线,开箱即可用
server {
    listen 443 quic reuseport;         			 # udp 监听,用于 HTTP/3,reuseport 允许多个 worker 进程同时监听 udp443,对 quic 性能几乎是必写项
    listen 443 ssl http2;              			 # tcp 监听,兼容 HTTP/2
    http3 on;
    add_header Alt-Svc 'h3=":443"; ma=86400'; 	 # 告诉浏览器优先选择 HTTP/3(可不写,浏览器会自动降级)
}

https://http3check.net 可以检测一个网站是否开启了 HTTP/3 协议。
使用场景:

  • HTTP/3(面向未来的高性能协议):高延迟或不稳定网络、实时应用、边缘 CDN、pwa和移动 web 应用、要求低延时等;(必须依赖 CDN 才能体现出优势,单机自建的 HTTP/3 在公网下的丢包收益很有限)
  • HTTP/2(当前主流,高性价比选择):企业官网、博客电商、saas 应用、应用后端 api、传统 CDN、TLS 加密加性能提升等;
  • HTTP/1.1(兼容性优先的兜底协议):老旧客户端、内部系统/API、调试开发、CDN 回源等(服务器通常会自动保留 HTTP/1.1 作为兜底)。

建站选择:HTTP/3 + HTTP/2 + HTTP/1.1 组合模式(因部分企业网络、校园网和防火墙是直接封了 UDP443 的,所以需要三协议组合使用)

  • HTTP/3 作为先锋,为现代浏览器、移动端、网络波动环境(极速首屏加载)提供服务;
  • HTTP/2 作为中坚力量,为主流的 PC 环境、不支持 UDP 的办公网络提供服务;
  • HTTP1.1 充当兜底手段,为爬虫、老旧 api 调用工具(如 curl 旧版)、IE 等极老浏览器提供兜底服务。

HTTP 变量

  1. ngx_http_map_module 变量映射:根据一个变量的值,动态生成另一个变量;

    nginx 复制代码
    map $source_var $target_var {			# 基本用法
    default         val1;
    case1           val2;
    ~regex          val3;
    }
    
    map $http_user_agent $cache_time {		# 示例,根据 user-agent 设置缓存时间
    default                 5m;
    ~*mobile                1m;
    ~*bot|spider            0s;
    }
    location ~* \.css$ {
        expires $cache_time;
    }
  2. ngx_http_referer_module 防盗链:根据 referer 请求头,限制资源被其他网站盗用(图片、视频、JS/CSS 等);

    nginx 复制代码
    valid_referers [none|blocked|server_names] ...;					# 基本用法
    if ($invalid_referer) { ... }
    
    location ~* \.(jpg|jpeg|png|gif|mp4)$ {							# 示例
        valid_referers none blocked example.com *.example.com;		# 允许空 Referer(直接访问)或来自本站
        if ($invalid_referer) {
            rewrite ^/.*$ /nohotlink.png last;
        }
    }
  3. ngx_http_geo_module ip 段匹配:根据 $remote_addr 匹配 IP 段,设置变量(常用于内网判断);

    nginx 复制代码
    geo $remote_addr $user_group {					# 访问控制,动态分发
        default        A;
        127.0.0.1      B;
        192.168.1.0/24 B;
        10.0.0.0/8     B;
    }
    server {
        if ($user_group = "B") {					# 允许特定用户访问此处
            ...
        }
    }
  4. ngx_http_geoip2_module 地域识别:根据客户端 ip 查询国家、城市、ASN 等信息;

    这是第三方模块,需要自己编译添加进去 --add-module=/path/to/ngx_http_geoip2_module

    nginx 复制代码
    http {
    	...
    	geoip2 /etc/nginx/GeoLite2-Country.mmdb {
    	    $geoip2_data_country_code source=$remote_addr country iso_code;
    	    $geoip2_data_country_name source=$remote_addr country names en;
    	}
    	geoip2 /etc/nginx/GeoLite2-City.mmdb {
    	    $geoip2_data_city source=$remote_addr city names en;
    	}
    	
    	server {
    	    if ($geoip2_data_country_code = "JP") {			# 屏蔽特定国家
    	        return 403;
    	    }
    	    log_format geo '$remote_addr - $geoip2_data_country_code $geoip2_data_city [$time_local] "$request"';	# 记录地域访问日志
    	    access_log /var/log/nginx/access_geo.log geo;
    	}
    }

    应用场景:地域限流或屏蔽、多语言跳转、合规化处理等。(数据库下载处:https://dev.maxmind.com/geoip/geolite2-free-geolocation-data/,需要注册 MaxMind 账号获取 license key 才能下载)

  5. ngx_http_split_clients_module 流量分割:基于 IP 或变量的哈希值,将流量按比例分配到不同后端或配置;

    nginx 复制代码
    split_clients $variable $target_var {				# 基本用法
        10%     "group_a";								# 10% 的流量走 A 组
        20%     "group_b";
        *       "group_c"; 								# 最后 70% 流量走 C 组
    }
    
    split_clients "${remote_addr}" $new_version {					# 示例
        5%      "on";
        *       "off";
    }
    server {
        location / {
            root /var/www/oldVersion;
            if ($new_version = "on") {
                root /var/www/newVersion;  						# 让 5% 的流量走新版本
            }
        }
    }

    应用场景:AB 测试、灰度测试、性能比较等。

  6. headers-more-nginx-module 增强 Header 操作:更灵活地操作请求和响应头;

    这是第三方模块,需要自己编译添加进去 --add-module=/xxx/headers-more

    nginx 复制代码
    location / {
        more_set_headers 'X-Frame-Options: DENY';									# 设置响应头
        more_set_headers -t 'text/html' 'X-Is-Html: True';							# 针对特定类型设置响应头
        more_set_headers -s '403 404' 'X-Error-Notice: Page-Not-Found';				# 根据指定状态码设置响应头
        more_clear_headers 'X-Powered-By';											# 清除响应头
        
        more_set_input_headers "User-Agent: Mozilla/5.0 (Compatible Device)";		# 修改请求头
        more_clear_input_headers "X-Forwarded-For-Secret";							# 清除请求头
    }

    适用场景:安全加固、统一 CORS 处理、后端服务解耦、请求伪装等(模块下载地址:https://github.com/openresty/headers-more-nginx-module

  7. ngx_http_lua_module:嵌入 lua 脚本,完全控制变量生命周期;

    nginx 复制代码
    location / {
        access_by_lua_block {									# 编写 lua 脚本
            local token = ngx.var.http_authorization
            if not validate_jwt(token) then
                ngx.exit(403)
            end
            ngx.var.user_id = extract_user_id(token)
        }
        proxy_set_header X-User-ID $user_id;
    }

    nginx 添加 openresty 毕竟麻烦,推荐直接使用 openresty 服务器:https://openresty.org/cn/,它是基于 nginx + lua 开发的 web 服务器(可连接 mysql、redis 等数据库,可直接在服务器上写业务),在一些场景(广告竞价、秒杀系统等)下性能非常强大。


    如果你非要作为模块使用 nginx,这是模块网址:https://github.com/openresty/lua-nginx-module,这么做其实等于使用上面所说的 openresty 服务器。

HTTP 过滤

nginx 的 过滤模块是其处理 HTTP 响应内容的关键组件,它们工作在上游响应返回后、发送给客户端前的阶段,用于修改、压缩、缓存、记录或丢弃响应体/头部。其与处理器模块(proxy_pass、fastcgi_pass等)不同,过滤模块是链式调用的,每个模块处理完后传递给下一个,最终形成完整响应。

  1. ngx_http_sub_filter_module 响应体文本替换:动态替换响应体中的字符串;

    默认不开启,需手动编译 --with-http_sub_module,或动态编译进入。

    nginx 复制代码
    location / {
        sub_filter_types text/html text/css;				# 默认只支持 text/html,这里扩展为支持 css
        sub_filter 'aaa' 'bbb';		 						# 将 aaa 替换成 bbb
        sub_filter_once off;         						# off 全局替换,on (默认)只替换第一个匹配项
        sub_filter_last_modified on; 						# 更新 Last-Modified 头
    }
    • 该模块不支持正则,该模块只能进行固定的字符串替换。如果需要使用正则表达式,可以选择第三方模块 ngx_http_substitutions_filter_module
    • 该模块会关闭缓冲(proxy_buffering off),影响性能。
  2. ngx_http_image_filter_module 图片动态处理:服务器端动态处理图片,可以缩放、裁剪、旋转、生成缩略图;

    默认不开启,需手动编译 --with-http_image_filter_module,或动态编译进入;

    对于包管理器版本来说,需要 dnf install nginx-extras -y 安装 extras。

    nginx 复制代码
    location /img/ {									# 常见用法
        image_filter resize 300 200;        			# 缩放
        image_filter resize width height;				# 等比例缩放
        image_filter crop 150 150;       				# 裁剪
        image_filter crop width height;					# 强制缩放并裁剪至 exact 尺寸,resize 和 crop 不能同时使用
        image_filter rotate 90;            				# 旋转
        image_filter jpeg_quality 90;       			# jpeg 质量 (1-100)
        image_filter_buffer 10M;          				# 最大处理内存 (默认 1m)
        image_filter_interlace on;          			# 启用渐进式 jpeg
        image_filter size;								# json 格式返回图片尺寸(常用作 api)
    }
    
    location ~ ^/imgs/(\d+)x(\d+)/(.+\.(jpg|jpeg|png))$ {		# 请求 /imgs/300x200/image.jpg,返回 300x200 缩略图
        alias /var/www/images/$3;
        image_filter resize $1 $2;
        image_filter_jpeg_quality 85;
        image_filter_buffer 20M;
        expires 1M;								# 告诉客户端浏览器,此资源缓存一个月(秒s、分m、小时h、天d、周w、月M、年y)
    }

    适用场景:中小型网站、内部系统、对格式要求不高的缩略图服务,更高级的图像(webp、水印等)需要专门的图像处理服务,此内置模块只支持 jpeg、gif、png(部分版本可能支持 webp)。
    注意:

    • 此服务处理 10m 图片可能需要大于 100m 的内存,内存和 CPU 压力会很大;
    • 为了防止被 dos 攻击,建议限制处理大小 if ($1 > 4096) { return 400; }
    • 避免目录被恶意遍历,建议 location 写成 location ~ ^/img/[^/]+\.(jpg|png)$
  3. ngx_http_addition_module 前后缀注入:在响应体开头或结尾插入本地静态内容;

    默认不开启,需手动编译 --with-http_addition_module,或动态编译进入。

    nginx 复制代码
    location / {
        add_before_body /prefix.html;   			# 插入头部
        add_after_body /suffix.html; 				# 插入尾部
        addition_types text/html text/plain;		# 指定哪些 MIME 类型文件可以执行插入(默认是 text/html )
    }

    注意:

    • 该模块默认不包含在 Nginx 中。编译时需要添加参数 --with-http_addition_module
    • 如果主响应或被插入的子请求开启了压缩,该模块将无法工作,需要在对应的 location 中关闭压缩,或者确保后端不返回压缩内容;
  4. ngx_http_ssi_filter_module 服务器端包含 SSI:解析 HTML 中的 指令;

    nginx 复制代码
    location ~* \.shtml$ {
        ssi on;
        ssi_silent_errors on;
        ssi_types text/shtml;
    }

    注意:

    • 这种类型的网页几乎已被现代前端构建工具取代,不推荐在新项目使用。
  5. ngx_http_headers_filter_module 响应头操作:添加、修改响应头(最常用);

    nginx 复制代码
    location ~* \.css$ {
        expires 1M;
        add_header Cache-Control "public, immutable";
        add_header X-Content-Type-Options nosniff;
    }

    注意:

    • add_header 在子块中会覆盖父块!!若需继承,必须在子块中重新声明所有 header 设置;
    • 因为此模块的局限性,推荐使用上述提到的 headers-more-nginx-module 模块。

HTTP 压缩

  1. ngx_http_gzip_module 压缩为 gz:

    nginx 开源版默认不编译此模块,但几乎所有发行版(如 nginx-full、nginx-extras)或自行编译时都会启用;


    触发条件:

    • 客户端请求头包含 Accept-Encoding: gzip;
    • 响应 Content-Type 在 gzip_types 列表中;
    • 响应体长度大于了 gzip 的最小压缩长度。
    nginx 复制代码
    gzip on;                         				 # 启用 gzip
    gzip_vary on;                   				 # 添加 Vary: Accept-Encoding
    gzip_types text/css application/javascript; 	 # 指定压缩的 mime 类型
    gzip_min_length 1024;							# 响应体大于此值才压缩(字节)
    gzip_comp_level 6;          				     # 压缩级别(1-9,越高越慢)
    gzip_proxied any;            				     # 对代理请求也压缩

    注意:

    • 图片、视频、zip 等已压缩格式不要再 gzip。
  2. ngx_http_gunzip_module 解压 gzip:上游返回 gzip 压缩内容后,客户端却不支持 gzip,nginx 将自动解压后再返回;

    默认不开启,需手动编译 --with-http_gunzip_module,或动态编译进入。

    nginx 复制代码
    location {
    	gunzip on;
    	...
    }
  3. ngx_http_gzip_static_module 预压缩 gzip 文件处理:如果存在 .gz 后缀的预压缩文件(如 app.js.gz),且客户端支持 gzip,则直接返回该文件即可;

    默认不开启,需手动编译 --with-http_gzip_static_module,或动态编译进入。

    nginx 复制代码
    gzip_static on;
  4. ngx_brotli 压缩为 br:比 gzip 压缩率高 15%~30%,尤其适合文本(如 HTML/CSS/JS);

    这是第三方模块,需要自己编译添加进去 --add-module=/xxx/ngx_brotli

    nginx 复制代码
    gzip on;
    brotli on;										# gzip 和 brotli 共存,nginx 会根据 Accept-Encoding 字段自动选择最优格式
    brotli_comp_level 6;							# 压缩等级
    brotli_types text/css application/javascript image/svg+xml;
    brotli_static on;  							 	# 支持预压缩的 .br 文件,功能和 gzip_static 相同
  5. ngx_zstd 压缩为 zstd:获得比 gzip 更高的压缩率和更快的解压速度;(实验性)

    这是第三方模块,需要自己编译添加进去 --add-module=/xxx/ngx_zstd

    nginx 复制代码
    zstd on;
    zstd_comp_level 6;
    zstd_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
    zstd_min_length 1024;
    zstd_vary on;

    警告:

    • zstd 压缩的支持现阶段不是很好,Chrome (123+)、Firefox (126+)、Edge 均已获得原生支持,目前唯独 Safari 缺席。

综合配置: 针对生产级别的压缩综合配置案例:压缩策略 zstd > brotli > gzip

nginx 复制代码
http {
	...
	
	zstd on;
	zstd_comp_level 3;
	zstd_types text/plain text/css application/json application/javascript text/xml image/svg+xml;
	
	brotli on;
	brotli_static on; 							# 优先查找磁盘上的 .br 预压缩文件
	brotli_comp_level 5;						# 动态压缩级别不宜过高,5-6 差不多
	brotli_types text/plain text/css application/json application/javascript text/xml image/svg+xml;
	
	gzip on;									# 兜底策略
	gzip_static on;
	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 5;
	gzip_types text/plain text/css application/json application/javascript text/xml image/svg+xml;
	
	...
}

附加

看到了有些小伙伴还不会配置 nginx 跨域,这里是一份用 nginx 解决跨域的配置示例:(不依赖第三方模块,兼容性更好)

nginx 复制代码
location /api/ {
    # 动态判断 origin
    set $cors_origin "";
    if ($http_origin ~* "^http?://(localhost|.*\.example\.com)$") {
        set $cors_origin $http_origin;
    }

    # 使用 add_header (后端返回 4xx/5xx,需要加 always 才能生效)
    add_header Access-Control-Allow-Origin $cors_origin always;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE" always;
    add_header Access-Control-Allow-Credentials "true" always;
    add_header Access-Control-Allow-Headers "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Requested-With" always;

    # 预检请求处理
    if ($request_method = 'OPTIONS') {
        add_header Access-Control-Max-Age 1728000 always;
        add_header Content-Type "text/plain; charset=utf-8" always;
        add_header Content-Length 0 always;
        return 204;
    }

    proxy_pass http://backend;
}

HTTPS 的 session ticket key 的轮换脚本:

bash 复制代码
#!/bin/bash

# Key 存放目录
KEY_DIR="/etc/nginx/ticket_keys"
# Key 文件前缀
KEY_PREFIX="ticket.key"
# OpenSSL 二进制路径
OPENSSL_CMD="openssl"
# Nginx 二进制路径 (用于检查配置)
NGINX_CMD="nginx"
# 系统服务管理命令 (用于重载 Nginx)
SYSTEMCTL_CMD="systemctl"
# 日志文件
LOG_FILE="/var/log/nginx/key_rotation.log"

# 记录日志
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# 检查目录是否存在
if [ ! -d "$KEY_DIR" ]; then
    log "Error: Key directory $KEY_DIR does not exist."
    exit 1
fi

cd "$KEY_DIR" || exit 1

# 开始轮换 (倒序操作,防覆盖),删除 key.2,key.1 -> key.2,key.0 -> key.1,生成新 key.0

# 移动 key.1 到 key.2 (如果 key.1 存在)
if [ -f "${KEY_PREFIX}.1" ]; then
    mv "${KEY_PREFIX}.1" "${KEY_PREFIX}.2"
fi

# 移动 key.0 到 key.1 (如果 key.0 存在)
if [ -f "${KEY_PREFIX}.0" ]; then
    mv "${KEY_PREFIX}.0" "${KEY_PREFIX}.1"
fi

# 生成新的 key.0,使用 openssl 生成 48 字节 (RFC 5077 推荐) 或 80 字节的随机数
$OPENSSL_CMD rand 48 > "${KEY_PREFIX}.0"

if [ $? -ne 0 ]; then
    log "Error: Failed to generate new key using openssl."
    exit 1
fi

# 设置权限,仅 root 可读写,保证私钥安全
chmod 600 "${KEY_PREFIX}".*
log "Keys rotated. New key generated."

# 检查 nginx 配置并重载,在重载前必须检查配置,防止因配置错误导致 nginx 挂掉
$NGINX_CMD -t > /dev/null 2>&1
if [ $? -eq 0 ]; then
    # 配置无误,重载 Nginx
    $SYSTEMCTL_CMD reload nginx
    if [ $? -eq 0 ]; then
        log "Nginx reloaded successfully."
    else
        log "Error: Failed to reload Nginx."
        exit 1
    fi
else
    log "Error: Nginx configuration test failed. Not reloading."
    exit 1
fi

exit 0
相关推荐
Evan芙13 小时前
搭建nexus服务,实现本地仓库、代理仓库
java·nginx·tomcat
秋田君14 小时前
前端工程化部署入门:Windows + Nginx 实现多项目独立托管与跨域解决方案
前端·windows·nginx
小鸡吃米…14 小时前
Python - XML 处理
xml·开发语言·python·开源
Evan芙15 小时前
nginx核心配置总结,并实现nginx多虚拟主机
运维·数据库·nginx
FIT2CLOUD飞致云16 小时前
操作教程丨通过1Panel快速安装Zabbix,搭建企业级监控系统
运维·服务器·开源·zabbix·监控·1panel
代码小学僧17 小时前
从 Arco Table 迁移到 VTable:VTable使用经验分享
前端·react.js·开源
一个没有感情的程序猿18 小时前
前端实现人体骨架检测与姿态对比:基于 MediaPipe 的完整方案
机器学习·计算机视觉·前端框架·开源
邂逅星河浪漫18 小时前
【域名解析+反向代理】配置与实现(步骤)-SwitchHosts-Nginx
linux·nginx·反向代理·域名解析·switchhosts
sg_knight18 小时前
Nuxt 4 生产环境部署指南 (Node.js + Nginx)
运维·nginx·node.js·nuxt·ssr