Mercurial > hg > ngx_http_upstream_keepalive
comparison ngx_http_upstream_keepalive_module.c @ 6:bef88ba0b378
Keepalive: distinguish between upstream servers by default.
Option 'single' may be used if single pool of connections desired for some
reason.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 24 Oct 2008 02:03:39 +0400 |
parents | e7d1b49e0611 |
children | 565939797f5c |
comparison
equal
deleted
inserted
replaced
5:e7d1b49e0611 | 6:bef88ba0b378 |
---|---|
10 | 10 |
11 | 11 |
12 typedef struct { | 12 typedef struct { |
13 ngx_queue_t queue; | 13 ngx_queue_t queue; |
14 ngx_connection_t *connection; | 14 ngx_connection_t *connection; |
15 | |
16 socklen_t socklen; | |
17 struct sockaddr_storage sockaddr; | |
18 | |
15 } ngx_http_upstream_keepalive_cache_t; | 19 } ngx_http_upstream_keepalive_cache_t; |
16 | 20 |
17 | 21 |
18 typedef struct { | 22 typedef struct { |
19 ngx_uint_t max_cached; | 23 ngx_uint_t max_cached; |
24 ngx_uint_t single; /* unsigned:1 */ | |
20 | 25 |
21 ngx_queue_t cache; | 26 ngx_queue_t cache; |
22 ngx_queue_t free; | 27 ngx_queue_t free; |
23 | 28 |
24 ngx_http_upstream_init_pt original_init_upstream; | 29 ngx_http_upstream_init_pt original_init_upstream; |
54 | 59 |
55 | 60 |
56 static ngx_command_t ngx_http_upstream_keepalive_commands[] = { | 61 static ngx_command_t ngx_http_upstream_keepalive_commands[] = { |
57 | 62 |
58 { ngx_string("keepalive"), | 63 { ngx_string("keepalive"), |
59 NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1, | 64 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, |
60 ngx_http_upstream_keepalive, | 65 ngx_http_upstream_keepalive, |
61 0, | 66 0, |
62 0, | 67 0, |
63 NULL }, | 68 NULL }, |
64 | 69 |
177 ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) | 182 ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) |
178 { | 183 { |
179 ngx_http_upstream_keepalive_peer_data_t *kp = data; | 184 ngx_http_upstream_keepalive_peer_data_t *kp = data; |
180 ngx_http_upstream_keepalive_cache_t *item; | 185 ngx_http_upstream_keepalive_cache_t *item; |
181 | 186 |
182 ngx_queue_t *q; | 187 ngx_int_t rc; |
188 ngx_queue_t *q, *cache; | |
183 ngx_connection_t *c; | 189 ngx_connection_t *c; |
184 | 190 |
185 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 191 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
186 "get keepalive peer"); | 192 "get keepalive peer"); |
187 | 193 |
188 /* XXX single pool of cached connections */ | 194 /* single pool of cached connections */ |
189 | 195 |
190 if (!ngx_queue_empty(&kp->conf->cache)) { | 196 if (kp->conf->single && !ngx_queue_empty(&kp->conf->cache)) { |
191 | 197 |
192 q = ngx_queue_head(&kp->conf->cache); | 198 q = ngx_queue_head(&kp->conf->cache); |
193 ngx_queue_remove(q); | 199 ngx_queue_remove(q); |
194 | 200 |
195 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | 201 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); |
206 pc->cached = 1; | 212 pc->cached = 1; |
207 | 213 |
208 return NGX_DONE; | 214 return NGX_DONE; |
209 } | 215 } |
210 | 216 |
211 return kp->original_get_peer(pc, kp->data); | 217 rc = kp->original_get_peer(pc, kp->data); |
218 | |
219 if (kp->conf->single || rc != NGX_OK) { | |
220 return rc; | |
221 } | |
222 | |
223 /* search cache for suitable connection */ | |
224 | |
225 cache = &kp->conf->cache; | |
226 | |
227 for (q = ngx_queue_head(cache); | |
228 q != ngx_queue_sentinel(cache); | |
229 q = ngx_queue_next(q)) | |
230 { | |
231 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | |
232 c = item->connection; | |
233 | |
234 if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr, | |
235 item->socklen, pc->socklen) | |
236 == 0) | |
237 { | |
238 ngx_queue_remove(q); | |
239 ngx_queue_insert_head(&kp->conf->free, q); | |
240 | |
241 c->idle = 0; | |
242 c->log = pc->log; | |
243 c->read->log = pc->log; | |
244 c->write->log = pc->log; | |
245 | |
246 pc->connection = c; | |
247 pc->cached = 1; | |
248 | |
249 return NGX_DONE; | |
250 } | |
251 } | |
252 | |
253 return NGX_OK; | |
212 } | 254 } |
213 | 255 |
214 | 256 |
215 static void | 257 static void |
216 ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, | 258 ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, |
266 c->data = kp->conf; | 308 c->data = kp->conf; |
267 c->idle = 1; | 309 c->idle = 1; |
268 c->log = ngx_cycle->log; | 310 c->log = ngx_cycle->log; |
269 c->read->log = ngx_cycle->log; | 311 c->read->log = ngx_cycle->log; |
270 c->write->log = ngx_cycle->log; | 312 c->write->log = ngx_cycle->log; |
313 | |
314 item->socklen = pc->socklen; | |
315 ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen); | |
271 } | 316 } |
272 | 317 |
273 return kp->original_free_peer(pc, kp->data, state); | 318 return kp->original_free_peer(pc, kp->data, state); |
274 } | 319 } |
275 | 320 |
365 | 410 |
366 /* read options */ | 411 /* read options */ |
367 | 412 |
368 value = cf->args->elts; | 413 value = cf->args->elts; |
369 | 414 |
370 for (i = 1; i < cf->args->nelts; i++) { | 415 n = ngx_atoi(value[1].data, value[1].len); |
371 | 416 |
372 if (ngx_strncmp(value[i].data, "cached=", 7) == 0) { | 417 if (n == NGX_ERROR || n == 0) { |
373 n = ngx_atoi(&value[i].data[7], value[i].len - 7); | 418 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
374 | 419 "invalid value \"%V\" in \"%V\" directive", |
375 if (n == NGX_ERROR || n == 0) { | 420 &value[1], &cmd->name); |
376 goto invalid; | 421 return NGX_CONF_ERROR; |
377 } | 422 } |
378 | 423 |
379 kcf->max_cached = n; | 424 kcf->max_cached = n; |
425 | |
426 for (i = 2; i < cf->args->nelts; i++) { | |
427 | |
428 if (ngx_strcmp(value[i].data, "single") == 0) { | |
429 | |
430 kcf->single = 1; | |
380 | 431 |
381 continue; | 432 continue; |
382 } | 433 } |
383 | 434 |
384 goto invalid; | 435 goto invalid; |