mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Allow for a simple socket check in addition to the
higher level protocol-level checks for backends... Not sure if it makes sense to do both or not... Comments? git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1516930 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -1003,7 +1003,9 @@ ProxyPass /mirror/foo http://backend.example.com
|
||||
<tr><td>ping</td>
|
||||
<td>0</td>
|
||||
<td>Ping property tells the webserver to "test" the connection to
|
||||
the backend before forwarding the request. For AJP, it causes
|
||||
the backend before forwarding the request. For negative values
|
||||
the test is a simple socket check, for positive values it's
|
||||
a more functional check, dependent upon the protocol. For AJP, it causes
|
||||
<module>mod_proxy_ajp</module>to send a <code>CPING</code>
|
||||
request on the ajp13 connection (implemented on Tomcat 3.3.2+, 4.1.28+
|
||||
and 5.0.13+). For HTTP, it causes <module>mod_proxy_http</module>
|
||||
|
@@ -233,7 +233,7 @@ static const char *set_worker_param(apr_pool_t *p,
|
||||
*/
|
||||
if (ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS)
|
||||
return "Ping/Pong timeout has wrong format";
|
||||
if (timeout < 1000)
|
||||
if (timeout < 1000 && timeout >= 0)
|
||||
return "Ping/Pong timeout must be at least one millisecond";
|
||||
worker->s->ping_timeout = timeout;
|
||||
worker->s->ping_timeout_set = 1;
|
||||
|
@@ -972,6 +972,13 @@ PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc,
|
||||
APR_DECLARE_OPTIONAL_FN(int, ap_proxy_clear_connection,
|
||||
(request_rec *r, apr_table_t *headers));
|
||||
|
||||
|
||||
/**
|
||||
* @param socket socket to test
|
||||
* @return TRUE if socket is connected/active
|
||||
*/
|
||||
PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket);
|
||||
|
||||
#define PROXY_LBMETHOD "proxylbmethod"
|
||||
|
||||
/* The number of dynamic workers that can be added when reconfiguring.
|
||||
|
@@ -759,22 +759,35 @@ static int proxy_ajp_handler(request_rec *r, proxy_worker *worker,
|
||||
|
||||
/* Handle CPING/CPONG */
|
||||
if (worker->s->ping_timeout_set) {
|
||||
status = ajp_handle_cping_cpong(backend->sock, r,
|
||||
worker->s->ping_timeout);
|
||||
/*
|
||||
* In case the CPING / CPONG failed for the first time we might be
|
||||
* just out of luck and got a faulty backend connection, but the
|
||||
* backend might be healthy nevertheless. So ensure that the backend
|
||||
* TCP connection gets closed and try it once again.
|
||||
*/
|
||||
if (status != APR_SUCCESS) {
|
||||
backend->close = 1;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00897)
|
||||
"cping/cpong failed to %pI (%s)",
|
||||
worker->cp->addr, worker->s->hostname);
|
||||
status = HTTP_SERVICE_UNAVAILABLE;
|
||||
retry++;
|
||||
continue;
|
||||
if (worker->s->ping_timeout_set < 0) {
|
||||
if (!ap_proxy_is_socket_connected(backend->sock)) {
|
||||
backend->close = 1;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO()
|
||||
"socket check failed to %pI (%s)",
|
||||
worker->cp->addr, worker->s->hostname);
|
||||
status = HTTP_SERVICE_UNAVAILABLE;
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = ajp_handle_cping_cpong(backend->sock, r,
|
||||
worker->s->ping_timeout);
|
||||
/*
|
||||
* In case the CPING / CPONG failed for the first time we might be
|
||||
* just out of luck and got a faulty backend connection, but the
|
||||
* backend might be healthy nevertheless. So ensure that the backend
|
||||
* TCP connection gets closed and try it once again.
|
||||
*/
|
||||
if (status != APR_SUCCESS) {
|
||||
backend->close = 1;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00897)
|
||||
"cping/cpong failed to %pI (%s)",
|
||||
worker->cp->addr, worker->s->hostname);
|
||||
status = HTTP_SERVICE_UNAVAILABLE;
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Step Three: Process the Request */
|
||||
|
@@ -1975,13 +1975,25 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
|
||||
}
|
||||
}
|
||||
|
||||
/* Step Three-and-a-Half: See if the socket is still connected (if desired) */
|
||||
if (worker->s->ping_timeout_set && worker->s->ping_timeout < 0 &&
|
||||
!ap_proxy_is_socket_connected(backend->sock)) {
|
||||
backend->close = 1;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r, APLOGNO()
|
||||
"socket check failed to %pI (%s)",
|
||||
worker->cp->addr, worker->s->hostname);
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Step Four: Send the Request
|
||||
* On the off-chance that we forced a 100-Continue as a
|
||||
* kinda HTTP ping test, allow for retries
|
||||
*/
|
||||
if ((status = ap_proxy_http_request(p, r, backend, worker,
|
||||
conf, uri, locurl, server_portstr)) != OK) {
|
||||
if ((status == HTTP_SERVICE_UNAVAILABLE) && worker->s->ping_timeout_set) {
|
||||
if ((status == HTTP_SERVICE_UNAVAILABLE) && worker->s->ping_timeout_set &&
|
||||
worker->s->ping_timeout > 0) {
|
||||
backend->close = 1;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r, APLOGNO(01115)
|
||||
"HTTP: 100-Continue failed to %pI (%s)",
|
||||
|
@@ -2245,7 +2245,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
|
||||
#endif
|
||||
|
||||
#if USE_ALTERNATE_IS_CONNECTED && defined(APR_MSG_PEEK)
|
||||
static int is_socket_connected(apr_socket_t *socket)
|
||||
PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket)
|
||||
{
|
||||
apr_pollfd_t pfds[1];
|
||||
apr_status_t status;
|
||||
@@ -2283,7 +2283,7 @@ static int is_socket_connected(apr_socket_t *socket)
|
||||
|
||||
}
|
||||
#else
|
||||
static int is_socket_connected(apr_socket_t *sock)
|
||||
PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket)
|
||||
|
||||
{
|
||||
apr_size_t buffer_len = 1;
|
||||
@@ -2466,7 +2466,7 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
|
||||
(proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
|
||||
|
||||
if (conn->sock) {
|
||||
if (!(connected = is_socket_connected(conn->sock))) {
|
||||
if (!(connected = ap_proxy_is_socket_connected(conn->sock))) {
|
||||
socket_cleanup(conn);
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00951)
|
||||
"%s: backend socket is disconnected.",
|
||||
|
Reference in New Issue
Block a user