Skip to content

Commit

Permalink
HTTP: implementation of the sticky sessions in upstream.
Browse files Browse the repository at this point in the history
The module allows to "stick" client to a particular upstream server.
In the "cookie" mode this is achieved by setting cookie which value
identifies upstream server.

In the "route" mode, upstream server assigns client a route, and the
client carries this information in all further requests.  The server
may use this information to route the client to a particular server
identified by the "sid" parameter.

Example configuration:

upstream u_cookie {
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;

    sticky cookie example domain=example.com max-age=3600;
}

upstream u_route {

    server 127.0.0.1:8081 sid=backend1;
    server 127.0.0.1:8082 sid=backend2;

    sticky route $http_route $cookie_route;

    sticky_strict on;
}
  • Loading branch information
vlhomutov committed Feb 28, 2023
1 parent ae52c06 commit ef91e23
Show file tree
Hide file tree
Showing 11 changed files with 827 additions and 2 deletions.
16 changes: 15 additions & 1 deletion auto/modules
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

# Copyright (C) 2022 Web Server LLC
# Copyright (C) 2022-2023 Web Server LLC
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.

Expand Down Expand Up @@ -944,6 +944,20 @@ if [ $HTTP = YES ]; then
. auto/module
fi

if [ $HTTP_UPSTREAM_STICKY = YES ]; then
have=NGX_HTTP_UPSTREAM_SID . auto/have
have=NGX_HTTP_UPSTREAM_STICKY . auto/have

ngx_module_name=ngx_http_upstream_sticky_module
ngx_module_incs=
ngx_module_deps=
ngx_module_srcs=src/http/modules/ngx_http_upstream_sticky_module.c
ngx_module_libs=
ngx_module_link=$HTTP_UPSTREAM_STICKY

. auto/module
fi

if [ $HTTP_STUB_STATUS = YES ]; then
have=NGX_STAT_STUB . auto/have

Expand Down
6 changes: 5 additions & 1 deletion auto/options
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

# Copyright (C) 2022 Web Server LLC
# Copyright (C) 2022-2023 Web Server LLC
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.

Expand Down Expand Up @@ -108,6 +108,7 @@ HTTP_UPSTREAM_LEAST_CONN=YES
HTTP_UPSTREAM_RANDOM=YES
HTTP_UPSTREAM_KEEPALIVE=YES
HTTP_UPSTREAM_ZONE=YES
HTTP_UPSTREAM_STICKY=YES

# STUB
HTTP_STUB_STATUS=NO
Expand Down Expand Up @@ -294,6 +295,7 @@ $0: warning: the \"--with-ipv6\" option is deprecated"
HTTP_UPSTREAM_RANDOM=NO ;;
--without-http_upstream_keepalive_module) HTTP_UPSTREAM_KEEPALIVE=NO ;;
--without-http_upstream_zone_module) HTTP_UPSTREAM_ZONE=NO ;;
--without-http_upstream_sticky_module) HTTP_UPSTREAM_STICKY=NO ;;

--with-http_perl_module) HTTP_PERL=YES ;;
--with-http_perl_module=dynamic) HTTP_PERL=DYNAMIC ;;
Expand Down Expand Up @@ -518,6 +520,8 @@ cat << END
disable ngx_http_upstream_keepalive_module
--without-http_upstream_zone_module
disable ngx_http_upstream_zone_module
--without-http_upstream_sticky_module
disable ngx_http_upstream_sticky_module

--with-http_perl_module enable ngx_http_perl_module
--with-http_perl_module=dynamic enable dynamic ngx_http_perl_module
Expand Down
13 changes: 13 additions & 0 deletions docs/xml/angie/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@

<changes ver="1.2.0" date="">

<change type="feature">
<para lang="ru">
директива "sticky" и сопутствующие настройки в блоке "upstream" HTTP-модуля,
позволяющие задать режим привязки сессий, при котором все запросы в рамках
сессии будут направляться на один и тот же сервер.
</para>
<para lang="en">
the "sticky" directive and related options in the HTTP module "upstream"
block, that allow to configure sticky sessions mode, where all requests of
the session are routed to the same server.
</para>
</change>

