]> git.kaiwu.me - nginx.git/commitdiff
Sticky: added the "header" parameter in the learn mode.
authorVladimir Homutov <vl@nginx.com>
Thu, 8 Jun 2017 12:39:06 +0000 (15:39 +0300)
committerAleksei Bavshin <a.bavshin@f5.com>
Mon, 9 Mar 2026 17:08:30 +0000 (11:08 -0600)
With this parameter set, sessions are learned after receiving upstream headers.

src/http/modules/ngx_http_upstream_keepalive_module.c
src/http/modules/ngx_http_upstream_sticky_module.c
src/http/ngx_http_upstream.c
src/http/ngx_http_upstream.h

index 1a4dfd77665129c2dea4d7fef4544c3bc1d84e75..8858922a0d2b944df1578df4f6a112d6b9907a25 100644 (file)
@@ -52,6 +52,8 @@ typedef struct {
     ngx_event_save_peer_session_pt     original_save_session;
 #endif
 
+    ngx_event_notify_peer_pt           original_notify;
+
 } ngx_http_upstream_keepalive_peer_data_t;
 
 
@@ -73,6 +75,9 @@ static void ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc,
     void *data);
 #endif
 
+static void ngx_http_upstream_notify_keepalive_peer(ngx_peer_connection_t *pc,
+    void *data, ngx_uint_t type);
+
 static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf);
 static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
@@ -228,6 +233,11 @@ ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
     r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session;
 #endif
 
+    if (r->upstream->peer.notify) {
+        kp->original_notify = r->upstream->peer.notify;
+        r->upstream->peer.notify = ngx_http_upstream_notify_keepalive_peer;
+    }
+
     return NGX_OK;
 }
 
@@ -507,6 +517,16 @@ ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, void *data)
 #endif
 
 
