httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tony Finch <...@dotat.at>
Subject Re: Zen regarding accept filters
Date Sun, 30 Jul 2000 04:59:58 GMT
OK, here's what I hope is the final patch. It uses "dataready" by
default but it can be persuaded to use "httpready" if you really want.
It also handles the case where the accept filter is not available in
the kernel (should it be less noisy about this?). And, as a bonus, it
even comes with documentation!

I decided that fixing "httpready" to properly matching an HTTP request
is too painful and that this was a fair compromise. I'm also slightly
worried about the opportunity for clients to stuff the server's socket
buffers with incomplete HTTP requests which is another reason for not
using "httpready". There remains one more issue which I am unsure
about and that is that there seems to be no timeout on these
un-accepted connections for either filter.

Tony.
-- 
en oeccget g mtcaa    f.a.n.finch
v spdlkishrhtewe y    dot@dotat.at
eatp o v eiti i d.    fanf@covalent.net


? diff
? src/main/http_main.c.diff
Index: htdocs/manual/misc/perf-bsd44.html
===================================================================
RCS file: /home/cvs/httpd-docs-1.3/htdocs/manual/misc/perf-bsd44.html,v
retrieving revision 1.13
diff -u -r1.13 perf-bsd44.html
--- htdocs/manual/misc/perf-bsd44.html	1998/09/17 14:14:53	1.13
+++ htdocs/manual/misc/perf-bsd44.html	2000/07/30 04:28:28
@@ -242,6 +242,70 @@
 often maxed out.</BLOCKQUOTE>
 <P>
 
+<A NAME="accf">
+<H2>Accept filtering on FreeBSD</H2>
+</A>
+
+<P>
+
+Versions of FreeBSD from August 2000 onwards include a feature called
+&quot;accept filters&quot; which delay the return from accept() until
+a condition has been met, e.g. an HTTP request has arrived. This
+postpones the requirement for a child process to handle the new
+connection which therefore increases the number of connections that a
+given number of child processes can handle. It also allows a child
+process to accomplish more immediately after accept() returns (because
+the request is already available to be read) so there is less context
+switching.
+
+<P>
+
+There are two filters in FreeBSD at the time of writing:
+&quot;dataready&quot; and &quot;httpready&quot;. The former just waits
+for the first packet to arrive from the client; the latter waits for
+the end of the HTTP headers. Unfortunately the &quot;httpready&quot;
+filter breaks support for HTTP/0.9 (which doesn't have headers) so
+Apache doesn't use it, but the &quot;dataready&quot; filter gives the
+same benefit in the majority of cases so Apache attempts to use that
+instead.
+
+<P>
+
+Accept filters provide the most benefit on servers that are already so
+busy that they are configured with &quot;<CODE>KeepAlive Off</CODE>&quot;.
+<A HREF="../keepalive.html">HTTP KeepAlive (aka persistent connections)</A>
+avoids the cost of setting up a new connection for every request, but
+connections that are being kept alive use up one of the available
+child processes. Since there are a limited number of child processes
+this can significantly reduce the capacity of the server. The viewers
+of a web site will still get a lot of the benefit of persistent
+connections even with a very small <CODE>KeepAliveTimeout</CODE> so
+you should try reducing it before turning it off altogether.
+
+<P>
+
+To enable accept filtering, you must either load the appropriate
+accept filter module,
+e.g. with the command <CODE>kldload accf_data</CODE>,
+or compile a kernel with <CODE>options ACCEPT_FILTER_DATA</CODE>.
+Apache will then enable filtering when it is restarted.
+
+<P>
+
+If you are more concerned about performance than compatibility with
+brain-dead HTTP/0.9 user agents then you can recompile Apache to use
+the &quot;httpready&quot; filter. This may be particularly helpful if
+your web site uses really big cookies, for example.
+If you are using <CODE>src/Configure</CODE> then add
+<CODE>-DACCEPT_FILTER_NAME=\&quot;httpready\&quot;</CODE> to the
+<CODE>EXTRA_CFLAGS</CODE> line in the <CODE>src/Configuration</CODE>
+file.
+If you are using APACI (aka <CODE>./configure</CODE>) then use the command
+<CODE>CFLAGS=-DACCEPT_FILTER_NAME=\'\&quot;httpready\&quot;\' ./configure</CODE>
+(with all the funky backslashed quotes).
+
+<P>
+
 <HR>
 
 <H3>More welcome!</H3>
Index: htdocs/manual/misc/perf.html
===================================================================
RCS file: /home/cvs/httpd-docs-1.3/htdocs/manual/misc/perf.html,v
retrieving revision 1.24
diff -u -r1.24 perf.html
--- htdocs/manual/misc/perf.html	1998/09/17 14:14:53	1.24
+++ htdocs/manual/misc/perf.html	2000/07/30 04:28:28
@@ -53,6 +53,7 @@
 <A HREF="perf-bsd44.html#initial">Quick</A> and
 <A HREF="perf-bsd44.html#detail">detailed</A>
 performance tuning hints for BSD-derived systems.
+<A HREF="perf-bsd44.html#accf">Accept filtering</A> on FreeBSD.
 
 <P><HR>
 
Index: src/CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1562
diff -u -r1.1562 CHANGES
--- src/CHANGES	2000/07/03 15:24:22	1.1562
+++ src/CHANGES	2000/07/30 04:28:30
@@ -1,5 +1,9 @@
 Changes with Apache 1.3.13
 
+  *) Use "accept filtering" on recent versions of FreeBSD to avoid
+     having to handle new connections until the request has arrived.
+     [Tony Finch]
+
   *) Win32 NT and 2000 services now capture stderr messages that occur
      before Apache's logs are opened to the Application Event Log.
      Console and Win9x services now hold the console open for 30 seconds
Index: src/main/http_main.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v
retrieving revision 1.507
diff -u -r1.507 http_main.c
--- src/main/http_main.c	2000/07/29 23:56:19	1.507
+++ src/main/http_main.c	2000/07/30 04:28:31
@@ -3398,6 +3398,36 @@
 	exit(1);
     }
 
+#if defined(SO_ACCEPTFILTER)
+    {
+	/*
+	 * See htdocs/manual/misc/perf-bsd44.html
+	 */
+#ifndef ACCEPT_FILTER_NAME
+#define ACCEPT_FILTER_NAME "dataready"
+#endif
+	struct accept_filter_arg af = {
+	    ACCEPT_FILTER_NAME, ""
+	};
+	if (setsockopt(s, SOL_SOCKET, SO_ACCEPTFILTER, &af, sizeof(af)) < 0) {
+            if (errno == ENOENT) {
+                ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
+                             "make_sock: for %s, setsockopt: (SO_ACCEPTFILTER) "
+                             "accept filter %s not found, using unfiltered accept()",
+                             addr, af.af_name);
+            }
+	    else {
+		ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+			     "make_sock: for %s, setsockopt: (SO_ACCEPTFILTER)",
+			     addr);
+		close(s);
+		ap_unblock_alarms();
+		exit(1);
+	    }
+	}
+    }
+#endif
+
 #ifdef WORKAROUND_SOLARIS_BUG
     s = ap_slack(s, AP_SLACK_HIGH);
 

Mime
View raw message