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);