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;