序本文主要研究一下nginx的keepalive_time參數
keepalive_timeSyntax: keepalive_time time;Default: keepalive_time 1h;Context: http, server, locationThis directive appeared in version 1.19.10.nginx的1.19.10版本新增了keepalive_time參數,用于限制一個keep-alive連接處理請求的最長時間。當達到這個時間后,連接會在后續請求處理完成后關閉。
ngx_http_core_modulenginx/src/http/ngx_http_core_module.c
voidngx_http_update_location_config(ngx_http_request_t *r){ngx_http_core_loc_conf_t *clcf;
//......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; }}//......
}ngx_http_core_module的ngx_http_update_location_config方法在開啟keepalive時會判斷connection的存活時間,若大于keepalive_time則關閉keepalive(ngx_current_msec - r->connection->start_time > clcf->keepalive_time)
ngx_http_core_keepalivenginx/src/http/ngx_http_core_module.c
static char *ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){ngx_http_core_loc_conf_t *clcf = conf;
ngx_str_t *value;if (clcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) { return "is duplicate";}value = cf->args->elts;clcf->keepalive_timeout = ngx_parse_time(&value[1], 0);if (clcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) { return "invalid value";}if (cf->args->nelts == 2) { return NGX_CONF_OK;}clcf->keepalive_header = ngx_parse_time(&value[2], 1);if (clcf->keepalive_header == (time_t) NGX_ERROR) { return "invalid value";}return NGX_CONF_OK;
}ngx_http_core_module的ngx_http_core_keepalive方法會解析nginx配置文件的keepalive_timeout配置,第一個參數為keepalive_timeout參數,第二參數為header_timeout
ngx_http_header_filter_modulenginx/src/http/ngx_http_header_filter_module.c
static ngx_int_tngx_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;}//......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的時候會寫入Connection: keep-alive,若keepalive_header的值大于0則寫入Keep-Alive: timeout=%T,可以看到這個值是固定的
ngx_http_set_keepalivenginx/src/http/ngx_http_request.c
static voidngx_http_set_keepalive(ngx_http_request_t *r){int tcp_nodelay;ngx_buf_t *b, *f;ngx_chain_t *cl, *ln;ngx_event_t *rev, *wev;ngx_connection_t *c;ngx_http_connection_t *hc;ngx_http_core_loc_conf_t *clcf;
//......wev = c->write;wev->handler = ngx_http_empty_handler;if (b->pos < b->last) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); c->log->action = "reading client pipelined request line"; r = ngx_http_create_request(c); if (r == NULL) { ngx_http_close_connection(c); return; } r->pipeline = 1; c->data = r; c->sent = 0; c->destroyed = 0; c->pipeline = 1; if (rev->timer_set) { ngx_del_timer(rev); } rev->handler = ngx_http_process_request_line; ngx_post_event(rev, &ngx_posted_events); return;}//......rev->handler = ngx_http_keepalive_handler;//......c->idle = 1;ngx_reusable_connection(c, 1);ngx_add_timer(rev, clcf->keepalive_timeout);if (rev->ready) { ngx_post_event(rev, &ngx_posted_events);}
}ngx_http_request的ngx_http_set_keepalive方法,在b->pos < b->last會嘗試讀取request line然后執行ngx_http_create_request,若能讀到數據則判斷是否有timer,有則執行ngx_del_timer(rev)刪除timer,然后返回;若進入keepalive邏輯,則會通過ngx_add_timer添加一個定時事件,在keepalive_timeout之后觸發
ngx_http_keepalive_handlernginx/src/http/ngx_http_request.c
static voidngx_http_keepalive_handler(ngx_event_t *rev){size_t size;ssize_t n;ngx_buf_t *b;ngx_connection_t *c;
c = rev->data;ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");if (rev->timedout || c->close) { ngx_http_close_connection(c); return;}
#if (NGX_HAVE_KQUEUE)
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { if (rev->pending_eof) { c->log->handler = NULL; ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, "kevent() reported that client %V closed " "keepalive connection", &c->addr_text);
#if (NGX_HTTP_SSL)if (c->ssl) {c->ssl->no_send_shutdown = 1;}#endifngx_http_close_connection(c);return;}}
#endif
b = c->buffer;size = b->end - b->start;if (b->pos == NULL) { /* * The c->buffer's memory was freed by ngx_http_set_keepalive(). * However, the c->buffer->start and c->buffer->end were not changed * to keep the buffer size. */ b->pos = ngx_palloc(c->pool, size); if (b->pos == NULL) { ngx_http_close_connection(c); return; } b->start = b->pos; b->last = b->pos; b->end = b->pos + size;}/* * MSIE closes a keepalive connection with RST flag * so we ignore ECONNRESET here. */c->log_error = NGX_ERROR_IGNORE_ECONNRESET;ngx_set_socket_errno(0);n = c->recv(c, b->last, size);c->log_error = NGX_ERROR_INFO;if (n == NGX_AGAIN) { if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_close_connection(c); return; } /* * Like ngx_http_set_keepalive() we are trying to not hold * c->buffer's memory for a keepalive connection. */ if (ngx_pfree(c->pool, b->start) == NGX_OK) { /* * the special note that c->buffer's memory was freed */ b->pos = NULL; } return;}if (n == NGX_ERROR) { ngx_http_close_connection(c); return;}c->log->handler = NULL;if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno, "client %V closed keepalive connection", &c->addr_text); ngx_http_close_connection(c); return;}b->last += n;c->log->handler = ngx_http_log_error;c->log->action = "reading client request line";c->idle = 0;ngx_reusable_connection(c, 0);c->data = ngx_http_create_request(c);if (c->data == NULL) { ngx_http_close_connection(c); return;}c->sent = 0;c->destroyed = 0;ngx_del_timer(rev);rev->handler = ngx_http_process_request_line;ngx_http_process_request_line(rev);
}ngx_http_request的ngx_http_keepalive_handler會在rev->timedout || c->close的時候執行ngx_http_close_connection然后返回,若還能讀到請求數據則執行ngx_del_timer(rev)刪除定時任務
nginx的1.19.10版本新增了keepalive_time參數(默認1h),用于限制一個keep-alive連接處理請求的最長時間(即指定connection的最大存活時間),當達到這個時間后,連接會在后續請求處理完成后關閉。而keepalive_timeout參數(默認75s)則是用于指定connection最大的空閑時間,nginx內部有會給該連接設定一個timer,在keepalive_timeout之后觸發,若連接還是空閑則關閉連接。
本文鏈接:http://www.www897cc.com/showinfo-26-38528-0.html聊聊Nginx的Keepalive_time參數,你學會了嗎?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 七個鮮為人知的VS Code快捷鍵