~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/modules/ngx_http_upstream_ip_hash_module.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_http.h>
 10 
 11 
 12 typedef struct {
 13     /* the round robin data must be first */
 14     ngx_http_upstream_rr_peer_data_t   rrp;
 15 
 16     ngx_uint_t                         hash;
 17 
 18     u_char                             addr[3];
 19 
 20     u_char                             tries;
 21 
 22     ngx_event_get_peer_pt              get_rr_peer;
 23 } ngx_http_upstream_ip_hash_peer_data_t;
 24 
 25 
 26 static ngx_int_t ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
 27     ngx_http_upstream_srv_conf_t *us);
 28 static ngx_int_t ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc,
 29     void *data);
 30 static char *ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd,
 31     void *conf);
 32 
 33 
 34 static ngx_command_t  ngx_http_upstream_ip_hash_commands[] = {
 35 
 36     { ngx_string("ip_hash"),
 37       NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
 38       ngx_http_upstream_ip_hash,
 39       0,
 40       0,
 41       NULL },
 42 
 43       ngx_null_command
 44 };
 45 
 46 
 47 static ngx_http_module_t  ngx_http_upstream_ip_hash_module_ctx = {
 48     NULL,                                  /* preconfiguration */
 49     NULL,                                  /* postconfiguration */
 50 
 51     NULL,                                  /* create main configuration */
 52     NULL,                                  /* init main configuration */
 53 
 54     NULL,                                  /* create server configuration */
 55     NULL,                                  /* merge server configuration */
 56 
 57     NULL,                                  /* create location configuration */
 58     NULL                                   /* merge location configuration */
 59 };
 60 
 61 
 62 ngx_module_t  ngx_http_upstream_ip_hash_module = {
 63     NGX_MODULE_V1,
 64     &ngx_http_upstream_ip_hash_module_ctx, /* module context */
 65     ngx_http_upstream_ip_hash_commands,    /* module directives */
 66     NGX_HTTP_MODULE,                       /* module type */
 67     NULL,                                  /* init master */
 68     NULL,                                  /* init module */
 69     NULL,                                  /* init process */
 70     NULL,                                  /* init thread */
 71     NULL,                                  /* exit thread */
 72     NULL,                                  /* exit process */
 73     NULL,                                  /* exit master */
 74     NGX_MODULE_V1_PADDING
 75 };
 76 
 77 
 78 ngx_int_t
 79 ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
 80 {
 81     if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
 82         return NGX_ERROR;
 83     }
 84 
 85     us->peer.init = ngx_http_upstream_init_ip_hash_peer;
 86 
 87     return NGX_OK;
 88 }
 89 
 90 
 91 static ngx_int_t
 92 ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
 93     ngx_http_upstream_srv_conf_t *us)
 94 {
 95     u_char                                 *p;
 96     struct sockaddr_in                     *sin;
 97     ngx_http_upstream_ip_hash_peer_data_t  *iphp;
 98 
 99     iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t));
100     if (iphp == NULL) {
101         return NGX_ERROR;
102     }
103 
104     r->upstream->peer.data = &iphp->rrp;
105 
106     if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
107         return NGX_ERROR;
108     }
109 
110     r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;
111 
112     /* AF_INET only */
113 
114     if (r->connection->sockaddr->sa_family == AF_INET) {
115 
116         sin = (struct sockaddr_in *) r->connection->sockaddr;
117         p = (u_char *) &sin->sin_addr.s_addr;
118         iphp->addr[0] = p[0];
119         iphp->addr[1] = p[1];
120         iphp->addr[2] = p[2];
121 
122     } else {
123         iphp->addr[0] = 0;
124         iphp->addr[1] = 0;
125         iphp->addr[2] = 0;
126     }
127 
128     iphp->hash = 89;
129     iphp->tries = 0;
130     iphp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;
131 
132     return NGX_OK;
133 }
134 
135 
136 static ngx_int_t
137 ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
138 {
139     ngx_http_upstream_ip_hash_peer_data_t  *iphp = data;
140 
141     time_t                        now;
142     uintptr_t                     m;
143     ngx_uint_t                    i, n, p, hash;
144     ngx_http_upstream_rr_peer_t  *peer;
145 
146     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
147                    "get ip hash peer, try: %ui", pc->tries);
148 
149     /* TODO: cached */
150 
151     if (iphp->tries > 20 || iphp->rrp.peers->single) {
152         return iphp->get_rr_peer(pc, &iphp->rrp);
153     }
154 
155     now = ngx_time();
156 
157     pc->cached = 0;
158     pc->connection = NULL;
159 
160     hash = iphp->hash;
161 
162     for ( ;; ) {
163 
164         for (i = 0; i < 3; i++) {
165             hash = (hash * 113 + iphp->addr[i]) % 6271;
166         }
167 
168         p = hash % iphp->rrp.peers->number;
169 
170         n = p / (8 * sizeof(uintptr_t));
171         m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
172 
173         if (!(iphp->rrp.tried[n] & m)) {
174 
175             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
176                            "get ip hash peer, hash: %ui %04XA", p, m);
177 
178             peer = &iphp->rrp.peers->peer[p];
179 
180             /* ngx_lock_mutex(iphp->rrp.peers->mutex); */
181 
182             if (!peer->down) {
183 
184                 if (peer->max_fails == 0 || peer->fails < peer->max_fails) {
185                     break;
186                 }
187 
188                 if (now - peer->accessed > peer->fail_timeout) {
189                     peer->fails = 0;
190                     break;
191                 }
192             }
193 
194             iphp->rrp.tried[n] |= m;
195 
196             /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
197 
198             pc->tries--;
199         }
200 
201         if (++iphp->tries >= 20) {
202             return iphp->get_rr_peer(pc, &iphp->rrp);
203         }
204     }
205 
206     iphp->rrp.current = p;
207 
208     pc->sockaddr = peer->sockaddr;
209     pc->socklen = peer->socklen;
210     pc->name = &peer->name;
211 
212     /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
213 
214     iphp->rrp.tried[n] |= m;
215     iphp->hash = hash;
216 
217     return NGX_OK;
218 }
219 
220 
221 static char *
222 ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
223 {
224     ngx_http_upstream_srv_conf_t  *uscf;
225 
226     uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
227 
228     uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash;
229 
230     uscf->flags = NGX_HTTP_UPSTREAM_CREATE
231                   |NGX_HTTP_UPSTREAM_MAX_FAILS
232                   |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
233                   |NGX_HTTP_UPSTREAM_DOWN;
234 
235     return NGX_CONF_OK;
236 }
237 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.