项目场景:

这个任务的主要目标是上传大文件,这些文件非常庞大,可以达到几百兆字节。需要确保上传过程的可靠性和稳定性,同时确保上传速度快,并且不会出现任何错误或中断。这个任务可能需要使用高速的互联网连接和专门的上传软件来完成。


问题描述

提示:直接走程序是没有问题的,会提示自定义错误,但是走nginx就直接502了

nginx配置属性client_max_body_size配置1G,但是服务端配置500M上传800M的文件nginx提示502。

springboot配置

spring.servlet.multipart.max-file-size=500MB
spring.servlet.multipart.max-request-size=500MB

502 Bad Gateway

前端页面请求
在这里插入图片描述
potmain请求
在这里插入图片描述
nginx请求的超时时间

        proxy_read_timeout 200s;
        proxy_connect_timeout 200s;
        proxy_send_timeout 200s;

413Request Entity Too Large

在这里插入图片描述

nginx原始配置:

server {
    listen 8090;
    add_header X-Frame-Options "SAMEORIGIN";
#    access_log    "/dev/stdout" json;
    client_max_body_size 1000m;
    access_log    "/opt/bitnami/nginx/logs/access-81.log" json;

    location / {
        root /html/ROOT81;
        index index.html index.htm;
        try_files $uri $uri/ ${uri}.html /index.html;
    }
    location ^~ /es/ {
        alias /html/es81/;
        index index.html index.htm;
        try_files $uri $uri/ /es/index.html;
    }
    location ~* ^/admin|client/ {
        proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;  #Add-zwh
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   Connection        $connection_upgrade;
        proxy_set_header   Upgrade           $http_upgrade;
        proxy_http_version 1.1;
        proxy_read_timeout 200s;
        proxy_connect_timeout 200s;
        proxy_send_timeout 200s;
        proxy_pass http://gateway;
    }


原因分析:

提示:事实证明还是nginx问题,直接用postman请求gateway没有问题

之后在测试本地环境发现,也会出奇的久,或许是不是环境不一致导致我看到的结果不一样。

nginx日志
failed (32: Broken pipe)
failed (104: Connection reset by peer)

-- 输出日志
{"remote_addr":"192.168.0.1","time":"2023-09-20T14:07:34+08:00","remote_user":"-","request_method":"POST","server_protocol":"HTTP/1.1","uri":"/admin/trade-ops/upload/record/upload/one/batch","args":"-","status":"502","body_bytes_sent":"150","upstream_addr":"192.168.0.236:8089","host":"192.168.0.236","gzip_ratio":"-","request_time":"22.242","request_length":"612276694","upstream_response_time":"0.000","upstream_status":"502","http_referer": "-","http_user_agent": "PostmanRuntime/7.33.0"}

-- 错误日志
2023/09/21 10:49:10 [error] 36#36: *7 writev() failed (32: Broken pipe) while sending request to upstream, client: 192.168.0.194, server: , request: "POST /admin/trade-ops/upload/record/upload/one/batch HTTP/1.1", upstream: "http://192.168.0.236:8089/admin/trade-ops/upload/record/upload/one/batch", host: "192.168.0.236:81"
2023/09/21 10:49:42 [error] 36#36: *7 readv() failed (104: Connection reset by peer) while reading upstream, client: 192.168.0.194, server: , request: "POST /admin/trade-ops/upload/record/upload/one/batch HTTP/1.1", upstream: "http://192.168.0.236:8089/admin/trade-ops/upload/record/upload/one/batch", host: "192.168.0.236:81"
2023/09/21 10:50:27 [warn] 1#1: conflicting server name "" on 0.0.0.0:8080, ignored

程序日志:
测试服务器一直打印的SizeLimitExceededException异常

2023-09-20 17:27:48.525 [http-nio-8130-exec-2] [] ERROR com.timelinecapital.ops.common.exception.GlobalExceptionHand - Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException: the request was rejected because its size (612276174) exceeds the configured maximum (524288000)
org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException: the request was rejected because its size (612276174) exceeds the configured maximum (524288000)

突然在本地跑一下看到FileSizeLimitExceededException异常

2023-09-20 17:00:13.527 [http-nio-8088-exec-4] [] ERROR com.timelinecapital.ops.common.exception.GlobalExceptionHand:33 - Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field files exceeds its maximum permitted size of 209715200 bytes.
org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field files exceeds its maximum permitted size of 209715200 bytes.

解决方案:

提示:定位问题还是得多多测试才对,多假设小心定位。方向错了就完了~

在异常盘里面加上e instanceof SizeLimitExceededException || e instanceof FileSizeLimitExceededException 好了短暂的异常解决了

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> sendErrorResponse(Exception e){
        log.error(e.getMessage(), e);
        if(e instanceof HttpMessageNotReadableException
                || e instanceof ServletException){
            return OpsResponse.failure(ExceptionEnum.SYSTEM_BUSY);
        } else if (e instanceof MaxUploadSizeExceededException
                || e instanceof SizeLimitExceededException
                || e instanceof FileSizeLimitExceededException) {
            return ResponseEntity.ok(ResponseResult.failureMsg(ExceptionEnum.FILE_SIZE_OVER_LIMIT.getMsg()));
        }
        return OpsResponse.failure(ExceptionEnum.SYSTEM_EXCEPTION);
    }

要不是看到突然本地环境多了一个特殊的异常信息FileSizeLimitExceededException仔细分析一下才发现,或许真是程序的问题不是nginx的问题,害我一直在配置nginx。然后不断测试发现还是一个坑对一次不对一次。
在这里插入图片描述
接着我把程序上传的文件配置改成了5M,发现上传文件10M一下子会提示异常,但当我上传900M的时候还是会提示502异常。我猜测应该是缓存问题,因为小文件一下子就触发了,大文件会出现问题,本身大文件会在短时间内占用信道导致传输出现问题,只是猜测。添加了 client_header_buffer_size配置,发现成功次数大大提高。
nginx添加或者修改如下配置

server {
      client_header_buffer_size 1024m;
      client_max_body_size 1000m;
      client_body_timeout 600s;
      client_body_temp_path /tmp;
      client_header_timeout    600s;
     
    location ~* ^/admin|client/ {
        proxy_http_version 1.1;
        proxy_read_timeout 600s;
        proxy_connect_timeout 600s;
        proxy_send_timeout 600s;
        proxy_pass http://gateway;
        #proxy_buffer_size 64k;
        #proxy_buffers   32 32k;
        #proxy_busy_buffers_size 128k;
        #send_timeout 400s;
        #proxy_buffer_size 64K;
        #proxy_buffers 32 32K;
        #proxy_busy_buffers_size 128K;
        proxy_buffer_size 128k;
        proxy_busy_buffers_size 192k;
        proxy_buffers 4 192k;

正确回复的还是蛮高了,可能偶尔来一次网络问题,导致传输失败502其他的还是ok的

{"code":-1,"msg":"文件大小超过限制","data":null,"timestamp":1695284283482}

总结

我一直觉得这是一个nginx的配置问题,413问题倒是正常,因为本身就限制了传输,只是程序和nginx之间会有点出入,导致这个空隙到底谁来处理,这中间是个问题,况且文件还蛮大几百兆,先优化到这里吧,之后再贴个文继续后续优化,优化需要灵感需要时间不是一蹴而就。

引用

https://juejin.cn/post/7111514489182224392
https://blog.csdn.net/guo_qiangqiang/article/details/89675720
https://blog.csdn.net/zzhongcy/article/details/89090193
PS:参与本次活动的博文请务必添加「1024程序员节」标签,并在文章末尾加上小尾巴:

本文参与了「1024 程序员节」活动,欢迎正在阅读的你也加入。
使用 Markdown 编辑的小伙伴可直接复制以下内容到文章末尾:

本文参与了1024 程序员节活动,欢迎正在阅读的你也加入。

查拉图斯特拉说
381 声望210 粉丝

让世界因你而不同