聊聊nginx的keepalive相关参数

本文主要研究一下nginx的keepalive相关参数

keepalive_timeout

复制代码
Syntax:	keepalive_timeout timeout [header_timeout];
Default:	
keepalive_timeout 75s;
Context:	http, server, location

默认是75s,客户端的一个keep-alive连接在服务端保持open的时间,为0表示禁用keep-alive,可选指定header_timeout,若有指定则response header会有Keep-Alive: timeout=time,该header能被Mozilla和Konqueror浏览器识别,MSIE浏览器大概在60s会关闭keep-alive连接

keepalive_requests

复制代码
Syntax:	keepalive_requests number;
Default:	
keepalive_requests 1000;
Context:	http, server, location

keepalive_requests用于指定一个keep-alive连接最大处理的请求数,超过此值则连接被关闭

ngx_http_core_module

nginx/src/http/ngx_http_core_module.c

复制代码
void
ngx_http_update_location_config(ngx_http_request_t *r)
{
    ngx_http_core_loc_conf_t  *clcf;

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (r->method & clcf->limit_except) {
        r->loc_conf = clcf->limit_except_loc_conf;
        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    }

    if (r == r->main) {
        ngx_set_connection_log(r->connection, clcf->error_log);
    }

    if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
        r->connection->sendfile = 1;

    } else {
        r->connection->sendfile = 0;
    }

    if (clcf->client_body_in_file_only) {
        r->request_body_in_file_only = 1;
        r->request_body_in_persistent_file = 1;
        r->request_body_in_clean_file =
            clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN;
        r->request_body_file_log_level = NGX_LOG_NOTICE;

    } else {
        r->request_body_file_log_level = NGX_LOG_WARN;
    }

    r->request_body_in_single_buf = clcf->client_body_in_single_buffer;

    if (r->keepalive) {
        if (clcf->keepalive_timeout == 0) {
            r->keepalive = 0;

        } else if (r->connection->requests >= clcf->keepalive_requests) {
            r->keepalive = 0;

        } else if (ngx_current_msec - r->connection->start_time
                   > clcf->keepalive_time)
        {
            r->keepalive = 0;

        } else if (r->headers_in.msie6
                   && r->method == NGX_HTTP_POST
                   && (clcf->keepalive_disable
                       & NGX_HTTP_KEEPALIVE_DISABLE_MSIE6))
        {
            /*
             * MSIE may wait for some time if an response for
             * a POST request was sent over a keepalive connection
             */
            r->keepalive = 0;

        } else if (r->headers_in.safari
                   && (clcf->keepalive_disable
                       & NGX_HTTP_KEEPALIVE_DISABLE_SAFARI))
        {
            /*
             * Safari may send a POST request to a closed keepalive
             * connection and may stall for some time, see
             *     https://bugs.webkit.org/show_bug.cgi?id=5760
             */
            r->keepalive = 0;
        }
    }

    if (!clcf->tcp_nopush) {
        /* disable TCP_NOPUSH/TCP_CORK use */
        r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
    }

    if (clcf->handler) {
        r->content_handler = clcf->handler;
    }
}

ngx_http_core_module的ngx_http_update_location_config(ngx_http_request_t *r)方法在keepalive为true时,若connection的requests的requests大于等于配置的keepalive_requests,则设置keepalive为0;若ngx_current_msec减去connection的start_time等于keepalive_time则设置keepalive为0

ngx_http_header_filter

nginx/src/http/ngx_http_header_filter_module.c

