# HG changeset patch # User Vladimir Homutov # Date 1439198081 -10800 # Node ID 7565e056fad6b4a71c140269bceb271b2da0036f # Parent 5e6142609e486f94f6ed4006f6586bf1a0277b4d Stream: the "tcp_nodelay" directive. diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -132,6 +132,7 @@ typedef struct { u_char *file_name; ngx_int_t line; ngx_log_t *error_log; + ngx_flag_t tcp_nodelay; } ngx_stream_core_srv_conf_t; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -45,6 +45,13 @@ static ngx_command_t ngx_stream_core_co 0, NULL }, + { ngx_string("tcp_nodelay"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay), + NULL }, + ngx_null_command }; @@ -122,6 +129,7 @@ ngx_stream_core_create_srv_conf(ngx_conf cscf->file_name = cf->conf_file->file.name.data; cscf->line = cf->conf_file->line; + cscf->tcp_nodelay = NGX_CONF_UNSET; return cscf; } @@ -148,6 +156,8 @@ ngx_stream_core_merge_srv_conf(ngx_conf_ } } + ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); + return NGX_CONF_OK; } diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c --- a/src/stream/ngx_stream_handler.c +++ b/src/stream/ngx_stream_handler.c @@ -23,6 +23,7 @@ static void ngx_stream_ssl_handshake_han void ngx_stream_init_connection(ngx_connection_t *c) { + int tcp_nodelay; u_char text[NGX_SOCKADDR_STRLEN]; size_t len; ngx_int_t rc; @@ -165,6 +166,24 @@ ngx_stream_init_connection(ngx_connectio } } + if (cscf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_stream_close_connection(c); + return; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + + #if (NGX_STREAM_SSL) { ngx_stream_ssl_conf_t *sslcf; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -478,13 +478,35 @@ ngx_stream_proxy_connect(ngx_stream_sess static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) { + int tcp_nodelay; u_char *p; ngx_connection_t *c, *pc; ngx_log_handler_pt handler; ngx_stream_upstream_t *u; + ngx_stream_core_srv_conf_t *cscf; ngx_stream_proxy_srv_conf_t *pscf; u = s->upstream; + pc = u->peer.connection; + + cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); + + if (cscf->tcp_nodelay && pc->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(pc->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(pc, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_stream_proxy_next_upstream(s); + return; + } + + pc->tcp_nodelay = NGX_TCP_NODELAY_SET; + } if (u->proxy_protocol) { if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { @@ -496,8 +518,6 @@ ngx_stream_proxy_init_upstream(ngx_strea pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); - pc = u->peer.connection; - #if (NGX_STREAM_SSL) if (pscf->ssl && pc->ssl == NULL) { ngx_stream_proxy_ssl_init_connection(s);