nginx文件上传限速

https://github.com/cfsego/limit_upload_rate 这个模块,通过修改nginx核心源码,可以支持设置文件上传限速

首先下载 nginx-1.2.6 稳定版本
解压后目录结构如下
$ ls 
for-nginx.patch
nginx
   — addon
       — limit_upload_rate
   — src
   — ...
 执行 patch -p0 < for-nginx.patch将补丁替换源代码
./configure --without-http_gzip_module --add-module=./addon/limit_upload_rate-master
make
 配置nginx.conf
                location ~ .*\.php$ {
                        limit_upload_rate 500k;
                        limit_upload_rate_after 1m;
                        fastcgi_index index.php;
                        fastcgi_pass   unix:/usr/local/ciaos/php_fcgi.socket;
                        include /usr/local/ciaos/fastcgi.conf;
                }
测试文件upload.html
<html>
<head>
        <meta http-equiv="content-type" content="text/html;charset=utf-8" />
</head>
<body>
        <form enctype="multipart/form-data" action="up.php" method="POST">
        <!-- Name of input element determines name in $_FILES array -->
                Send file: <input name="Filedata" id="Filedata" type="file" />
                <input name="submit" type="submit" value="Send File" />
        </form>


</body>
</html>
上传处理up.php
<?php


// Define a destination
$targetFolder = '/files'; // Relative to the root


if (!empty($_FILES)) {
        $tempFile = $_FILES['Filedata']['tmp_name'];


        $targetPath = $_SERVER['DOCUMENT_ROOT'] . $targetFolder;
        $targetFile = rtrim($targetPath,'/') . '/' . $_FILES['Filedata']['name'];


        if (file_exists($tempFile)) {
            move_uploaded_file($tempFile,$targetFile);
                //move_uploaded_file($tempFile,$targetFile);
                echo 'Upload succeed';
        } else {
                echo 'Invalid file type.';
        }
}
?>
记得修改files目录的权限为777,最后可以用chrome浏览器测试了,文件上传达到限速效果。

在局域网环境下我发现如果 文件在60s内没有上传完毕,服务器会丢弃此连接,需要配置client_body_timeout为一个更大的值
默认值是60s。(nginx官方手册对这个参数的介绍如下)
“Defines a timeout for reading client request body. A timeout is only set between two successive read operations, not for the transmission of the whole request body. If a client does not transmit anything within this time, the client error 408 (Request Time-out) is returned.”
大概看了一下这个模块对限速的实现,通过对连接的write事件添加定时器,降低服务器的数据处理能力(其实这时客户端已经把全部数据发送给服务端了的),间接影响read事件就会超时。或者做下面的处理,每次延迟write事件的时候重置read事件的超时( 添加下面注释的三行即可
ngx_http_limit_upload_input_body_filter(ngx_http_request_t *r, ngx_buf_t *buf)
{
    off_t                          excess;
    ngx_int_t                      rc;
    ngx_msec_t                     delay;
    ngx_http_limit_upload_ctx_t   *ctx;
    ngx_http_limit_upload_conf_t  *llcf;
    // add line below
    // ngx_http_core_loc_conf_t      *clcf;


    rc = ngx_http_next_input_body_filter(r, buf);
    if (rc != NGX_OK) {
        return rc;
    }


    ctx = ngx_http_get_module_ctx(r, ngx_http_limit_upload_module);


    llcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_upload_module);


    if (ctx->limit_rate == 0) {
        ctx->limit_rate = llcf->limit_rate;
    }


    if (ctx->limit_rate) {
        ctx->received += ngx_buf_size(buf);


        excess = ctx->received - llcf->limit_rate_after
               - ctx->limit_rate * (ngx_time() - r->start_sec + 1);


        ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "limit upload: ctx=%p, received=%O, "
                       "excess=%O, limit_rate=%z, period=%M",
                       ctx, ctx->received, excess, ctx->limit_rate,
                       ngx_time() - r->start_sec + 1);


        if (excess > 0) {
            if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
                return NGX_HTTP_INTERNAL_SERVER_ERROR;
            }


            delay = excess * 1000 / ctx->limit_rate;


            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                           "limit upload: delay=%M", delay);


            ctx->read_event_handler = r->read_event_handler;
            ctx->write_event_handler = r->write_event_handler;
            r->read_event_handler = ngx_http_test_reading;
            r->write_event_handler = ngx_http_limit_req_delay;
            ngx_add_timer(r->connection->write, delay);
            // add two lines below
            // clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
            // ngx_add_timer(r->connection->read, clcf->client_body_timeout);


            return NGX_AGAIN;
        }
    }


    return NGX_OK;
}
此外还有一个文件上传模块可做参考; nginx_upload_module

猜你喜欢

转载自blog.csdn.net/ciaos/article/details/8392703
今日推荐