复制代码
static ngx_int_t
ngx_http_header_filter(ngx_http_request_t *r)
{
    u_char                    *p;
    size_t                     len;
    ngx_str_t                  host, *status_line;
    ngx_buf_t                 *b;
    ngx_uint_t                 status, i, port;
    ngx_chain_t                out;
    ngx_list_part_t           *part;
    ngx_table_elt_t           *header;
    ngx_connection_t          *c;
    ngx_http_core_loc_conf_t  *clcf;
    ngx_http_core_srv_conf_t  *cscf;
    u_char                     addr[NGX_SOCKADDR_STRLEN];

    if (r->header_sent) {
        return NGX_OK;
    }

    r->header_sent = 1;

    if (r != r->main) {
        return NGX_OK;
    }

    //......

    if (r->keepalive && (ngx_terminate || ngx_exiting)) {
        r->keepalive = 0;
    }

    //......

    if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
        len += sizeof("Connection: upgrade" CRLF) - 1;

    } else if (r->keepalive) {
        len += sizeof("Connection: keep-alive" CRLF) - 1;

        /*
         * MSIE and Opera ignore the "Keep-Alive: timeout=<N>" header.
         * MSIE keeps the connection alive for about 60-65 seconds.
         * Opera keeps the connection alive very long.
         * Mozilla keeps the connection alive for N plus about 1-10 seconds.
         * Konqueror keeps the connection alive for about N seconds.
         */

        if (clcf->keepalive_header) {
            len += sizeof("Keep-Alive: timeout=") - 1 + NGX_TIME_T_LEN + 2;
        }

    } else {
        len += sizeof("Connection: close" CRLF) - 1;
    }

    //......    

    if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
        b->last = ngx_cpymem(b->last, "Connection: upgrade" CRLF,
                             sizeof("Connection: upgrade" CRLF) - 1);

    } else if (r->keepalive) {
        b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
                             sizeof("Connection: keep-alive" CRLF) - 1);

        if (clcf->keepalive_header) {
            b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF,
                                  clcf->keepalive_header);
        }

    } else {
        b->last = ngx_cpymem(b->last, "Connection: close" CRLF,
                             sizeof("Connection: close" CRLF) - 1);
    }    
}    

ngx_http_header_filter_module的ngx_http_header_filter方法,在keepalive为1时会添加Connection: keep-alive,若开启keepalive_header,则添加Keep-Alive: timeout=%T";若keepalive为0时,则添加Connection: close到response的header

小结

nginx提供了keepalive_timeout(一个keep-alive连接在服务端保持open的时间)及keepalive_requests(一个keep-alive连接最大处理的请求数)参数,其中ngx_http_core_module的ngx_http_update_location_config(ngx_http_request_t *r)方法在keepalive为true时,若connection的requests的requests大于等于配置的keepalive_requests,则设置keepalive为0;若ngx_current_msec减去connection的start_time等于keepalive_time则设置keepalive为0;而ngx_http_header_filter_module的ngx_http_header_filter方法,在keepalive为1时会添加Connection: keep-alive,若开启keepalive_header,则添加Keep-Alive: timeout=%T";若keepalive为0时,则添加Connection: close到response的header。

doc

相关推荐
舒一笑40 分钟前
程序员效率神器:一文掌握 tmux(服务器开发必备工具)
运维·后端·程序员
NineData3 小时前
数据库管理工具NineData,一年进化成为数万+开发者的首选数据库工具?
运维·数据结构·数据库
梦想很大很大1 天前
拒绝“盲猜式”调优:在 Go Gin 项目中落地 OpenTelemetry 链路追踪
运维·后端·go
Sinclair1 天前
内网服务器离线安装 Nginx+PHP+MySQL 的方法
运维
叶落阁主1 天前
Tailscale 完全指南:从入门到私有 DERP 部署
运维·安全·远程工作
十二7401 天前
前端缓存踩坑实录:从版本号管理到自动化构建
前端·javascript·nginx
可观测性用观测云2 天前
云原生网关 Ingress-Nginx 链路追踪实战:OpenTelemetry 采集与观测云集成方案
nginx·kubernetes
甲鱼9292 天前
MySQL 实战手记:日志管理与主从复制搭建全指南
运维
闲云一鹤4 天前
nginx 快速入门教程 - 写给前端的你
前端·nginx·前端工程化
碳基沙盒4 天前
OpenClaw 多 Agent 配置实战指南
运维