yanchang
yanchang
发布于 2026-02-01 / 19 阅读
0
0

Nginx HTTPS 避坑指南:解决文件上传失败 (413) 与速度暴跌 (HTTP/2)

碎碎念

技术圈总有一种“喜新厌旧”的倾向,觉得 HTTP/2 一定比 HTTP/1.1 好,HTTPS 一定比 HTTP 高级。

但这次经历狠狠地给我上了一课:没有最好的协议,只有最适合的场景。 对于高并发的小文件请求(比如加载网页图片、CSS),HTTP/2 是神;但对于简单粗暴的大文件管道传输(比如网盘上传),老旧的 HTTP/1.1 反而因为没有复杂的流控机制,跑得更快更欢。

现实世界里倒是迎来了好消息:网站备案初审今天顺利通过了! 目前已经正式进入 ICP 工信部审查阶段。看着进度条往前走,感觉离“正规军”的身份越来越近了。

现在的 8090 端口通了,HTTPS 也没问题了。下一步计划等 ICP 号下来,立马去攻克 公安部备案。虽然折腾,但看着这个“数字家园”从黑户变成双证齐全的合法公民,这种养成系的快乐确实无可替代。

周末愉快,继续折腾!

前言

刚刚搞定了浏览器 HSTS 强制跳转的“幽灵”问题,原本以为我的 HomeLab 终于可以完美运行在 HTTPS 的保护伞下了。

然而,现实总是喜欢在你不经意的时候给你一记重锤。当我兴冲冲地打开 OpenList 网盘,准备上传一部刚才下载的 4K 电影(测试内网速度)时,两个意想不到的问题接踵而至:

  1. 文件传不上去:大文件直接报错,小文件却正常。

  2. 速度慢到令人发指:原本 HTTP 下能跑满 10MB/s 的内网带宽,换了 HTTPS 后竟然跌到了 1.5MB/s。

这就好比给法拉利换了一把防盗锁,结果车门打不开,好不容易打开了,最高时速被锁死在 20 码。


正文内容

第一关:解决“上传失败” (413 Error)

现象: 上传几 KB 的文本文件一切正常,但只要上传超过 1MB 的图片或压缩包,进度条还没开始跑就直接报红,浏览器控制台显示 413 Request Entity Too Large

原因: 这是一个 Nginx 的经典“新手坑”。Nginx 默认的 client_max_body_size(允许客户端请求的最大体积)只有 1M。这是为了防止恶意攻击占满服务器带宽,但对于网盘或博客应用来说,这个限制简直是灾难。

解决方案: 在 Nginx 配置文件中(serverlocation 块),手动解除这个封印。

Nginx

# 设置为 0 表示不限制大小,或者按需设置为 100m, 10g 等
client_max_body_size 0;

第二关:解决“速度暴跌” (HTTP/2 的锅)

现象: 解决了 413 错误后,文件能传了,但速度极其感人。

  • HTTP 协议下:上传速度稳定在 10MB/s(跑满百兆上行)。

  • HTTPS 协议下:上传速度断崖式下跌,只有 1.5MB/s 左右。

排查过程: 起初我怀疑是 SSL 加密消耗了太多性能,或者硬盘写入跟不上。于是我一边上传一边在服务器运行 top 命令监控:

  • CPU:Nginx 占用仅 1.7%,空闲率 98% -> 排除算力瓶颈

  • IO:wa (IO Wait) 仅 0.3% -> 排除硬盘瓶颈

既没算加密,也没写硬盘,那 Nginx 在干嘛?它在“等”。

真凶:HTTP/2 的流控机制 为了追求现代化,我在配置 HTTPS 时顺手(实际上是抄别人作业的时候)开启了 http2。 虽然 HTTP/2 对网页加载(多路复用)有奇效,但它在处理大文件上传(单一长连接大数据流)时,由于复杂的窗口更新(Window Update)机制,客户端和服务器需要频繁交互确认“还能发多少”,导致大量时间浪费在握手上,而不是传输数据。

解决方案: 返璞归真,去掉 http2,回退到更简单粗暴但适合持续传输的 HTTP/1.1。

修改 Nginx 配置文件:

Nginx

# 修改前:listen 5244 ssl http2;
# 修改后:去掉 http2
listen 5244 ssl;

重载配置后,奇迹发生了:上传速度瞬间回到了 9-10MB/s 的满速状态!

