diff options
Diffstat (limited to 'src/http/modules/proxy')
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_cache.c | 37 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.c | 33 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.h | 3 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_upstream.c | 126 |
4 files changed, 181 insertions, 18 deletions
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c index e8e3b5280..0bc7c6159 100644 --- a/src/http/modules/proxy/ngx_http_proxy_cache.c +++ b/src/http/modules/proxy/ngx_http_proxy_cache.c @@ -216,6 +216,30 @@ static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) } +#if 0 + +static void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p) +{ + rc = ngx_http_busy_lock(p->lcf->busy_lock, p->cache->ctx.md5); + + if (rc == NGX_OK) { + ngx_http_proxy_request_upstream(p); + } + + if (rc == NGX_AGAIN) { + if (p->busy_lock_time) { + ngx_add_timer(p->request->connection->read, 1000); + return; + } + } + + rc == NGX_ERROR + check waitn +} + +#endif + + int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) { int rc, len, i; @@ -428,10 +452,21 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p) { + ngx_event_pipe_t *ep; + if (p->cache == NULL) { return NGX_OK; } + ep = p->upstream->event_pipe; + + if (p->cache->ctx.length == -1) { + /* TODO: test rc */ + ngx_write_file(&ep->temp_file->file, + (char *) &ep->read_length, sizeof(off_t), + offsetof(ngx_http_cache_header_t, length)); + } + return ngx_http_cache_update_file(p->request, &p->cache->ctx, - &p->upstream->event_pipe->temp_file->file.name); + &ep->temp_file->file.name); } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c index 860ba7ac7..a28495668 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -266,7 +266,9 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t)); - if (!p->lcf->cache) { + if (!p->lcf->cache + || (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD)) + { p->state->cache = NGX_HTTP_PROXY_CACHE_PASS; } else if (r->bypass_cache) { @@ -290,16 +292,16 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) rc = ngx_http_proxy_get_cached_response(p); + if (rc == NGX_DONE || rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { + return rc; + } + p->valid_header_in = 1; if (rc == NGX_OK) { return ngx_http_proxy_send_cached_response(p); } - if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { - return rc; - } - /* rc == NGX_DECLINED || NGX_HTTP_CACHE_STALE || NGX_HTTP_CACHE_AGED */ return ngx_http_proxy_request_upstream(p); @@ -312,8 +314,7 @@ void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc) "finalize http proxy request"); if (p->upstream->peer.connection) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } if (p->header_sent @@ -329,8 +330,17 @@ void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc) } -void ngx_http_proxy_close_connection(ngx_connection_t *c) +void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p) { + ngx_connection_t *c; + + c = p->upstream->peer.connection; + p->upstream->peer.connection = NULL; + + if (p->lcf->busy_lock) { + p->lcf->busy_lock->conn_n--; + } + ngx_log_debug(c->log, "proxy close connection: %d" _ c->fd); if (c->fd == -1) { @@ -505,6 +515,13 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, if (conf->busy_lock && conf->cache && conf->busy_lock->busy == NULL) { + /* ngx_alloc_shared() */ + conf->busy_lock->busy_mask = + ngx_palloc(cf->pool, (conf->busy_lock->max_conn + 7) / 8); + if (conf->busy_lock->busy_mask == NULL) { + return NGX_CONF_ERROR; + } + /* 16 bytes are 128 bits of the md5 */ /* ngx_alloc_shared() */ diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h index 6e4b08429..919a0afc3 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -140,6 +140,7 @@ struct ngx_http_proxy_ctx_s { ngx_hunk_t *header_in; + time_t busy_lock_time; unsigned accel:1; @@ -188,7 +189,7 @@ int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p); size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len); void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); -void ngx_http_proxy_close_connection(ngx_connection_t *c); +void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p); int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p, diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c index cee93ee65..c66c16418 100644 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -11,6 +11,8 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); static void ngx_http_proxy_init_upstream(void *data); static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p); +static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p); +static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev); static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p); static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); static void ngx_http_proxy_send_request_handler(ngx_event_t *wev); @@ -264,7 +266,11 @@ ngx_log_debug(r->connection->log, "timer_set: %d" _ wctx->pool = r->pool; - ngx_http_proxy_connect(p); + if (p->lcf->busy_lock) { + ngx_http_proxy_upstream_busy_lock(p); + } else { + ngx_http_proxy_connect(p); + } } @@ -306,6 +312,109 @@ static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p) } +static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p) +{ + int ft_type; + + if (p->lcf->busy_lock->conn_n < p->lcf->busy_lock->max_conn) { + p->lcf->busy_lock->conn_n++; + + if (p->busy_lock_time) { + p->busy_lock_time = 0; + p->lcf->busy_lock->waiting_n--; + } + + ngx_http_proxy_connect(p); + return; + } + + if (p->busy_lock_time) { + if (p->busy_lock_time < p->lcf->busy_lock->timeout) { + ngx_add_timer(p->request->connection->read, 1000); + return; + } + + p->lcf->busy_lock->waiting_n--; + ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK; + + } else { + if (p->lcf->busy_lock->waiting_n < p->lcf->busy_lock->max_waiting) { + p->lcf->busy_lock->waiting_n++; + ngx_add_timer(p->request->connection->read, 1000); + p->request->connection->read->event_handler = + ngx_http_proxy_upstream_busy_lock_handler; + /* TODO: ngx_handle_level_read_event() */ + return; + } + + ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING; + } + + if (p->stale && (p->lcf->use_stale & ft_type)) { + ngx_http_proxy_finalize_request(p, + ngx_http_proxy_send_cached_response(p)); + return; + } + + ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE); + return; +} + + +static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_proxy_ctx_t *p; + + ngx_log_debug(rev->log, "busy lock"); + + c = rev->data; + r = c->data; + p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); + p->action = "waiting upstream in busy lock"; + + if (rev->timedout) { + rev->timedout = 0; + p->busy_lock_time++; + ngx_http_proxy_upstream_busy_lock(p); + return; + } + + ngx_log_debug(rev->log, "client sent while busy lock"); + + /* + * TODO: kevent() notify about error, otherwise we need to + * call ngx_peek(): recv(MGS_PEEK) to get errno. THINK about aio + * if there's no error we need to disable event. + */ + +#if (HAVE_KQUEUE) + + if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) { + p->lcf->busy_lock->waiting_n--; + + ngx_del_timer(rev); + + ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno, + "client() closed connection"); + + if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) { + ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + /* we have not HTTP code for the case when a client cancels a request */ + + ngx_http_proxy_finalize_request(p, 0); + return; + } + +#endif + +} + + static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) { int rc; @@ -1011,8 +1120,7 @@ static void ngx_http_proxy_process_body(ngx_event_t *ev) } if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } } @@ -1024,8 +1132,7 @@ static void ngx_http_proxy_process_body(ngx_event_t *ev) if (ep->downstream_error) { if (!p->cachable && p->upstream->peer.connection) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } if (p->upstream->peer.connection == NULL) { @@ -1080,8 +1187,7 @@ ngx_log_debug(p->request->connection->log, "next upstream: %d" _ ft_type); } if (p->upstream->peer.connection) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } if (status) { @@ -1100,5 +1206,9 @@ ngx_log_debug(p->request->connection->log, "next upstream: %d" _ ft_type); } } - ngx_http_proxy_connect(p); + if (p->lcf->busy_lock) { + ngx_http_proxy_upstream_busy_lock(p); + } else { + ngx_http_proxy_connect(p); + } } |