[PATCH] Proxy: tcp fast open in client mode
Jan Prachař
jan.prachar at gmail.com
Thu Oct 5 13:12:42 UTC 2017
What do you think about adding support for tcp fast open in the proxy
module when connecting to upstream?
---
nginx/conf/nginx/nginx.conf | 1 +
nginx/contrib/vim/syntax/nginx.vim | 1 +
nginx/src/core/ngx_connection.h | 1 +
nginx/src/event/ngx_event_connect.c | 9 +++++++++
nginx/src/event/ngx_event_connect.h | 1 +
nginx/src/http/modules/ngx_http_proxy_module.c | 15 +++++++++++++++
nginx/src/http/ngx_http_upstream.h | 1 +
nginx/src/os/unix/ngx_send.c | 12 ++++++++++--
nginx/src/os/unix/ngx_writev_chain.c | 14 ++++++++++++++
9 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/nginx/conf/nginx/nginx.conf b/nginx/conf/nginx/nginx.conf
index e1a090132..6d32dfac5 100644
--- a/nginx/conf/nginx/nginx.conf
+++ b/nginx/conf/nginx/nginx.conf
@@ -107,6 +107,7 @@ http
proxy_max_temp_file_size 0;
proxy_ignore_client_abort on;
proxy_temp_path /var/cache/nginx/tmp;
+ proxy_tcp_fastopen on;
proxy_set_header Host $resource_origin;
proxy_set_header Via $upstream_header_via;
diff --git a/nginx/contrib/vim/syntax/nginx.vim
b/nginx/contrib/vim/syntax/nginx.vim
index e7aadea9c..63e05b3bf 100644
--- a/nginx/contrib/vim/syntax/nginx.vim
+++ b/nginx/contrib/vim/syntax/nginx.vim
@@ -399,6 +399,7 @@ syn keyword ngxDirective contained
proxy_headers_hash_bucket_size
syn keyword ngxDirective contained proxy_headers_hash_max_size
syn keyword ngxDirective contained proxy_hide_header
syn keyword ngxDirective contained proxy_http_version
+syn keyword ngxDirective contained proxy_tcp_fastopen
syn keyword ngxDirective contained proxy_ignore_client_abort
syn keyword ngxDirective contained proxy_ignore_headers
syn keyword ngxDirective contained proxy_intercept_errors
diff --git a/nginx/src/core/ngx_connection.h
b/nginx/src/core/ngx_connection.h
index e4dfe5879..bcfe2f6d8 100644
--- a/nginx/src/core/ngx_connection.h
+++ b/nginx/src/core/ngx_connection.h
@@ -179,6 +179,7 @@ struct ngx_connection_s {
unsigned sndlowat:1;
unsigned tcp_nodelay:2; /*
ngx_connection_tcp_nodelay_e */
unsigned tcp_nopush:2; /*
ngx_connection_tcp_nopush_e */
+ unsigned tcp_fastopen:1;
unsigned need_last_buf:1;
diff --git a/nginx/src/event/ngx_event_connect.c
b/nginx/src/event/ngx_event_connect.c
index c5bb80681..f24804dd9 100644
--- a/nginx/src/event/ngx_event_connect.c
+++ b/nginx/src/event/ngx_event_connect.c
@@ -190,6 +190,15 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pc->log, 0,
"connect to %V, fd:%d #%uA", pc->name, s, c-
>number);
+#if (NGX_LINUX) && defined(MSG_FASTOPEN)
+ if (pc->tcp_fastopen && type == SOCK_STREAM) {
+ rc = 0; /* Do nothing now */
+
+ c->sockaddr = pc->sockaddr;
+ c->socklen = pc->socklen;
+ c->tcp_fastopen = 1;
+ } else
+#endif
rc = connect(s, pc->sockaddr, pc->socklen);
if (rc == -1) {
diff --git a/nginx/src/event/ngx_event_connect.h
b/nginx/src/event/ngx_event_connect.h
index 72d21d7f3..ebc6b78a7 100644
--- a/nginx/src/event/ngx_event_connect.h
+++ b/nginx/src/event/ngx_event_connect.h
@@ -62,6 +62,7 @@ struct ngx_peer_connection_s {
unsigned cached:1;
unsigned transparent:1;
+ unsigned tcp_fastopen:1;
/* ngx_connection_log_error_e */
unsigned log_error:2;
diff --git a/nginx/src/http/modules/ngx_http_proxy_module.c
b/nginx/src/http/modules/ngx_http_proxy_module.c
index d8b5541e1..27c25bdfb 100644
--- a/nginx/src/http/modules/ngx_http_proxy_module.c
+++ b/nginx/src/http/modules/ngx_http_proxy_module.c
@@ -653,6 +653,13 @@ static ngx_command_t ngx_http_proxy_commands[] =
{
offsetof(ngx_http_proxy_loc_conf_t, http_version),
&ngx_http_proxy_http_version },
+ { ngx_string("proxy_tcp_fastopen"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_
FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.tcp_fastopen),
+ NULL },
+
#if (NGX_HTTP_SSL)
{ ngx_string("proxy_ssl_session_reuse"),
@@ -956,6 +963,10 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
r->request_body_no_buffering = 1;
}
+ if (plcf->upstream.tcp_fastopen) {
+ u->peer.tcp_fastopen = 1;
+ }
+
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -3074,6 +3085,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->http_version = NGX_CONF_UNSET_UINT;
+ conf->upstream.tcp_fastopen = NGX_CONF_UNSET;
+
conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT;
@@ -3473,6 +3486,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child)
ngx_conf_merge_uint_value(conf->http_version, prev->http_version,
NGX_HTTP_VERSION_10);
+ ngx_conf_merge_value(conf->upstream.tcp_fastopen, prev-
>upstream.tcp_fastopen, 0);
+
ngx_conf_merge_uint_value(conf->headers_hash_max_size,
prev->headers_hash_max_size, 512);
diff --git a/nginx/src/http/ngx_http_upstream.h
b/nginx/src/http/ngx_http_upstream.h
index 089374f65..b2a360f86 100644
--- a/nginx/src/http/ngx_http_upstream.h
+++ b/nginx/src/http/ngx_http_upstream.h
@@ -184,6 +184,7 @@ typedef struct {
ngx_flag_t intercept_errors;
ngx_flag_t cyclic_temp_file;
ngx_flag_t force_ranges;
+ ngx_flag_t tcp_fastopen;
ngx_path_t *temp_path;
diff --git a/nginx/src/os/unix/ngx_send.c
b/nginx/src/os/unix/ngx_send.c
index 61ea20252..0559cb76d 100644
--- a/nginx/src/os/unix/ngx_send.c
+++ b/nginx/src/os/unix/ngx_send.c
@@ -31,6 +31,14 @@ ngx_unix_send(ngx_connection_t *c, u_char *buf,
size_t size)
#endif
for ( ;; ) {
+#if (NGX_LINUX) && defined(MSG_FASTOPEN)
+ if (c->tcp_fastopen) {
+
+ n = sendto(c->fd, buf, size, MSG_FASTOPEN, c->sockaddr, c-
>socklen);
+ c->tcp_fastopen = 0;
+
+ } else
+#endif
n = send(c->fd, buf, size, 0);
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
@@ -54,13 +62,13 @@ ngx_unix_send(ngx_connection_t *c, u_char *buf,
size_t size)
return n;
}
- if (err == NGX_EAGAIN || err == NGX_EINTR) {
+ if (err == NGX_EAGAIN || err == NGX_EINTR || err ==
NGX_EINPROGRESS) {
wev->ready = 0;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
"send() not ready");
- if (err == NGX_EAGAIN) {
+ if (err == NGX_EAGAIN || err == NGX_EINPROGRESS) {
return NGX_AGAIN;
}
diff --git a/nginx/src/os/unix/ngx_writev_chain.c
b/nginx/src/os/unix/ngx_writev_chain.c
index e38a3aae0..349b07900 100644
--- a/nginx/src/os/unix/ngx_writev_chain.c
+++ b/nginx/src/os/unix/ngx_writev_chain.c
@@ -186,6 +186,19 @@ ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec)
eintr:
+#if (NGX_LINUX) && defined(MSG_FASTOPEN)
+ if (c->tcp_fastopen) {
+ if (vec->count > 0) {
+
+ n = sendto(c->fd, vec->iovs[0].iov_base, vec-
>iovs[0].iov_len,
+ MSG_FASTOPEN, c->sockaddr, c->socklen);
+ c->tcp_fastopen = 0;
+
+ } else {
+ n = 0;
+ }
+ } else
+#endif
n = writev(c->fd, vec->iovs, vec->count);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
@@ -195,6 +208,7 @@ eintr:
err = ngx_errno;
switch (err) {
+ case NGX_EINPROGRESS:
case NGX_EAGAIN:
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
"writev() not ready");
--
2.14.2
More information about the nginx-devel
mailing list