终极配置

结合以上两个坑,以及针对家庭宽带 MTU 的分片优化,总结出了一套适合 HomeLab(Halo/AList/OpenList)的 Nginx 最佳配置:

Nginx

server {
    # 1. 【速度核心优化】去掉 http2
    # 这一步是解决上传速度慢(从 1.5MB/s -> 10MB/s)的关键
    listen 8091 ssl; 
    server_name www.yanchang.cc;

    ssl_certificate     /etc/nginx/ssl/www.yanchang.pem;
    ssl_certificate_key /etc/nginx/ssl/www.yanchang.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    # 2. 【网络层优化】减小 SSL 缓冲区
    # 适配家庭宽带 MTU,减少丢包和卡顿
    ssl_buffer_size 4k;

    # 3. 【解除封印】解除上传大小限制
    # 虽然你写了 1000m,但 0 (不限制) 是更通用的写法
    client_max_body_size 0;

    location / {
        proxy_pass http://127.0.0.1:8090;   # Halo 的端口
        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;

        # 4. 【IO 性能优化】关闭缓冲
        # Halo 上传附件、主题包时,直接转发,不写临时文件,速度更快
        proxy_request_buffering off;
        proxy_buffering off;

        # 5. 【连接稳定性】增加超时时间
        # 防止上传大主题包或备份文件时超时
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
        proxy_read_timeout 300;
        send_timeout 300;

        # ========================================================
        # 6. 【HSTS 修复】这两行绝对不能删!
        # 这是为了防止浏览器强制把你的 8090 端口跳转到 HTTPS
        # ========================================================
        proxy_hide_header Strict-Transport-Security;
        add_header Strict-Transport-Security "max-age=0" always;
    }
}

PhotoPrism 相册服务报错刷屏主力是: WebSocket connection to 'wss://yanchang.cc:2343/api/v1/ws' failed

1. 报错原因分析

  • 现象:你的浏览器试图建立 WebSocket 连接(wss://),用于实时通信(比如 Halo 的控制台日志、PhotoPrism 的索引进度等),但连接建立失败,一直在无限重连。

  • 原因:Nginx 默认只转发标准的 HTTP 请求。当浏览器发起 "Upgrade" 请求试图把 HTTP 升级为 WebSocket 协议时,如果 Nginx 没有显式配置转发 Upgrade 头,它就会把这个请求拦截下来,导致连接失败。

  • 其他报错(如 maps.photoprism.apptranslate.google.com):这些是网络问题。PhotoPrism 试图加载地图,Halo/浏览器试图加载谷歌翻译,但因为众所周知的网络原因(服务器在国内无法连接谷歌/外部地图源),导致连接超时。这部分通常不影响核心功能,可以忽略。

解决方案

我们需要修改 2343 端口 的 Nginx 配置文件,在 location / 块中显式开启 WebSocket 支持。

请使用以下修复版配置(在之前的终极版基础上,加入了 WebSocket 专用配置):

server {
    # 1. 【端口与协议】
    # 使用 2343 端口 (SSL),强制 HTTP/1.1 以确保大文件传输速度
    listen 2343 ssl;
    server_name www.yanchang.cc;

    # 2. 【证书配置】
    ssl_certificate     /etc/nginx/ssl/www.yanchang.pem;
    ssl_certificate_key /etc/nginx/ssl/www.yanchang.key;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    # 3. 【网络分片优化】适配家庭宽带 MTU
    ssl_buffer_size 4k;

    # 4. 【解除限制】允许上传超大视频/照片
    client_max_body_size 0;

    location / {
        # 指向 PhotoPrism 内部端口 (通常是 2342)
        proxy_pass http://127.0.0.1:2342;

        # 标准头部
        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;

        # =======================================================
        # 5. 【关键修复】WebSocket 支持
        # PhotoPrism 的索引进度条、通知都需要这个,否则会一直报错
        # =======================================================
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 6. 【IO 性能优化】关闭缓冲
        # 照片视频直接直通后端,不写 Nginx 临时文件
        proxy_request_buffering off;
        proxy_buffering off;

        # 7. 【长连接超时】大幅延长
        # PhotoPrism 处理 AI 识别和转码非常慢,给足 1 小时超时时间
        proxy_connect_timeout 3600s;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        send_timeout 3600s;
    }
}


评论