Mercurial > hg > ngx_http_upstream_keepalive
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; |