Skip to content

Commit

Permalink
Sticky: $upstream_sticky_status variable.
Browse files Browse the repository at this point in the history
Possible values are:
    empty  - the request to the upstream with no sticky enabled
    "new"  - request without sticky information
    "hit"  - request with sticky information was routed to desired backend
    "miss" - request with sticky information was routed to backend selected
             by balancing algorithm
  • Loading branch information
vlhomutov committed Feb 28, 2023
1 parent ef91e23 commit 99a9d83
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/http/modules/ngx_http_upstream_sticky_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,19 @@ ngx_http_upstream_sticky_select_peer(ngx_http_upstream_rr_peer_data_t *rrp,
ngx_uint_t i, n;

ngx_http_request_t *r;
ngx_http_upstream_state_t *us;
ngx_http_upstream_rr_peer_t *peer;
ngx_http_upstream_rr_peers_t *peers;
ngx_http_upstream_sticky_srv_conf_t *scf;

r = pc->ctx;

hint = &sp->hint;
us = r->upstream->state;

if (hint->len == 0) {
us->sticky_status = NGX_HTTP_UPSTREAM_STICKY_STATUS_NEW;

ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"sticky: no hint provided");
return NGX_OK;
Expand Down Expand Up @@ -200,6 +204,8 @@ ngx_http_upstream_sticky_select_peer(ngx_http_upstream_rr_peer_data_t *rrp,
continue;
}

us->sticky_status = NGX_HTTP_UPSTREAM_STICKY_STATUS_HIT;

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"sticky: found matching peer %ui", i);

Expand Down Expand Up @@ -236,6 +242,8 @@ ngx_http_upstream_sticky_select_peer(ngx_http_upstream_rr_peer_data_t *rrp,
goto again;
}

us->sticky_status = NGX_HTTP_UPSTREAM_STICKY_STATUS_MISS;

ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "sticky: no match");

ngx_http_upstream_rr_peers_unlock(peers);
Expand Down
92 changes: 92 additions & 0 deletions src/http/ngx_http_upstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
#include <ngx_http.h>


#if (NGX_HTTP_UPSTREAM_STICKY)
static ngx_int_t ngx_http_upstream_sticky_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
#endif


#if (NGX_HTTP_CACHE)
static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
ngx_http_upstream_t *u);
Expand Down Expand Up @@ -445,6 +451,14 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = {
ngx_http_upstream_cache_etag, 0,
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },

#endif

#if (NGX_HTTP_UPSTREAM_STICKY)

{ ngx_string("upstream_sticky_status"), NULL,
ngx_http_upstream_sticky_status_variable, 0,
NGX_HTTP_VAR_NOCACHEABLE, 0 },

#endif

{ ngx_string("upstream_http_"), NULL, ngx_http_upstream_header_variable,
Expand Down Expand Up @@ -6103,6 +6117,84 @@ ngx_http_upstream_cache_etag(ngx_http_request_t *r,
#endif


#if (NGX_HTTP_UPSTREAM_STICKY)

static ngx_str_t ngx_http_upstream_sticky_status[4] = {
ngx_string(""),
ngx_string("new"), /* NGX_HTTP_UPSTREAM_STICKY_STATUS_NEW */
ngx_string("hit"), /* NGX_HTTP_UPSTREAM_STICKY_STATUS_HIT */
ngx_string("miss") /* NGX_HTTP_UPSTREAM_STICKY_STATUS_MISS */
};


static ngx_int_t
ngx_http_upstream_sticky_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
u_char *p;
size_t len;
ngx_uint_t i;
ngx_http_upstream_state_t *state;

v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;

if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
v->not_found = 1;
return NGX_OK;
}

len = r->upstream_states->nelts * (sizeof("miss") - 1 + 2);

p = ngx_pnalloc(r->pool, len);
if (p == NULL) {
return NGX_ERROR;
}

v->data = p;

i = 0;
state = r->upstream_states->elts;

for ( ;; ) {
if (state[i].status) {
p = ngx_sprintf(p, "%V",
&ngx_http_upstream_sticky_status[state[i].sticky_status]);

} else {
*p++ = '-';
}

if (++i == r->upstream_states->nelts) {
break;
}

if (state[i].peer) {
*p++ = ',';
*p++ = ' ';

} else {
*p++ = ' ';
*p++ = ':';
*p++ = ' ';

if (++i == r->upstream_states->nelts) {
break;
}

continue;
}
}

v->len = p - v->data;

return NGX_OK;
}

#endif


static char *
ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
Expand Down
8 changes: 8 additions & 0 deletions src/http/ngx_http_upstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@

#define NGX_HTTP_UPSTREAM_INVALID_HEADER 40

/* zero indicates no sticky */
#define NGX_HTTP_UPSTREAM_STICKY_STATUS_NEW 1
#define NGX_HTTP_UPSTREAM_STICKY_STATUS_HIT 2
#define NGX_HTTP_UPSTREAM_STICKY_STATUS_MISS 3


#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT 0x00000002
#define NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES 0x00000004
Expand All @@ -66,6 +71,9 @@ typedef struct {
off_t response_length;
off_t bytes_received;
off_t bytes_sent;
#if (NGX_HTTP_UPSTREAM_STICKY)
ngx_uint_t sticky_status;
#endif

ngx_str_t *peer;
} ngx_http_upstream_state_t;
Expand Down

0 comments on commit 99a9d83

Please sign in to comment.