<change type="feature">
<para lang="ru">
возможность сжатия модулем gzip ответов со статусом "207 Multi-Status".
Expand Down
1 change: 1 addition & 0 deletions src/event/ngx_event_connect.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct ngx_peer_connection_s {
struct sockaddr *sockaddr;
socklen_t socklen;
ngx_str_t *name;
ngx_str_t sid;

ngx_uint_t tries;
ngx_msec_t start_time;
Expand Down
22 changes: 22 additions & 0 deletions src/http/modules/ngx_http_upstream_hash_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_rr_peer_t *peer;
ngx_http_upstream_hash_peer_data_t *hp;

#if (NGX_HTTP_UPSTREAM_STICKY)
if (pc->sockaddr) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get hash peer skipped");
return NGX_OK;
}
#endif

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get hash peer, try: %ui", pc->tries);

Expand Down Expand Up @@ -284,6 +292,9 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = peer->sockaddr;
pc->socklen = peer->socklen;
pc->name = &peer->name;
#if (NGX_HTTP_UPSTREAM_SID)
pc->sid = peer->sid;
#endif

peer->conns++;

Expand Down Expand Up @@ -574,6 +585,14 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_hash_srv_conf_t *hcf;
ngx_http_upstream_hash_peer_data_t *hp;

#if (NGX_HTTP_UPSTREAM_STICKY)
if (pc->sockaddr) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get consistent hash peer skipped");
return NGX_OK;
}
#endif

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get consistent hash peer, try: %ui", pc->tries);

Expand Down Expand Up @@ -692,6 +711,9 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = best->sockaddr;
pc->socklen = best->socklen;
pc->name = &best->name;
#if (NGX_HTTP_UPSTREAM_SID)
pc->sid = best->sid;
#endif

best->conns++;

Expand Down
11 changes: 11 additions & 0 deletions src/http/modules/ngx_http_upstream_ip_hash_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_rr_peer_t *peer;
ngx_http_upstream_ip_hash_peer_data_t *iphp;

#if (NGX_HTTP_UPSTREAM_STICKY)
if (pc->sockaddr) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get ip hash peer skipped");
return NGX_OK;
}
#endif

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get ip hash peer, try: %ui", pc->tries);

Expand Down Expand Up @@ -250,6 +258,9 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = peer->sockaddr;
pc->socklen = peer->socklen;
pc->name = &peer->name;
#if (NGX_HTTP_UPSTREAM_SID)
pc->sid = peer->sid;
#endif

peer->conns++;

Expand Down
11 changes: 11 additions & 0 deletions src/http/modules/ngx_http_upstream_least_conn_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_rr_peer_t *peer, *best;
ngx_http_upstream_rr_peers_t *peers;

#if (NGX_HTTP_UPSTREAM_STICKY)
if (pc->sockaddr) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get least conn peer skipped");
return NGX_OK;
}
#endif

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get least conn peer, try: %ui", pc->tries);

Expand Down Expand Up @@ -247,6 +255,9 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = best->sockaddr;
pc->socklen = best->socklen;
pc->name = &best->name;
#if (NGX_HTTP_UPSTREAM_SID)
pc->sid = best->sid;
#endif

best->conns++;

Expand Down
22 changes: 22 additions & 0 deletions src/http/modules/ngx_http_upstream_random_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,14 @@ ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_random_srv_conf_t *rcf;
ngx_http_upstream_random_peer_data_t *rp;

#if (NGX_HTTP_UPSTREAM_STICKY)
if (pc->sockaddr) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get random peer skipped");
return NGX_OK;
}
#endif

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get random peer, try: %ui", pc->tries);

Expand Down Expand Up @@ -309,6 +317,9 @@ ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = peer->sockaddr;
pc->socklen = peer->socklen;
pc->name = &peer->name;
#if (NGX_HTTP_UPSTREAM_SID)
pc->sid = peer->sid;
#endif

peer->conns++;

Expand Down Expand Up @@ -340,6 +351,14 @@ ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_random_srv_conf_t *rcf;
ngx_http_upstream_random_peer_data_t *rp;

#if (NGX_HTTP_UPSTREAM_STICKY)
if (pc->sockaddr) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get random2 peer skipped");
return NGX_OK;
}
#endif

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get random2 peer, try: %ui", pc->tries);

Expand Down Expand Up @@ -439,6 +458,9 @@ ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = peer->sockaddr;
pc->socklen = peer->socklen;
pc->name = &peer->name;
#if (NGX_HTTP_UPSTREAM_SID)
pc->sid = peer->sid;
#endif

peer->conns++;

Expand Down
Loading

0 comments on commit ef91e23

Please sign in to comment.