+static void
+ngx_http_upstream_notify_keepalive_peer(ngx_peer_connection_t *pc, void *data,
+    ngx_uint_t type)
+{
+    ngx_http_upstream_keepalive_peer_data_t  *kp = data;
+
+    kp->original_notify(pc, kp->data, type);
+}
+
+
 static void *
 ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
 {
index 4c768a250346b87573805816ed48fde9386e1aeb..7780d7106256005587b3a5a6b9a4f90f26c5bff8 100644 (file)
@@ -74,6 +74,7 @@ typedef struct {
     time_t                                      cookie_expires;
     unsigned                                    cookie_httponly:1;
     unsigned                                    cookie_secure:1;
+    unsigned                                    learn_after_headers:1;
 } ngx_http_upstream_sticky_srv_conf_t;
 
 
@@ -93,6 +94,9 @@ typedef struct {
     ngx_event_set_peer_session_pt               original_set_session;
     ngx_event_save_peer_session_pt              original_save_session;
 #endif
+
+    ngx_event_notify_peer_pt                    original_notify;
+
 } ngx_http_upstream_sticky_peer_data_t;
 
 
@@ -109,6 +113,8 @@ static ngx_int_t ngx_http_upstream_sticky_get_peer(ngx_peer_connection_t *pc,
     void *data);
 static void ngx_http_upstream_sticky_free_peer(ngx_peer_connection_t *pc,
     void *data, ngx_uint_t state);
+static void ngx_http_upstream_sticky_learn_peer(
+    ngx_http_upstream_sticky_peer_data_t *stp, ngx_peer_connection_t *pc);
 
 
 #if (NGX_HTTP_SSL)
@@ -119,6 +125,8 @@ static void ngx_http_upstream_sticky_save_session(ngx_peer_connection_t *pc,
 #endif
 
 
+static void ngx_http_upstream_sticky_notify_peer(
+    ngx_peer_connection_t *pc, void *data, ngx_uint_t type);
 static ngx_int_t ngx_http_upstream_sticky_cookie_insert(
     ngx_peer_connection_t *pc, ngx_http_upstream_sticky_peer_data_t *stp);
 
@@ -269,6 +277,11 @@ ngx_http_upstream_sticky_init_peer(ngx_http_request_t *r,
     u->peer.save_session = ngx_http_upstream_sticky_save_session;
 #endif
 
+    if (u->peer.notify || stcf->learn_after_headers) {
+        stp->original_notify = u->peer.notify;
+        u->peer.notify = ngx_http_upstream_sticky_notify_peer;
+    }
+
     ngx_http_upstream_sticky_get_id(stcf, r, stcf->lookup_vars, &stp->id);
 
     return NGX_OK;
@@ -393,6 +406,24 @@ ngx_http_upstream_sticky_free_peer(ngx_peer_connection_t *pc, void *data,
 {
     ngx_http_upstream_sticky_peer_data_t  *stp = data;
 
+    if (state & (NGX_PEER_FAILED|NGX_PEER_NEXT)) {
+        goto done;
+    }
+
+    if (stp->conf->shm_zone && !stp->conf->learn_after_headers) {
+        ngx_http_upstream_sticky_learn_peer(stp, pc);
+    }
+
+done:
+
+    stp->original_free_peer(pc, stp->original_data, state);
+}
+
+
+static void
+ngx_http_upstream_sticky_learn_peer(ngx_http_upstream_sticky_peer_data_t *stp,
+    ngx_peer_connection_t *pc)
+{
     ngx_str_t                              sess_id;
     ngx_msec_t                             now;
     ngx_time_t                            *tp;
@@ -403,22 +434,14 @@ ngx_http_upstream_sticky_free_peer(ngx_peer_connection_t *pc, void *data,
     ngx_http_upstream_sticky_srv_conf_t   *stcf;
     ngx_http_upstream_sticky_sess_node_t  *sn;
 
-    if (state & (NGX_PEER_FAILED|NGX_PEER_NEXT)) {
-        goto done;
-    }
-
-    stcf = stp->conf;
-
-    if (stcf->shm_zone == NULL) {
-        goto done;
-    }
-
     if (pc->sid == NULL) {
         ngx_log_error(NGX_LOG_WARN, pc->log, 0,
                       "balancer does not support sticky");
-        goto done;
+        return;
     }
 
+    stcf = stp->conf;
+
     r = stp->request;
 
     sess = stcf->shm_zone->data;
@@ -485,10 +508,6 @@ ngx_http_upstream_sticky_free_peer(ngx_peer_connection_t *pc, void *data,
     }
 
     ngx_shmtx_unlock(&sess->shpool->mutex);
-
-done:
-
-    stp->original_free_peer(pc, stp->original_data, state);
 }
 
 
@@ -514,6 +533,24 @@ ngx_http_upstream_sticky_save_session(ngx_peer_connection_t *pc, void *data)
 #endif
 
 
+static void
+ngx_http_upstream_sticky_notify_peer(ngx_peer_connection_t *pc, void *data,
+    ngx_uint_t type)
+{
+    ngx_http_upstream_sticky_peer_data_t  *stp = data;
+
+    if (type == NGX_HTTP_UPSTREAM_NOTIFY_HEADER
+        && stp->conf->learn_after_headers)
+    {
+        ngx_http_upstream_sticky_learn_peer(stp, pc);
+    }
+
+    if (stp->original_notify) {
+        stp->original_notify(pc, stp->original_data, type);
+    }
+}
+
+
 static ngx_int_t
 ngx_http_upstream_sticky_cookie_insert(ngx_peer_connection_t *pc,
     ngx_http_upstream_sticky_peer_data_t *stp)
@@ -934,6 +971,8 @@ ngx_http_upstream_sticky_create_conf(ngx_conf_t *cf)
      *     stcf->cookie_path = { 0, NULL };
      *     stcf->cookie_httponly = 0;
      *     stcf->cookie_secure = 0;
+     *
+     *     stcf->learn_after_headers = 0;
      */
 
     stcf->cookie_expires = NGX_CONF_UNSET;
@@ -1267,6 +1306,9 @@ ngx_http_upstream_sticky_learn(ngx_conf_t *cf,
 
             *indexp = index;
 
+        } else if (ngx_strcmp(value[i].data, "header") == 0) {
+            stcf->learn_after_headers = 1;
+
         } else {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "unknown parameter \"%V\"", &value[i]);
index 88d954f17801dec62f424411d13f13199695f57c..f177f0a2854473889a8116bcaec191468888d574 100644 (file)
@@ -2607,6 +2607,10 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
         }
     }
 
+    if (u->peer.notify) {
+        u->peer.notify(&u->peer, u->peer.data, NGX_HTTP_UPSTREAM_NOTIFY_HEADER);
+    }
+
     if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
         return;
     }
index 4f1663225acccafd422a2077311827fce21c3d47..0d48db78807651d0086c275789cf7096ad797e9c 100644 (file)
@@ -57,6 +57,9 @@
 #define NGX_HTTP_UPSTREAM_IGN_VARY           0x00000200
 
 
+#define NGX_HTTP_UPSTREAM_NOTIFY_HEADER      0x1
+
+
 typedef struct {
     ngx_uint_t                       status;
     ngx_msec_t                       response_time;