Mercurial > hg > nginx
comparison src/http/ngx_http_upstream.c @ 884:4d68c486fcb0
upstream choice modules
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 04 Dec 2006 16:46:13 +0000 |
parents | 3b763d36e055 |
children | bb6e1bbcdd67 |
comparison
equal
deleted
inserted
replaced
883:eac23634d614 | 884:4d68c486fcb0 |
---|---|
85 | 85 |
86 #if (NGX_HTTP_SSL) | 86 #if (NGX_HTTP_SSL) |
87 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, | 87 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, |
88 ngx_http_upstream_t *u, ngx_connection_t *c); | 88 ngx_http_upstream_t *u, ngx_connection_t *c); |
89 static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c); | 89 static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c); |
90 static void ngx_http_upstream_ssl_shutdown(ngx_connection_t *c, | |
91 ngx_peer_t *peer); | |
92 #endif | 90 #endif |
93 | 91 |
94 | 92 |
95 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { | 93 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { |
96 | 94 |
213 0, | 211 0, |
214 0, | 212 0, |
215 NULL }, | 213 NULL }, |
216 | 214 |
217 { ngx_string("server"), | 215 { ngx_string("server"), |
218 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, | 216 NGX_HTTP_UPS_CONF|NGX_CONF_1MORE, |
219 ngx_http_upstream_server, | 217 ngx_http_upstream_server, |
220 NGX_HTTP_SRV_CONF_OFFSET, | 218 NGX_HTTP_SRV_CONF_OFFSET, |
221 0, | 219 0, |
222 NULL }, | 220 NULL }, |
223 | 221 |
306 | 304 |
307 if (r->request_body) { | 305 if (r->request_body) { |
308 u->request_bufs = r->request_body->bufs; | 306 u->request_bufs = r->request_body->bufs; |
309 } | 307 } |
310 | 308 |
309 if (u->conf->upstream->peer.init(r, u->conf->upstream) != NGX_OK) { | |
310 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
311 return; | |
312 } | |
313 | |
311 if (u->create_request(r) != NGX_OK) { | 314 if (u->create_request(r) != NGX_OK) { |
312 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 315 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
313 return; | 316 return; |
314 } | 317 } |
315 | |
316 u->peer.log = r->connection->log; | |
317 | 318 |
318 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 319 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
319 | 320 |
320 u->output.sendfile = r->connection->sendfile; | 321 u->output.sendfile = r->connection->sendfile; |
321 u->output.pool = r->pool; | 322 u->output.pool = r->pool; |
324 u->output.output_filter = ngx_chain_writer; | 325 u->output.output_filter = ngx_chain_writer; |
325 u->output.filter_ctx = &u->writer; | 326 u->output.filter_ctx = &u->writer; |
326 | 327 |
327 u->writer.pool = r->pool; | 328 u->writer.pool = r->pool; |
328 | 329 |
329 if (ngx_array_init(&u->states, r->pool, u->peer.peers->number, | 330 if (ngx_array_init(&u->states, r->pool, 1, |
330 sizeof(ngx_http_upstream_state_t)) | 331 sizeof(ngx_http_upstream_state_t)) |
331 != NGX_OK) | 332 != NGX_OK) |
332 { | 333 { |
333 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 334 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
334 return; | 335 return; |
526 ngx_http_upstream_finalize_request(r, u, | 527 ngx_http_upstream_finalize_request(r, u, |
527 NGX_HTTP_INTERNAL_SERVER_ERROR); | 528 NGX_HTTP_INTERNAL_SERVER_ERROR); |
528 return; | 529 return; |
529 } | 530 } |
530 | 531 |
531 u->state->peer = &u->peer.peers->peer[u->peer.cur_peer].name; | 532 u->state->peer = u->peer.name; |
532 | 533 |
533 if (rc == NGX_BUSY) { | 534 if (rc == NGX_BUSY) { |
534 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams"); | 535 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams"); |
535 } | 536 } |
536 | 537 |
615 | 616 |
616 static void | 617 static void |
617 ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, | 618 ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, |
618 ngx_http_upstream_t *u, ngx_connection_t *c) | 619 ngx_http_upstream_t *u, ngx_connection_t *c) |
619 { | 620 { |
620 ngx_int_t rc; | 621 ngx_int_t rc; |
621 ngx_peer_t *peer; | |
622 | 622 |
623 if (ngx_ssl_create_connection(u->conf->ssl, c, | 623 if (ngx_ssl_create_connection(u->conf->ssl, c, |
624 NGX_SSL_BUFFER|NGX_SSL_CLIENT) | 624 NGX_SSL_BUFFER|NGX_SSL_CLIENT) |
625 == NGX_ERROR) | 625 == NGX_ERROR) |
626 { | 626 { |
630 } | 630 } |
631 | 631 |
632 c->sendfile = 0; | 632 c->sendfile = 0; |
633 u->output.sendfile = 0; | 633 u->output.sendfile = 0; |
634 | 634 |
635 peer = &u->peer.peers->peer[u->peer.cur_peer]; | 635 if (ngx_ssl_set_session(c, u->peer.ssl_session) != NGX_OK) { |
636 | |
637 if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) { | |
638 ngx_http_upstream_finalize_request(r, u, | 636 ngx_http_upstream_finalize_request(r, u, |
639 NGX_HTTP_INTERNAL_SERVER_ERROR); | 637 NGX_HTTP_INTERNAL_SERVER_ERROR); |
640 return; | 638 return; |
641 } | 639 } |
642 | 640 |
661 | 659 |
662 r = c->data; | 660 r = c->data; |
663 u = r->upstream; | 661 u = r->upstream; |
664 | 662 |
665 if (c->ssl->handshaked) { | 663 if (c->ssl->handshaked) { |
664 | |
665 u->peer.save_session(&u->peer, u->peer.data); | |
666 | 666 |
667 c->write->handler = ngx_http_upstream_send_request_handler; | 667 c->write->handler = ngx_http_upstream_send_request_handler; |
668 c->read->handler = ngx_http_upstream_process_header; | 668 c->read->handler = ngx_http_upstream_process_header; |
669 | 669 |
670 ngx_http_upstream_send_request(r, u); | 670 ngx_http_upstream_send_request(r, u); |
970 } | 970 } |
971 #endif | 971 #endif |
972 } | 972 } |
973 | 973 |
974 n = u->peer.connection->recv(u->peer.connection, u->buffer.last, | 974 n = u->peer.connection->recv(u->peer.connection, u->buffer.last, |
975 u->buffer.end - u->buffer.last); | 975 u->buffer.end - u->buffer.last); |
976 | 976 |
977 if (n == NGX_AGAIN) { | 977 if (n == NGX_AGAIN) { |
978 #if 0 | 978 #if 0 |
979 ngx_add_timer(rev, u->read_timeout); | 979 ngx_add_timer(rev, u->read_timeout); |
980 #endif | 980 #endif |
1583 size_t size; | 1583 size_t size; |
1584 ssize_t n; | 1584 ssize_t n; |
1585 ngx_buf_t *b; | 1585 ngx_buf_t *b; |
1586 ngx_int_t rc; | 1586 ngx_int_t rc; |
1587 ngx_uint_t do_write; | 1587 ngx_uint_t do_write; |
1588 ngx_connection_t *c, *client; | 1588 ngx_connection_t *c, *downstream, *upstream; |
1589 ngx_http_request_t *r; | 1589 ngx_http_request_t *r; |
1590 ngx_http_upstream_t *u; | 1590 ngx_http_upstream_t *u; |
1591 ngx_http_core_loc_conf_t *clcf; | 1591 ngx_http_core_loc_conf_t *clcf; |
1592 | 1592 |
1593 c = ev->data; | 1593 c = ev->data; |
1616 | 1616 |
1617 ngx_http_upstream_finalize_request(r, u, 0); | 1617 ngx_http_upstream_finalize_request(r, u, 0); |
1618 return; | 1618 return; |
1619 } | 1619 } |
1620 | 1620 |
1621 client = r->connection; | 1621 downstream = r->connection; |
1622 upstream = u->peer.connection; | |
1622 | 1623 |
1623 b = &u->buffer; | 1624 b = &u->buffer; |
1624 | 1625 |
1625 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 1626 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
1626 | 1627 |
1631 if (do_write) { | 1632 if (do_write) { |
1632 | 1633 |
1633 if (u->out_bufs || u->busy_bufs) { | 1634 if (u->out_bufs || u->busy_bufs) { |
1634 rc = ngx_http_output_filter(r, u->out_bufs); | 1635 rc = ngx_http_output_filter(r, u->out_bufs); |
1635 | 1636 |
1636 if (client->destroyed) { | 1637 if (downstream->destroyed) { |
1637 return; | 1638 return; |
1638 } | 1639 } |
1639 | 1640 |
1640 if (rc == NGX_ERROR) { | 1641 if (rc == NGX_ERROR) { |
1641 ngx_http_upstream_finalize_request(r, u, 0); | 1642 ngx_http_upstream_finalize_request(r, u, 0); |
1647 } | 1648 } |
1648 | 1649 |
1649 if (u->busy_bufs == NULL) { | 1650 if (u->busy_bufs == NULL) { |
1650 | 1651 |
1651 if (u->length == 0 | 1652 if (u->length == 0 |
1652 || u->peer.connection->read->eof | 1653 || upstream->read->eof |
1653 || u->peer.connection->read->error) | 1654 || upstream->read->error) |
1654 { | 1655 { |
1655 ngx_http_upstream_finalize_request(r, u, 0); | 1656 ngx_http_upstream_finalize_request(r, u, 0); |
1656 return; | 1657 return; |
1657 } | 1658 } |
1658 | 1659 |
1665 | 1666 |
1666 if (size > u->length) { | 1667 if (size > u->length) { |
1667 size = u->length; | 1668 size = u->length; |
1668 } | 1669 } |
1669 | 1670 |
1670 if (size && u->peer.connection->read->ready) { | 1671 if (size && upstream->read->ready) { |
1671 | 1672 |
1672 n = u->peer.connection->recv(u->peer.connection, b->last, size); | 1673 n = upstream->recv(upstream, b->last, size); |
1673 | 1674 |
1674 if (n == NGX_AGAIN) { | 1675 if (n == NGX_AGAIN) { |
1675 break; | 1676 break; |
1676 } | 1677 } |
1677 | 1678 |
1688 } | 1689 } |
1689 | 1690 |
1690 break; | 1691 break; |
1691 } | 1692 } |
1692 | 1693 |
1693 if (client->data == r) { | 1694 if (downstream->data == r) { |
1694 if (ngx_handle_write_event(client->write, clcf->send_lowat) | 1695 if (ngx_handle_write_event(downstream->write, clcf->send_lowat) |
1695 == NGX_ERROR) | 1696 == NGX_ERROR) |
1696 { | 1697 { |
1697 ngx_http_upstream_finalize_request(r, u, 0); | 1698 ngx_http_upstream_finalize_request(r, u, 0); |
1698 return; | 1699 return; |
1699 } | 1700 } |
1700 } | 1701 } |
1701 | 1702 |
1702 if (client->write->active) { | 1703 if (downstream->write->active) { |
1703 ngx_add_timer(client->write, clcf->send_timeout); | 1704 ngx_add_timer(downstream->write, clcf->send_timeout); |
1704 | 1705 |
1705 } else if (client->write->timer_set) { | 1706 } else if (downstream->write->timer_set) { |
1706 ngx_del_timer(client->write); | 1707 ngx_del_timer(downstream->write); |
1707 } | 1708 } |
1708 | 1709 |
1709 if (ngx_handle_read_event(u->peer.connection->read, 0) == NGX_ERROR) { | 1710 if (ngx_handle_read_event(upstream->read, 0) == NGX_ERROR) { |
1710 ngx_http_upstream_finalize_request(r, u, 0); | 1711 ngx_http_upstream_finalize_request(r, u, 0); |
1711 return; | 1712 return; |
1712 } | 1713 } |
1713 | 1714 |
1714 if (u->peer.connection->read->active) { | 1715 if (upstream->read->active) { |
1715 ngx_add_timer(u->peer.connection->read, u->conf->read_timeout); | 1716 ngx_add_timer(upstream->read, u->conf->read_timeout); |
1716 | 1717 |
1717 } else if (u->peer.connection->read->timer_set) { | 1718 } else if (upstream->read->timer_set) { |
1718 ngx_del_timer(u->peer.connection->read); | 1719 ngx_del_timer(upstream->read); |
1719 } | 1720 } |
1720 } | 1721 } |
1721 | 1722 |
1722 | 1723 |
1723 static ngx_int_t | 1724 static ngx_int_t |
1920 | 1921 |
1921 static void | 1922 static void |
1922 ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, | 1923 ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, |
1923 ngx_uint_t ft_type) | 1924 ngx_uint_t ft_type) |
1924 { | 1925 { |
1925 ngx_uint_t status, down; | 1926 ngx_uint_t status, state; |
1926 | 1927 |
1927 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1928 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1928 "http next upstream, %xD", ft_type); | 1929 "http next upstream, %xi", ft_type); |
1929 | 1930 |
1930 #if 0 | 1931 #if 0 |
1931 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); | 1932 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); |
1932 #endif | 1933 #endif |
1933 | 1934 |
1934 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) { | 1935 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) { |
1935 down = 0; | 1936 state = NGX_PEER_NEXT; |
1936 } else { | 1937 } else { |
1937 down = 1; | 1938 state = NGX_PEER_FAILED; |
1938 } | 1939 } |
1939 | 1940 |
1940 ngx_event_connect_peer_failed(&u->peer, down); | 1941 u->peer.free(&u->peer, u->peer.data, state); |
1941 | 1942 |
1942 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) { | 1943 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) { |
1943 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, | 1944 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, |
1944 "upstream timed out"); | 1945 "upstream timed out"); |
1945 } | 1946 } |
2001 if (u->peer.connection) { | 2002 if (u->peer.connection) { |
2002 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 2003 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
2003 "close http upstream connection: %d", | 2004 "close http upstream connection: %d", |
2004 u->peer.connection->fd); | 2005 u->peer.connection->fd); |
2005 #if (NGX_HTTP_SSL) | 2006 #if (NGX_HTTP_SSL) |
2007 | |
2006 if (u->peer.connection->ssl) { | 2008 if (u->peer.connection->ssl) { |
2007 ngx_http_upstream_ssl_shutdown(u->peer.connection, | 2009 u->peer.connection->ssl->no_wait_shutdown = 1; |
2008 &u->peer.peers->peer[u->peer.cur_peer]); | 2010 u->peer.connection->ssl->no_send_shutdown = 1; |
2011 | |
2012 (void) ngx_ssl_shutdown(u->peer.connection); | |
2009 } | 2013 } |
2010 #endif | 2014 #endif |
2015 | |
2011 ngx_close_connection(u->peer.connection); | 2016 ngx_close_connection(u->peer.connection); |
2012 } | 2017 } |
2013 | 2018 |
2014 #if 0 | 2019 #if 0 |
2015 if (u->conf->busy_lock && !u->busy_locked) { | 2020 if (u->conf->busy_lock && !u->busy_locked) { |
2052 u->state->response_time = (ms >= 0) ? ms : 0; | 2057 u->state->response_time = (ms >= 0) ? ms : 0; |
2053 } | 2058 } |
2054 | 2059 |
2055 u->finalize_request(r, rc); | 2060 u->finalize_request(r, rc); |
2056 | 2061 |
2062 u->peer.free(&u->peer, u->peer.data, 0); | |
2063 | |
2057 if (u->peer.connection) { | 2064 if (u->peer.connection) { |
2065 | |
2066 #if (NGX_HTTP_SSL) | |
2067 | |
2068 /* TODO: do not shutdown persistent connection */ | |
2069 | |
2070 if (u->peer.connection->ssl) { | |
2071 | |
2072 /* | |
2073 * We send the "close notify" shutdown alert to the upstream only | |
2074 * and do not wait its "close notify" shutdown alert. | |
2075 * It is acceptable according to the TLS standard. | |
2076 */ | |
2077 | |
2078 u->peer.connection->ssl->no_wait_shutdown = 1; | |
2079 | |
2080 (void) ngx_ssl_shutdown(u->peer.connection); | |
2081 } | |
2082 #endif | |
2083 | |
2058 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 2084 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
2059 "close http upstream connection: %d", | 2085 "close http upstream connection: %d", |
2060 u->peer.connection->fd); | 2086 u->peer.connection->fd); |
2061 #if (NGX_HTTP_SSL) | 2087 |
2062 | |
2063 /* TODO: do not shutdown persistent connection */ | |
2064 | |
2065 if (u->peer.connection->ssl) { | |
2066 ngx_http_upstream_ssl_shutdown(u->peer.connection, | |
2067 &u->peer.peers->peer[u->peer.cur_peer]); | |
2068 } | |
2069 #endif | |
2070 ngx_close_connection(u->peer.connection); | 2088 ngx_close_connection(u->peer.connection); |
2071 } | 2089 } |
2072 | 2090 |
2073 u->peer.connection = NULL; | 2091 u->peer.connection = NULL; |
2074 | 2092 |
2103 | 2121 |
2104 ngx_http_finalize_request(r, rc); | 2122 ngx_http_finalize_request(r, rc); |
2105 } | 2123 } |
2106 | 2124 |
2107 | 2125 |
2108 #if (NGX_HTTP_SSL) | |
2109 | |
2110 static void | |
2111 ngx_http_upstream_ssl_shutdown(ngx_connection_t *c, ngx_peer_t *peer) | |
2112 { | |
2113 /* lock peer mutex */ | |
2114 | |
2115 if (peer->ssl_session) { | |
2116 ngx_ssl_free_session(peer->ssl_session); | |
2117 } | |
2118 | |
2119 peer->ssl_session = ngx_ssl_get_session(c); | |
2120 | |
2121 /* unlock peer mutex */ | |
2122 | |
2123 /* | |
2124 * We send the "close notify" shutdown alert to the upstream only | |
2125 * and do not wait its "close notify" shutdown alert. | |
2126 * It is acceptable according to the TLS standard. | |
2127 */ | |
2128 | |
2129 c->ssl->no_wait_shutdown = 1; | |
2130 | |
2131 (void) ngx_ssl_shutdown(c); | |
2132 } | |
2133 | |
2134 #endif | |
2135 | |
2136 | |
2137 static ngx_int_t | 2126 static ngx_int_t |
2138 ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, | 2127 ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, |
2139 ngx_uint_t offset) | 2128 ngx_uint_t offset) |
2140 { | 2129 { |
2141 ngx_table_elt_t **ph; | 2130 ngx_table_elt_t **ph; |
2593 | 2582 |
2594 | 2583 |
2595 static char * | 2584 static char * |
2596 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) | 2585 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) |
2597 { | 2586 { |
2598 char *rv; | 2587 char *rv; |
2599 void *mconf; | 2588 void *mconf; |
2600 ngx_str_t *value; | 2589 ngx_str_t *value; |
2601 ngx_url_t u; | 2590 ngx_url_t u; |
2602 ngx_uint_t i, j, m, n; | 2591 ngx_uint_t m; |
2603 ngx_conf_t pcf; | 2592 ngx_conf_t pcf; |
2604 ngx_peers_t **peers; | 2593 ngx_http_module_t *module; |
2605 ngx_http_module_t *module; | 2594 ngx_http_conf_ctx_t *ctx, *http_ctx; |
2606 ngx_http_conf_ctx_t *ctx; | 2595 ngx_http_upstream_srv_conf_t *uscf; |
2607 ngx_http_upstream_srv_conf_t *uscf; | 2596 |
2597 ngx_memzero(&u, sizeof(ngx_url_t)); | |
2598 | |
2599 value = cf->args->elts; | |
2600 u.host = value[1]; | |
2601 u.upstream = 1; | |
2602 u.no_resolve = 1; | |
2603 | |
2604 uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE | |
2605 |NGX_HTTP_UPSTREAM_WEIGHT | |
2606 |NGX_HTTP_UPSTREAM_MAX_FAILS | |
2607 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | |
2608 |NGX_HTTP_UPSTREAM_DOWN | |
2609 |NGX_HTTP_UPSTREAM_BACKUP); | |
2610 if (uscf == NULL) { | |
2611 return NGX_CONF_ERROR; | |
2612 } | |
2613 | |
2608 | 2614 |
2609 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); | 2615 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
2610 if (ctx == NULL) { | 2616 if (ctx == NULL) { |
2611 return NGX_CONF_ERROR; | 2617 return NGX_CONF_ERROR; |
2612 } | 2618 } |
2613 | 2619 |
2614 ngx_memzero(&u, sizeof(ngx_url_t)); | 2620 http_ctx = cf->ctx; |
2615 | 2621 ctx->main_conf = http_ctx->main_conf; |
2616 value = cf->args->elts; | |
2617 u.host = value[1]; | |
2618 | |
2619 uscf = ngx_http_upstream_add(cf, &u); | |
2620 if (uscf == NULL) { | |
2621 return NGX_CONF_ERROR; | |
2622 } | |
2623 | 2622 |
2624 /* the upstream{}'s srv_conf */ | 2623 /* the upstream{}'s srv_conf */ |
2625 | 2624 |
2626 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | 2625 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); |
2627 if (ctx->srv_conf == NULL) { | 2626 if (ctx->srv_conf == NULL) { |
2628 return NGX_CONF_ERROR; | 2627 return NGX_CONF_ERROR; |
2629 } | 2628 } |
2630 | 2629 |
2631 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf; | 2630 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf; |
2632 | 2631 |
2632 uscf->srv_conf = ctx->srv_conf; | |
2633 | |
2633 | 2634 |
2634 /* the upstream{}'s loc_conf */ | 2635 /* the upstream{}'s loc_conf */ |
2635 | 2636 |
2636 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | 2637 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); |
2637 if (ctx->loc_conf == NULL) { | 2638 if (ctx->loc_conf == NULL) { |
2642 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { | 2643 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { |
2643 continue; | 2644 continue; |
2644 } | 2645 } |
2645 | 2646 |
2646 module = ngx_modules[m]->ctx; | 2647 module = ngx_modules[m]->ctx; |
2648 | |
2649 if (module->create_srv_conf) { | |
2650 mconf = module->create_srv_conf(cf); | |
2651 if (mconf == NULL) { | |
2652 return NGX_CONF_ERROR; | |
2653 } | |
2654 | |
2655 ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; | |
2656 } | |
2647 | 2657 |
2648 if (module->create_loc_conf) { | 2658 if (module->create_loc_conf) { |
2649 mconf = module->create_loc_conf(cf); | 2659 mconf = module->create_loc_conf(cf); |
2650 if (mconf == NULL) { | 2660 if (mconf == NULL) { |
2651 return NGX_CONF_ERROR; | 2661 return NGX_CONF_ERROR; |
2674 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 2684 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2675 "no servers are inside upstream"); | 2685 "no servers are inside upstream"); |
2676 return NGX_CONF_ERROR; | 2686 return NGX_CONF_ERROR; |
2677 } | 2687 } |
2678 | 2688 |
2679 peers = uscf->servers->elts; | |
2680 | |
2681 if (uscf->servers->nelts == 1) { | |
2682 uscf->peers = peers[0]; | |
2683 } | |
2684 | |
2685 n = 0; | |
2686 | |
2687 for (i = 0; i < uscf->servers->nelts; i++) { | |
2688 n += peers[i]->number; | |
2689 } | |
2690 | |
2691 uscf->peers = ngx_pcalloc(cf->pool, | |
2692 sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (n - 1)); | |
2693 if (uscf->peers == NULL) { | |
2694 return NGX_CONF_ERROR; | |
2695 } | |
2696 | |
2697 uscf->peers->number = n; | |
2698 | |
2699 n = 0; | |
2700 | |
2701 for (i = 0; i < uscf->servers->nelts; i++) { | |
2702 for (j = 0; j < peers[i]->number; j++) { | |
2703 uscf->peers->peer[n++] = peers[i]->peer[j]; | |
2704 } | |
2705 } | |
2706 | |
2707 return rv; | 2689 return rv; |
2708 } | 2690 } |
2709 | 2691 |
2710 | 2692 |
2711 static char * | 2693 static char * |
2712 ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 2694 ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2713 { | 2695 { |
2714 ngx_http_upstream_srv_conf_t *uscf = conf; | 2696 ngx_http_upstream_srv_conf_t *uscf = conf; |
2715 | 2697 |
2716 ngx_str_t *value; | 2698 time_t fail_timeout; |
2717 ngx_url_t u; | 2699 ngx_str_t *value, s; |
2718 ngx_int_t weight; | 2700 ngx_url_t u; |
2719 ngx_uint_t i; | 2701 ngx_int_t weight, max_fails; |
2720 ngx_peers_t **peers; | 2702 ngx_uint_t i; |
2703 ngx_http_upstream_server_t *us; | |
2721 | 2704 |
2722 if (uscf->servers == NULL) { | 2705 if (uscf->servers == NULL) { |
2723 uscf->servers = ngx_array_create(cf->pool, 4, sizeof(ngx_peers_t *)); | 2706 uscf->servers = ngx_array_create(cf->pool, 4, |
2707 sizeof(ngx_http_upstream_server_t)); | |
2724 if (uscf->servers == NULL) { | 2708 if (uscf->servers == NULL) { |
2725 return NGX_CONF_ERROR; | 2709 return NGX_CONF_ERROR; |
2726 } | 2710 } |
2727 } | 2711 } |
2728 | 2712 |
2729 peers = ngx_array_push(uscf->servers); | 2713 us = ngx_array_push(uscf->servers); |
2730 if (peers == NULL) { | 2714 if (us == NULL) { |
2731 return NGX_CONF_ERROR; | 2715 return NGX_CONF_ERROR; |
2732 } | 2716 } |
2717 | |
2718 ngx_memzero(us, sizeof(ngx_http_upstream_server_t)); | |
2733 | 2719 |
2734 value = cf->args->elts; | 2720 value = cf->args->elts; |
2735 | 2721 |
2736 ngx_memzero(&u, sizeof(ngx_url_t)); | 2722 ngx_memzero(&u, sizeof(ngx_url_t)); |
2737 | 2723 |
2746 | 2732 |
2747 return NGX_CONF_ERROR; | 2733 return NGX_CONF_ERROR; |
2748 } | 2734 } |
2749 | 2735 |
2750 weight = 1; | 2736 weight = 1; |
2751 | 2737 max_fails = 1; |
2752 if (cf->args->nelts == 3) { | 2738 fail_timeout = 10; |
2753 | 2739 |
2754 value = &value[2]; | 2740 for (i = 2; i < cf->args->nelts; i++) { |
2755 | 2741 |
2756 if (ngx_strncmp(value->data, "weight=", 7) == 0) { | 2742 if (ngx_strncmp(value[i].data, "weight=", 7) == 0) { |
2757 | 2743 |
2758 weight = ngx_atoi(&value->data[7], value->len - 7); | 2744 if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) { |
2745 goto invalid; | |
2746 } | |
2747 | |
2748 weight = ngx_atoi(&value[i].data[7], value[i].len - 7); | |
2759 | 2749 |
2760 if (weight == NGX_ERROR || weight == 0) { | 2750 if (weight == NGX_ERROR || weight == 0) { |
2761 goto invalid; | 2751 goto invalid; |
2762 } | 2752 } |
2763 | 2753 |
2764 } else { | 2754 continue; |
2765 goto invalid; | 2755 } |
2766 } | 2756 |
2767 } | 2757 if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) { |
2768 | 2758 |
2769 for (i = 0; i < u.peers->number; i++) { | 2759 if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) { |
2770 u.peers->peer[i].weight = weight; | 2760 goto invalid; |
2771 u.peers->peer[i].current_weight = weight; | 2761 } |
2772 u.peers->peer[i].max_fails = NGX_CONF_UNSET_UINT; | 2762 |
2773 u.peers->peer[i].fail_timeout = NGX_CONF_UNSET; | 2763 max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10); |
2774 } | 2764 |
2775 | 2765 if (max_fails == NGX_ERROR) { |
2776 *peers = u.peers; | 2766 goto invalid; |
2767 } | |
2768 | |
2769 continue; | |
2770 } | |
2771 | |
2772 if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) { | |
2773 | |
2774 if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) { | |
2775 goto invalid; | |
2776 } | |
2777 | |
2778 s.len = value[i].len - 13; | |
2779 s.data = &value[i].data[13]; | |
2780 | |
2781 fail_timeout = ngx_parse_time(&s, 1); | |
2782 | |
2783 if (fail_timeout < 0) { | |
2784 goto invalid; | |
2785 } | |
2786 | |
2787 continue; | |
2788 } | |
2789 | |
2790 if (ngx_strncmp(value[i].data, "down", 4) == 0) { | |
2791 | |
2792 if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) { | |
2793 goto invalid; | |
2794 } | |
2795 | |
2796 us->down = 1; | |
2797 | |
2798 continue; | |
2799 } | |
2800 | |
2801 goto invalid; | |
2802 } | |
2803 | |
2804 us->addrs = u.addrs; | |
2805 us->naddrs = u.naddrs; | |
2806 us->weight = weight; | |
2807 us->max_fails = max_fails; | |
2808 us->fail_timeout = fail_timeout; | |
2777 | 2809 |
2778 return NGX_CONF_OK; | 2810 return NGX_CONF_OK; |
2779 | 2811 |
2780 invalid: | 2812 invalid: |
2781 | 2813 |
2782 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", value); | 2814 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2815 "invalid parameter \"%V\"", &value[i]); | |
2783 | 2816 |
2784 return NGX_CONF_ERROR; | 2817 return NGX_CONF_ERROR; |
2785 } | 2818 } |
2786 | 2819 |
2787 | 2820 |
2788 ngx_http_upstream_srv_conf_t * | 2821 ngx_http_upstream_srv_conf_t * |
2789 ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u) | 2822 ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) |
2790 { | 2823 { |
2791 ngx_uint_t i; | 2824 ngx_uint_t i; |
2825 ngx_http_upstream_server_t *us; | |
2792 ngx_http_upstream_srv_conf_t *uscf, **uscfp; | 2826 ngx_http_upstream_srv_conf_t *uscf, **uscfp; |
2793 ngx_http_upstream_main_conf_t *umcf; | 2827 ngx_http_upstream_main_conf_t *umcf; |
2794 | 2828 |
2795 if (u->upstream) { | 2829 if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) { |
2830 | |
2796 if (ngx_parse_url(cf, u) != NGX_OK) { | 2831 if (ngx_parse_url(cf, u) != NGX_OK) { |
2797 if (u->err) { | 2832 if (u->err) { |
2798 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 2833 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2799 "%s in upstream \"%V\"", u->err, &u->url); | 2834 "%s in upstream \"%V\"", u->err, &u->url); |
2800 } | 2835 } |
2801 | 2836 |
2802 return NULL; | 2837 return NULL; |
2803 } | 2838 } |
2804 | |
2805 if (u->peers) { | |
2806 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t)); | |
2807 if (uscf == NULL) { | |
2808 return NULL; | |
2809 } | |
2810 | |
2811 uscf->peers = u->peers; | |
2812 | |
2813 return uscf; | |
2814 } | |
2815 } | 2839 } |
2816 | 2840 |
2817 umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module); | 2841 umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module); |
2818 | 2842 |
2819 uscfp = umcf->upstreams.elts; | 2843 uscfp = umcf->upstreams.elts; |
2820 | 2844 |
2821 for (i = 0; i < umcf->upstreams.nelts; i++) { | 2845 for (i = 0; i < umcf->upstreams.nelts; i++) { |
2822 if (uscfp[i]->host.len != u->host.len) { | 2846 if (uscfp[i]->host.len != u->host.len |
2847 || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) | |
2848 != 0) | |
2849 { | |
2823 continue; | 2850 continue; |
2824 } | 2851 } |
2825 | 2852 |
2826 if (ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) | 2853 if ((flags & NGX_HTTP_UPSTREAM_CREATE) |
2827 == 0) | 2854 && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE)) |
2828 { | 2855 { |
2829 return uscfp[i]; | 2856 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2830 } | 2857 "duplicate upstream \"%V\"", &u->host); |
2858 return NULL; | |
2859 } | |
2860 | |
2861 if (uscfp[i]->port == 0 && u->portn && !u->no_port) { | |
2862 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
2863 "upstream \"%V\" port %d is ignored", | |
2864 &u->host, u->portn); | |
2865 } | |
2866 | |
2867 return uscfp[i]; | |
2831 } | 2868 } |
2832 | 2869 |
2833 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t)); | 2870 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t)); |
2834 if (uscf == NULL) { | 2871 if (uscf == NULL) { |
2835 return NULL; | 2872 return NULL; |
2836 } | 2873 } |
2837 | 2874 |
2875 uscf->flags = flags; | |
2838 uscf->host = u->host; | 2876 uscf->host = u->host; |
2839 uscf->file_name = cf->conf_file->file.name; | 2877 uscf->file_name = cf->conf_file->file.name; |
2840 uscf->line = cf->conf_file->line; | 2878 uscf->line = cf->conf_file->line; |
2841 uscf->port = u->default_portn; | 2879 uscf->port = u->portn; |
2880 | |
2881 if (u->naddrs == 1) { | |
2882 uscf->servers = ngx_array_create(cf->pool, 1, | |
2883 sizeof(ngx_http_upstream_server_t)); | |
2884 if (uscf->servers == NULL) { | |
2885 return NGX_CONF_ERROR; | |
2886 } | |
2887 | |
2888 us = ngx_array_push(uscf->servers); | |
2889 if (us == NULL) { | |
2890 return NGX_CONF_ERROR; | |
2891 } | |
2892 | |
2893 ngx_memzero(us, sizeof(ngx_http_upstream_server_t)); | |
2894 | |
2895 us->addrs = u->addrs; | |
2896 us->naddrs = u->naddrs; | |
2897 } | |
2842 | 2898 |
2843 uscfp = ngx_array_push(&umcf->upstreams); | 2899 uscfp = ngx_array_push(&umcf->upstreams); |
2844 if (uscfp == NULL) { | 2900 if (uscfp == NULL) { |
2845 return NULL; | 2901 return NULL; |
2846 } | 2902 } |
2879 | 2935 |
2880 ngx_uint_t i; | 2936 ngx_uint_t i; |
2881 ngx_array_t headers_in; | 2937 ngx_array_t headers_in; |
2882 ngx_hash_key_t *hk; | 2938 ngx_hash_key_t *hk; |
2883 ngx_hash_init_t hash; | 2939 ngx_hash_init_t hash; |
2940 ngx_http_upstream_init_pt init; | |
2884 ngx_http_upstream_header_t *header; | 2941 ngx_http_upstream_header_t *header; |
2885 ngx_http_upstream_srv_conf_t **uscfp; | 2942 ngx_http_upstream_srv_conf_t **uscfp; |
2886 | 2943 |
2887 uscfp = umcf->upstreams.elts; | 2944 uscfp = umcf->upstreams.elts; |
2888 | 2945 |
2889 for (i = 0; i < umcf->upstreams.nelts; i++) { | 2946 for (i = 0; i < umcf->upstreams.nelts; i++) { |
2890 if (uscfp[i]->peers) { | 2947 |
2891 continue; | 2948 init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream: |
2892 } | 2949 ngx_http_upstream_init_round_robin; |
2893 | 2950 |
2894 uscfp[i]->peers = ngx_inet_resolve_peer(cf, &uscfp[i]->host, | 2951 if (init(cf, uscfp[i]) != NGX_OK) { |
2895 uscfp[i]->port); | |
2896 if (uscfp[i]->peers == NULL) { | |
2897 return NGX_CONF_ERROR; | 2952 return NGX_CONF_ERROR; |
2898 } | 2953 } |
2899 | 2954 } |
2900 if (uscfp[i]->peers == NGX_CONF_ERROR) { | 2955 |
2901 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | 2956 |
2902 "upstream host \"%V\" is not found in %s:%ui", | 2957 /* upstream_headers_in_hash */ |
2903 &uscfp[i]->host, uscfp[i]->file_name.data, | |
2904 uscfp[i]->line); | |
2905 return NGX_CONF_ERROR; | |
2906 } | |
2907 } | |
2908 | |
2909 | 2958 |
2910 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) | 2959 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) |
2911 != NGX_OK) | 2960 != NGX_OK) |
2912 { | 2961 { |
2913 return NGX_CONF_ERROR; | 2962 return NGX_CONF_ERROR; |