Mercurial > hg > ngx_http_upstream_keepalive
comparison ngx_http_upstream_keepalive_module.c @ 11:15530a464dba
Keepalive: don't cache invalid connections.
1. Remember failed status, since peer.free() may be called more than once.
It's called twice if peer fails - once from ngx_http_upstream_next() with
NGX_PEER_FAILED set, and then from ngx_http_upstream_finalize_request()
without.
2. We shouldn't cache connection unless we aren't expecting anything from
upstream. For memcached this means either 404 response or 200 response with
all body read (body may not be read e.g. when serving HEAD request).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 13 Nov 2008 19:36:23 +0300 |
parents | 06bd0e50e696 |
children | 28af4b0b32c1 |
comparison
equal
deleted
inserted
replaced
10:06bd0e50e696 | 11:15530a464dba |
---|---|
23 | 23 |
24 | 24 |
25 typedef struct { | 25 typedef struct { |
26 ngx_http_upstream_keepalive_srv_conf_t *conf; | 26 ngx_http_upstream_keepalive_srv_conf_t *conf; |
27 | 27 |
28 ngx_http_upstream_t *upstream; | |
29 | |
28 void *data; | 30 void *data; |
29 | 31 |
30 ngx_event_get_peer_pt original_get_peer; | 32 ngx_event_get_peer_pt original_get_peer; |
31 ngx_event_free_peer_pt original_free_peer; | 33 ngx_event_free_peer_pt original_free_peer; |
34 | |
35 ngx_uint_t failed; /* unsigned:1 */ | |
32 | 36 |
33 } ngx_http_upstream_keepalive_peer_data_t; | 37 } ngx_http_upstream_keepalive_peer_data_t; |
34 | 38 |
35 | 39 |
36 typedef struct { | 40 typedef struct { |
167 if (kcf->original_init_peer(r, us) != NGX_OK) { | 171 if (kcf->original_init_peer(r, us) != NGX_OK) { |
168 return NGX_ERROR; | 172 return NGX_ERROR; |
169 } | 173 } |
170 | 174 |
171 kp->conf = kcf; | 175 kp->conf = kcf; |
176 kp->upstream = r->upstream; | |
172 kp->data = r->upstream->peer.data; | 177 kp->data = r->upstream->peer.data; |
173 kp->original_get_peer = r->upstream->peer.get; | 178 kp->original_get_peer = r->upstream->peer.get; |
174 kp->original_free_peer = r->upstream->peer.free; | 179 kp->original_free_peer = r->upstream->peer.free; |
175 | 180 |
176 r->upstream->peer.data = kp; | 181 r->upstream->peer.data = kp; |
191 ngx_queue_t *q, *cache; | 196 ngx_queue_t *q, *cache; |
192 ngx_connection_t *c; | 197 ngx_connection_t *c; |
193 | 198 |
194 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 199 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
195 "get keepalive peer"); | 200 "get keepalive peer"); |
201 | |
202 kp->failed = 0; | |
196 | 203 |
197 /* single pool of cached connections */ | 204 /* single pool of cached connections */ |
198 | 205 |
199 if (kp->conf->single && !ngx_queue_empty(&kp->conf->cache)) { | 206 if (kp->conf->single && !ngx_queue_empty(&kp->conf->cache)) { |
200 | 207 |
262 ngx_uint_t state) | 269 ngx_uint_t state) |
263 { | 270 { |
264 ngx_http_upstream_keepalive_peer_data_t *kp = data; | 271 ngx_http_upstream_keepalive_peer_data_t *kp = data; |
265 ngx_http_upstream_keepalive_cache_t *item; | 272 ngx_http_upstream_keepalive_cache_t *item; |
266 | 273 |
267 ngx_queue_t *q; | 274 ngx_uint_t status; |
268 ngx_connection_t *c; | 275 ngx_queue_t *q; |
276 ngx_connection_t *c; | |
277 ngx_http_upstream_t *u; | |
269 | 278 |
270 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 279 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
271 "free keepalive peer"); | 280 "free keepalive peer"); |
272 | 281 |
273 if (!(state & NGX_PEER_FAILED) | 282 /* remember failed state - peer.free() may be called more than once */ |
274 && pc->connection != NULL) | 283 |
284 if (state & NGX_PEER_FAILED) { | |
285 kp->failed = 1; | |
286 } | |
287 | |
288 /* | |
289 * cache valid connections | |
290 * | |
291 * For memcached this means status either 404 or 200. For status 200 we | |
292 * should also check if all response body was read (u->length == 0) and | |
293 * make sure that u->length is valid (we use u->header_sent flag to test | |
294 * this). Memcached is the only supported protocol for now. | |
295 * | |
296 * Some notes on other possibilities (incomplete): | |
297 * | |
298 * fastcgi: u->pipe->upstream_done should be sufficient | |
299 * | |
300 * proxy buffered: u->pipe->upstream_done, 304 replies, replies to head | |
301 * requests (see RFC 2616, 4.4 Message Length) | |
302 * | |
303 * proxy unbuffered: 200 as for memcached (with u->length == 0 and | |
304 * header_sent), 304, replies to head requests | |
305 * | |
306 * subrequest_in_memory: won't work as of now | |
307 * | |
308 * TODO: move this logic to protocol modules (NGX_PEER_KEEPALIVE?) | |
309 */ | |
310 | |
311 u = kp->upstream; | |
312 status = u->headers_in.status_n; | |
313 | |
314 if (!kp->failed | |
315 && pc->connection != NULL | |
316 && (status == NGX_HTTP_NOT_FOUND | |
317 || (status == NGX_HTTP_OK && u->header_sent && u->length == 0))) | |
275 { | 318 { |
276 c = pc->connection; | 319 c = pc->connection; |
277 | 320 |
278 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 321 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
279 "free keepalive peer: saving connection %p", c); | 322 "free keepalive peer: saving connection %p", c); |