You are viewing a plain text version of this content. The canonical link for it is here.
Posted to apache-bugdb@apache.org by Ted Keller <ke...@bfg.com> on 2000/05/11 01:20:02 UTC

Re: mod_proxy/5972: Proxy cannot connect to many IIS 4.0 sites

The following reply was made to PR mod_proxy/5972; it has been noted by GNATS.

From: Ted Keller <ke...@bfg.com>
To: Marc Slemko <ma...@znep.com>
Cc: Apache bugs database <ap...@apache.org>
Subject: Re: mod_proxy/5972: Proxy cannot connect to many IIS 4.0 sites
Date: Wed, 10 May 2000 19:17:13 -0400 (EDT)

 Marc,
 
 I've solved the problem.....  Apache mods are attached.
 
 The problem is still caused by some internet sites not properly closing
 connections (missing <fin>) which causes apache to go into a long wait
 - waiting for the read to complete.
 
 
 There are three issues that I had to deal with.
 
 1. Apache normally reads data from the remote server until it receives an
 EOF - or unitl a "data block" is full prior to issuing hte data to the
 client.  Apache wants to reblock the data for more efficient tcp
 transmissions - wanting to send larger blocks instead of the blocks read
 from the internet.  Patch 1 then deals with flushing the data to the
 client as it is received from the net - thus ignoring the reblocking
 features.  This make apache appear to have equivalent performance as a
 client running native to one of these sites.
 
 2. Apache also tends to want to buffer up the receive side - performing
 multiple network reads to fill a block prior to passing it back to the
 internal caching routines and then sending it on to the client.  This does
 have server perfrormance ramifications - since without this buffering, the
 apache caching routines now have to work a bit harder.  The second patch
 places the apache into a "non" buffered read mode - such that each block
 is passed back as it is received.  No multi-buffering for performance is
 performed.  So I work my disks a bit harder....  
 
 This then allows the client to get the last block of data as issued by the
 remote server.
 
 3.  The third item is to then ratchet down the connection timeouts.
 Apache will still try to read that missing EOF.  But since the EOF never
 arrives, the process will hang until the timeout is received.  In standard
 configurations - this is 300 seconds.  If I have a particularly bad site -
 this will consume a number of processes until this timeout is reached.  By
 reducing this to about 60 seconds, we see a reasonable compromise.  Note -
 if this problem tends to poliferate, we may have to increase the number of
 available process slots for the apache to run in.
 
 Note - the attached mods also contain fixes to allow apache to work better
 with socks5.  These are limited to extra close statements in the code.
 
 The important mods are the ap_bflush additions and the modification of the
 flags on the input side to permit non-buffered reading.
 
 
 Here are the diff files for proxy_http.c (1.3.9)
 
 *** proxy_http.c.orig	Sat Sep 18 22:46:53 1999
 --- proxy_http.c	Fri May  5 22:21:29 2000
 ***************
 *** 289,305 ****
       }
   #endif
       if (i == -1) {
 ! 	if (proxyhost != NULL)
   	    return DECLINED;	/* try again another way */
 ! 	else
   	    return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
   				"Could not connect to remote machine: ",
   				strerror(errno), NULL));
       }
   
       clear_connection(r->pool, r->headers_in);	/* Strip connection-based headers */
   
 !     f = ap_bcreate(p, B_RDWR | B_SOCKET);
       ap_bpushfd(f, sock, sock);
   
       ap_hard_timeout("proxy send", r);
 --- 289,308 ----
       }
   #endif
       if (i == -1) {
 ! 	if (proxyhost != NULL) {
 ! 	    ap_pclosesocket(p,sock);
   	    return DECLINED;	/* try again another way */
 ! 	}else {
 ! 	    ap_pclosesocket(p,sock);
   	    return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
   				"Could not connect to remote machine: ",
   				strerror(errno), NULL));
 + 	}
       }
   
       clear_connection(r->pool, r->headers_in);	/* Strip connection-based headers */
   
 !     f = ap_bcreate(p, B_RDWR | B_SOCKET); 
       ap_bpushfd(f, sock, sock);
   
       ap_hard_timeout("proxy send", r);
 ***************
 *** 370,380 ****
 --- 373,385 ----
   	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
   		     "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)",
   		     proxyhost ? proxyhost : desthost, len);
 + 	ap_pclosesocket(p,sock);
   	return ap_proxyerror(r, HTTP_BAD_GATEWAY,
   			     "Error reading from remote server");
       } else if (len == 0) {
   	ap_bclose(f);
   	ap_kill_timeout(r);
 + 	ap_pclosesocket(p,sock);
   	return ap_proxyerror(r, HTTP_BAD_GATEWAY,
   			     "Document contains no data");
       }
 ***************
 *** 391,396 ****
 --- 396,402 ----
   	if (buffer[5] != '1' || buffer[len - 1] != '\n') {
   	    ap_bclose(f);
   	    ap_kill_timeout(r);
 + 	    ap_pclosesocket(p,sock);
   	    return HTTP_BAD_GATEWAY;
   	}
   	backasswards = 0;
 ***************
 *** 435,442 ****
   	}
   
   	clear_connection(p, resp_hdrs);	/* Strip Connection hdrs */
 !     }
 !     else {
   /* an http/0.9 response */
   	backasswards = 1;
   	r->status = 200;
 --- 441,447 ----
   	}
   
   	clear_connection(p, resp_hdrs);	/* Strip Connection hdrs */
 !     } else {
   /* an http/0.9 response */
   	backasswards = 1;
   	r->status = 200;
 ***************
 *** 476,481 ****
 --- 481,487 ----
       i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
       if (i != DECLINED) {
   	ap_bclose(f);
 + 	ap_pclosesocket(p,sock);
   	return i;
       }
   
 ***************
 *** 515,520 ****
 --- 521,527 ----
   	    c = ap_proxy_cache_error(c);
   	}
       }
 +     ap_bflush(r->connection->client);
       ap_kill_timeout(r);
   
   #ifdef CHARSET_EBCDIC
 ***************
 *** 539,543 ****
 --- 546,551 ----
       ap_bclose(f);
   
       ap_proxy_garbage_coll(r);
 +     ap_pclosesocket(p,sock);
       return OK;
   }
 
 
 mods for proxy_util.c
 
 *** proxy_util.c.orig	Sat May  1 13:02:29 1999
 --- proxy_util.c	Fri May  5 22:57:36 2000
 ***************
 *** 540,545 ****
 --- 540,549 ----
        * or (after the client aborted) while we can successfully
        * read and finish the configured cache_completion.
        */
 +     /*
 +      * clear the buffer read flag
 +      */
 +     f->flags=f->flags & ~B_RD;
       for (ok = 1; ok; ) {
           if (alternate_timeouts)
               ap_hard_timeout("proxy recv body from upstream server", r);
 ***************
 *** 583,588 ****
 --- 587,593 ----
                   ap_soft_timeout("proxy send body", r);
   
               w = ap_bwrite(con->client, &buf[o], n);
 + 	    ap_bflush(con->client);
   
               if (alternate_timeouts)
                   ap_kill_timeout(r);
 ***************
 *** 1238,1252 ****
   int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r)
   {
       int i;
   
       ap_hard_timeout("proxy connect", r);
       do {
   	i = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in));
   #ifdef WIN32
   	if (i == SOCKET_ERROR)
   	    errno = WSAGetLastError();
   #endif /* WIN32 */
 !     } while (i == -1 && errno == EINTR);
       if (i == -1) {
   	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
   		     "proxy connect to %s port %d failed",
 --- 1243,1265 ----
   int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r)
   {
       int i;
 +     int connect_count;
   
 + #ifndef CONNECT_RETRY
 + #define CONNECT_RETRY 1
 + #endif /* CONNECT_RETRY */
 + 
 +     connect_count=0;
 + 
       ap_hard_timeout("proxy connect", r);
       do {
   	i = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in));
 + 	connect_count++;
   #ifdef WIN32
   	if (i == SOCKET_ERROR)
   	    errno = WSAGetLastError();
   #endif /* WIN32 */
 !     } while (i == -1 && errno == EINTR || i == -1 && errno == ECONNREFUSED && connect_count < CONNECT_RETRY);
       if (i == -1) {
   	ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
   		     "proxy connect to %s port %d failed",
 
 
 
 On Thu, 27 Apr 2000, Ted Keller wrote:
 
 > Mark,
 > 
 > I'm still looking at this.  What I've discovered is as follows....
 > 
 > Certain iis 4.x sites are not sending the <fin> packets when closing the
 > tcp connection.  I've verified this with the site operators.  My
 > understanding of the tcp protocol is this packet is required to close the
 > session.  Once closed, the read in apache should get the end of file
 > indicator - thus allowing the data to be sent to the client.
 > 
 > Is my understanding correct?
 > 
 > I'm still curious as to why you can't reproduce the problem.  Can you
 > provide any input?
 > 
 > tnx
 > ted keller
 > 
 > 
 > On Fri, 14 Apr 2000, Marc Slemko wrote:
 > 
 > > On Fri, 14 Apr 2000, Ted Keller wrote:
 > > 
 > > > Marc,
 > > > 
 > > > Restored buff.c to original mode.  Turned off http 1.1 processing in the
 > > > browser.  Hit support.dell.com site - browser appears to die (were back to
 > > > using default timeouts).
 > > 
 > > So you mean just going to http://support.dell.com/ ?
 > > 
 > > Have you tried a more recent version of Apache?
 > > 
 > > Do other browsers have the same problem?
 > > 
 > > I'm having trouble reproducing it.
 > > 
 > > > 
 > > > Netstat -n reports 
 > > > xxx.xxx.xxx.xxx.59939  143.166.82.190.80    17152      0 64240      0
 > > > ESTABLISHED
 > > >  
 > > > all other connections to that site are in a FIN_WAIT mode.
 > > > 
 > > > With the buff.c modification, and http 1.1 support turned off, performance
 > > > improves to near acceptable. However, we still wait for the connection to
 > > > close which never does until the short timeout is reached.
 > > > 
 > > > Direct connections show this pages loads in about 2 seconds.
 > > > With the "fix" page loads in about 30 seconds
 > > > Without the "fix" page fails to load.
 > > > 
 > > > Obviously I like the 2 second loads....
 > > > 
 > > > 
 > > > On Fri, 14 Apr 2000, Marc Slemko wrote:
 > > > 
 > > > > On 14 Apr 2000, Ted Keller wrote:
 > > > > 
 > > > > > The following reply was made to PR mod_proxy/5972; it has been noted by GNATS.
 > > > > > 
 > > > > > From: Ted Keller <ke...@bfg.com>
 > > > > > To: submit@bugz.apache.org, apache-bugdb@apache.org
 > > > > > Cc:  
 > > > > > Subject: Re: mod_proxy/5972: Proxy cannot connect to many IIS 4.0 sites
 > > > > > Date: Fri, 14 Apr 2000 18:17:41 -0400 (EDT)
 > > > > > 
 > > > > >  Further investigations have shown the following....
 > > > > >  
 > > > > >  1. All pages that are failing are http 1.1 type pages.
 > > > > >  
 > > > > >  2. IE5 has an option, Use HTTP 1.1 through proxy connections, which, if
 > > > > >  checked, seems to help.  Note - netscape 4 does not have an equivalent
 > > > > >  selectable feature.
 > > > > 
 > > > > What if you disable all HTTP/1.1 support in IE?
 > > > > 
 > > > > >  
 > > > > >  3. A modification in buff.c as follows... forces "short" timeouts for
 > > > > >  sites that do NOT close connections at the end of a block transmission.
 > > > > >  The modification below set this to 8 seconds - this should really be a
 > > > > >  configurable parameter.
 > > > > >  
 > > > > >  With these, we are starting to see acceptable performance for these "bad"
 > > > > >  sites.
 > > > > 
 > > > > Refresh my memory; can you give me a URL that exhibits this problem?
 > > > > 
 > > > 
 > > > 
 > > > support.dell.com
 > > > 
 > > > We have also seen this on...
 > > > 
 > > > www.bell.ca
 > > > www.winntmag.com
 > > > www.nai.com
 > > > 
 > > > > Thanks.
 > > > > 
 > > > 
 > > 
 > 
 >