comparison ngx_http_upstream_keepalive_module.c @ 2:8545bbda9e4b

Keepalive: reimplement using queues.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 23 Oct 2008 18:15:26 +0400
parents ca955a7f651b
children 42e64900483b
comparison
equal deleted inserted replaced
1:ca955a7f651b 2:8545bbda9e4b
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_http.h> 9 #include <ngx_http.h>
10 10
11 typedef struct {
12 ngx_queue_t queue;
13 ngx_connection_t *connection;
14 } ngx_http_upstream_keepalive_cache_t;
11 15
12 typedef struct { 16 typedef struct {
13 ngx_uint_t max_cached; 17 ngx_uint_t max_cached;
14 ngx_uint_t last_cached; 18
15 19 ngx_queue_t cache;
16 ngx_connection_t **cached; 20 ngx_queue_t free;
17 21
18 ngx_http_upstream_init_pt original_init_upstream; 22 ngx_http_upstream_init_pt original_init_upstream;
19 ngx_http_upstream_init_peer_pt original_init_peer; 23 ngx_http_upstream_init_peer_pt original_init_peer;
20 24
21 } ngx_http_upstream_keepalive_srv_conf_t; 25 } ngx_http_upstream_keepalive_srv_conf_t;
93 97
94 ngx_int_t 98 ngx_int_t
95 ngx_http_upstream_init_keepalive(ngx_conf_t *cf, 99 ngx_http_upstream_init_keepalive(ngx_conf_t *cf,
96 ngx_http_upstream_srv_conf_t *us) 100 ngx_http_upstream_srv_conf_t *us)
97 { 101 {
102 ngx_uint_t i;
98 ngx_http_upstream_keepalive_srv_conf_t *kcf; 103 ngx_http_upstream_keepalive_srv_conf_t *kcf;
104 ngx_http_upstream_keepalive_cache_t *cached;
99 105
100 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, 106 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
101 "init keepalive"); 107 "init keepalive");
102 108
103 kcf = ngx_http_conf_upstream_srv_conf(us, 109 kcf = ngx_http_conf_upstream_srv_conf(us,
109 115
110 kcf->original_init_peer = us->peer.init; 116 kcf->original_init_peer = us->peer.init;
111 117
112 us->peer.init = ngx_http_upstream_init_keepalive_peer; 118 us->peer.init = ngx_http_upstream_init_keepalive_peer;
113 119
114 kcf->cached = ngx_pcalloc(cf->pool, 120 /* allocate cache items and add to free queue */
115 sizeof(ngx_connection_t *) * kcf->max_cached); 121
116 if (kcf->cached == NULL) { 122 cached = ngx_pcalloc(cf->pool,
123 sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached);
124 if (cached == NULL) {
117 return NGX_ERROR; 125 return NGX_ERROR;
118 } 126 }
119 127
128 ngx_queue_init(&kcf->cache);
129 ngx_queue_init(&kcf->free);
130
131 for (i = 0; i < kcf->max_cached; i++) {
132 ngx_queue_insert_head(&kcf->free, &cached[i].queue);
133 }
120 134
121 return NGX_OK; 135 return NGX_OK;
122 } 136 }
123 137
124 138
159 173
160 static ngx_int_t 174 static ngx_int_t
161 ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) 175 ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
162 { 176 {
163 ngx_http_upstream_keepalive_peer_data_t *kp = data; 177 ngx_http_upstream_keepalive_peer_data_t *kp = data;
164 178 ngx_http_upstream_keepalive_cache_t *item;
179
180 ngx_queue_t *q;
165 ngx_connection_t *c; 181 ngx_connection_t *c;
166 182
167 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, 183 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
168 "get keepalive peer"); 184 "get keepalive peer");
169 185
170 /* XXX single pool of cached connections */ 186 /* XXX single pool of cached connections */
171 187
172 if (kp->conf->last_cached) { 188 if (!ngx_queue_empty(&kp->conf->cache)) {
173 189
174 c = kp->conf->cached[--kp->conf->last_cached]; 190 q = ngx_queue_head(&kp->conf->cache);
191 ngx_queue_remove(q);
192
193 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
194 c = item->connection;
195
196 ngx_queue_insert_head(&kp->conf->free, q);
175 197
176 c->idle = 0; 198 c->idle = 0;
177 c->log = pc->log; 199 c->log = pc->log;
178 c->read->log = pc->log; 200 c->read->log = pc->log;
179 c->write->log = pc->log; 201 c->write->log = pc->log;
191 static void 213 static void
192 ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, 214 ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
193 ngx_uint_t state) 215 ngx_uint_t state)
194 { 216 {
195 ngx_http_upstream_keepalive_peer_data_t *kp = data; 217 ngx_http_upstream_keepalive_peer_data_t *kp = data;
196 218 ngx_http_upstream_keepalive_cache_t *item;
219
220 ngx_queue_t *q;
197 ngx_connection_t *c; 221 ngx_connection_t *c;
198 222
199 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, 223 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
200 "free keepalive peer"); 224 "free keepalive peer");
201 225
202 if (!(state & NGX_PEER_FAILED) 226 if (!(state & NGX_PEER_FAILED)
203 && pc->connection != NULL 227 && pc->connection != NULL
204 && kp->conf->last_cached < kp->conf->max_cached) 228 && !ngx_queue_empty(&kp->conf->free))
205 { 229 {
206 c = pc->connection; 230 c = pc->connection;
207 231
208 kp->conf->cached[kp->conf->last_cached++] = c; 232 q = ngx_queue_head(&kp->conf->free);
233 ngx_queue_remove(q);
234
235 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
236 item->connection = c;
237
238 ngx_queue_insert_head(&kp->conf->cache, q);
239
209 pc->connection = NULL; 240 pc->connection = NULL;
210 241
211 if (c->read->timer_set) { 242 if (c->read->timer_set) {
212 ngx_del_timer(c->read); 243 ngx_del_timer(c->read);
213 } 244 }
239 270
240 static void 271 static void
241 ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev) 272 ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev)
242 { 273 {
243 ngx_http_upstream_keepalive_srv_conf_t *conf; 274 ngx_http_upstream_keepalive_srv_conf_t *conf;
244 275 ngx_http_upstream_keepalive_cache_t *item;
245 ngx_uint_t i; 276
277 ngx_queue_t *q, *cache;
246 ngx_connection_t *c; 278 ngx_connection_t *c;
247 279
248 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, 280 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
249 "keepalive close handler"); 281 "keepalive close handler");
250 282
251 c = ev->data; 283 c = ev->data;
252 conf = c->data; 284 conf = c->data;
253 285
254 for (i = 0; i < conf->last_cached; i++) { 286 cache = &conf->cache;
255 if (conf->cached[i] == c) { 287
256 288 for (q = ngx_queue_head(cache);
257 conf->cached[i] = conf->cached[--conf->last_cached]; 289 q != ngx_queue_sentinel(cache);
258 290 q = ngx_queue_next(q))
291 {
292 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
293
294 if (item->connection == c) {
295 ngx_queue_remove(q);
259 ngx_close_connection(c); 296 ngx_close_connection(c);
260 return; 297 return;
261 } 298 }
262 } 299 }
263 300
279 } 316 }
280 317
281 /* 318 /*
282 * set by ngx_pcalloc(): 319 * set by ngx_pcalloc():
283 * 320 *
284 * conf->last_cached = 0;
285 * conf->original_init_upstream = NULL; 321 * conf->original_init_upstream = NULL;
286 * conf->original_init_peer = NULL; 322 * conf->original_init_peer = NULL;
287 */ 323 */
288 324
289 conf->max_cached = 1; 325 conf->max_cached = 1;