source: nutchez-0.1/tomcat/webapps/docs/aio.html @ 141

Last change on this file since 141 was 66, checked in by waue, 16 years ago

NutchEz - an easy way to nutch

File size: 22.2 KB
Line 
1<html><head><META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><title>Apache Tomcat 6.0 - Advanced IO and Tomcat</title><meta value="Remy Maucherat" name="author"><meta value="" name="email"></head><body vlink="#525D76" alink="#525D76" link="#525D76" text="#000000" bgcolor="#ffffff"><table cellspacing="0" width="100%" border="0"><!--PAGE HEADER--><tr><td><!--PROJECT LOGO--><a href="http://tomcat.apache.org/"><img border="0" alt="
2      The Apache Tomcat Servlet/JSP Container
3    " align="right" src="./images/tomcat.gif"></a></td><td><font face="arial,helvetica,sanserif"><h1>Apache Tomcat 6.0</h1></font></td><td><!--APACHE LOGO--><a href="http://www.apache.org/"><img border="0" alt="Apache Logo" align="right" src="./images/asf-logo.gif"></a></td></tr></table><table cellspacing="4" width="100%" border="0"><!--HEADER SEPARATOR--><tr><td colspan="2"><hr size="1" noshade></td></tr><tr><!--LEFT SIDE NAVIGATION--><td nowrap="true" valign="top" width="20%"><p><strong>Links</strong></p><ul><li><a href="index.html">Docs Home</a></li><li><a href="http://wiki.apache.org/tomcat/FAQ">FAQ</a></li></ul><p><strong>User Guide</strong></p><ul><li><a href="introduction.html">1) Introduction</a></li><li><a href="setup.html">2) Setup</a></li><li><a href="appdev/index.html">3) First webapp</a></li><li><a href="deployer-howto.html">4) Deployer</a></li><li><a href="manager-howto.html">5) Manager</a></li><li><a href="realm-howto.html">6) Realms and AAA</a></li><li><a href="security-manager-howto.html">7) Security Manager</a></li><li><a href="jndi-resources-howto.html">8) JNDI Resources</a></li><li><a href="jndi-datasource-examples-howto.html">9) JDBC DataSources</a></li><li><a href="class-loader-howto.html">10) Classloading</a></li><li><a href="jasper-howto.html">11) JSPs</a></li><li><a href="ssl-howto.html">12) SSL</a></li><li><a href="ssi-howto.html">13) SSI</a></li><li><a href="cgi-howto.html">14) CGI</a></li><li><a href="proxy-howto.html">15) Proxy Support</a></li><li><a href="mbeans-descriptor-howto.html">16) MBean Descriptor</a></li><li><a href="default-servlet.html">17) Default Servlet</a></li><li><a href="cluster-howto.html">18) Clustering</a></li><li><a href="balancer-howto.html">19) Load Balancer</a></li><li><a href="connectors.html">20) Connectors</a></li><li><a href="monitoring.html">21) Monitoring and Management</a></li><li><a href="logging.html">22) Logging</a></li><li><a href="apr.html">23) APR/Native</a></li><li><a href="virtual-hosting-howto.html">24) Virtual Hosting</a></li><li><a href="aio.html">25) Advanced IO</a></li><li><a href="extras.html">26) Additional Components</a></li><li><a href="maven-jars.html">27) Mavenized</a></li></ul><p><strong>Reference</strong></p><ul><li><a href="RELEASE-NOTES.txt">Release Notes</a></li><li><a href="config/index.html">Configuration</a></li><li><a href="api/index.html">Javadocs</a></li><li><a href="http://tomcat.apache.org/connectors-doc/">JK 1.2 Documentation</a></li></ul><p><strong>Apache Tomcat Development</strong></p><ul><li><a href="building.html">Building</a></li><li><a href="changelog.html">Changelog</a></li><li><a href="http://wiki.apache.org/tomcat/TomcatVersions">Status</a></li><li><a href="developers.html">Developers</a></li><li><a href="architecture/index.html">Architecture</a></li><li><a href="funcspecs/index.html">Functional Specs.</a></li></ul></td><!--RIGHT SIDE MAIN BODY--><td align="left" valign="top" width="80%"><table cellspacing="4" width="100%" border="0"><tr><td valign="top" align="left"><h1>Apache Tomcat 6.0</h1><h2>Advanced IO and Tomcat</h2></td><td nowrap="true" valign="top" align="right"><small><a href="printer/aio.html"><img alt="Printer Friendly Version" border="0" src="./images/printer.gif"><br>print-friendly<br>version
4                    </a></small></td></tr></table><table cellpadding="2" cellspacing="0" border="0"><tr><td bgcolor="#525D76"><font face="arial,helvetica.sanserif" color="#ffffff"><a name="Introduction"><strong>Introduction</strong></a></font></td></tr><tr><td><blockquote>
5
6  <p>
7    With usage of APR or NIO APIs as the basis of its connectors, Tomcat is
8    able to provide a number of extensions over the regular blocking IO
9    as provided with support for the Servlet API.
10  </p>
11
12  <p>
13    <b>IMPORTANT NOTE: Usage of these features requires using the APR or NIO
14    HTTP connectors. The classic java.io HTTP connector and the AJP connectors
15    do not support them.</b>
16  </p>
17
18  </blockquote></td></tr></table><table cellpadding="2" cellspacing="0" border="0"><tr><td bgcolor="#525D76"><font face="arial,helvetica.sanserif" color="#ffffff"><a name="Comet support"><strong>Comet support</strong></a></font></td></tr><tr><td><blockquote>
19
20  <p>
21    Comet support allows a servlet to process IO aynchronously, recieving
22    events when data is available for reading on the connection (rather than
23    always using a blocking read), and writing data back on connections
24    asychnonously (most likely responding to some event raised from some
25    other source).
26  </p>
27
28  <table cellpadding="2" cellspacing="0" border="0"><tr><td bgcolor="#828DA6"><font face="arial,helvetica.sanserif" color="#ffffff"><a name="CometEvent"><strong>CometEvent</strong></a></font></td></tr><tr><td><blockquote>
29 
30  <p>
31    Servlets which implement the <code>org.apache.catalina.CometProcessor</code>
32    interface will have their event method invoked rather than the usual service
33    method, according to the event which occurred. The event object gives
34    access to the usual request and response objects, which may be used in the
35    usual way. The main difference is that those objects remain valid and fully
36    functional at any time between processing of the BEGIN event until processing
37    an END or ERROR event.
38    The following event types exist:
39  </p>
40 
41  <ul>
42  <li>EventType.BEGIN: will be called at the beginning
43     of the processing of the connection. It can be used to initialize any relevant
44     fields using the request and response objects. Between the end of the processing
45     of this event, and the beginning of the processing of the end or error events,
46     it is possible to use the response object to write data on the open connection.
47     Note that the response object and depedent OutputStream and Writer are still
48     not synchronized, so when they are accessed by multiple threads,
49     synchronization is mandatory. After processing the initial event, the request
50     is considered to be committed.</li>
51  <li>EventType.READ: This indicates that input data is available, and that one read can be made
52       without blocking. The available and ready methods of the InputStream or
53       Reader may be used to determine if there is a risk of blocking: the servlet
54       should read while data is reported available, and can make one additional read
55       should read while data is reported available. When encountering a read error,
56       the servlet should report it by propagating the exception properly. Throwing
57       an exception will cause the error event to be invoked, and the connection
58       will be closed.
59       Alternately, it is also possible to catch any exception, perform clean up
60       on any data structure the servlet may be using, and using the close method
61       of the event. It is not allowed to attempt reading data from the request
62       object outside of the execution of this method.<br>
63       On some platforms, like Windows, a client disconnect is indicated by a READ event.
64       Reading from the stream may result in -1, an IOException or an EOFException.
65       Make sure you properly handle all these three cases.
66       If you don't catch the IOException, Tomcat will instantly invoke your event chain with an ERROR as
67       it catches the error for you, and you will be notified of the error at that time.
68  </li>
69  <li>EventType.END: End may be called to end the processing of the request. Fields that have
70     been initialized in the begin method should be reset. After this event has
71     been processed, the request and response objects, as well as all their dependent
72     objects will be recycled and used to process other requests. End will also be
73     called when data is available and the end of file is reached on the request input
74     (this usually indicates the client has pipelined a request).</li>
75  <li>EventType.ERROR: Error will be called by the container in the case where an IO exception
76     or a similar unrecoverable error occurs on the connection. Fields that have
77     been initialized in the begin method should be reset. After this event has
78     been processed, the request and response objects, as well as all their dependent
79     objects will be recycled and used to process other requests.</li>
80  </ul>
81
82  <p>
83    There are some event subtypes which allow finer processing of events (note: some of these
84    events require usage of the org.apache.catalina.valves.CometConnectionManagerValve valve):
85  </p>
86
87  <ul>
88  <li>EventSubType.TIMEOUT: The connection timed out (sub type of ERROR); note that this ERROR
89    type is not fatal, and the connection will not be closed unless the servlet uses the close
90    method of the event.
91  </li>
92  <li>EventSubType.CLIENT_DISCONNECT: The client connection was closed (sub type of ERROR).
93    method of the event.
94  </li>
95  <li>EventSubType.IOEXCEPTION: An IO exception occurred, such as invalid content, for example,
96    an invalid chunk block (sub type of ERROR).
97  </li>
98  <li>EventSubType.WEBAPP_RELOAD: The web application is being reloaded (sub type of END).
99  </li>
100  <li>EventSubType.SESSION_END: The servlet ended the session (sub type of END).
101  </li>
102  </ul>
103
104  <p>
105    As described above, the typical lifecycle of a Comet request will consist in a series of
106    events such as: BEGIN -&gt; READ -&gt; READ -&gt; READ -&gt; ERROR/TIMEOUT. At any time, the servlet
107    may end processing of the request by using the close method of the event object.
108  </p>
109 
110  </blockquote></td></tr></table>
111
112  <table cellpadding="2" cellspacing="0" border="0"><tr><td bgcolor="#828DA6"><font face="arial,helvetica.sanserif" color="#ffffff"><a name="CometFilter"><strong>CometFilter</strong></a></font></td></tr><tr><td><blockquote>
113 
114  <p>
115    Similar to regular filters, a filter chain is invoked when comet events are processed.
116    These filters should implement the CometFilter interface (which works in the same way as
117    the regular Filter interface), and should be declared and mapped in the deployment
118    descriptor in the same way as a regular filter. The filter chain when processing an event
119    will only include filters which match all the usual mapping rules, and also implement
120    the CometFiler interface.
121  </p>
122 
123  </blockquote></td></tr></table>
124
125  <table cellpadding="2" cellspacing="0" border="0"><tr><td bgcolor="#828DA6"><font face="arial,helvetica.sanserif" color="#ffffff"><a name="Example code"><strong>Example code</strong></a></font></td></tr><tr><td><blockquote>
126 
127  <p>
128    The following pseudo code servlet implments asynchronous chat functionality using the API
129    described above:
130  </p>
131 
132  <div align="left"><table border="0" cellpadding="0" cellspacing="4"><tr><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr><tr><td width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#ffffff"><pre>
133public class ChatServlet
134    extends HttpServlet implements CometProcessor {
135
136    protected ArrayList&lt;HttpServletResponse&gt; connections =
137        new ArrayList&lt;HttpServletResponse&gt;();
138    protected MessageSender messageSender = null;
139   
140    public void init() throws ServletException {
141        messageSender = new MessageSender();
142        Thread messageSenderThread =
143            new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");
144        messageSenderThread.setDaemon(true);
145        messageSenderThread.start();
146    }
147
148    public void destroy() {
149        connections.clear();
150        messageSender.stop();
151        messageSender = null;
152    }
153
154    /**
155     * Process the given Comet event.
156     *
157     * @param event The Comet event that will be processed
158     * @throws IOException
159     * @throws ServletException
160     */
161    public void event(CometEvent event)
162        throws IOException, ServletException {
163        HttpServletRequest request = event.getHttpServletRequest();
164        HttpServletResponse response = event.getHttpServletResponse();
165        if (event.getEventType() == CometEvent.EventType.BEGIN) {
166            log("Begin for session: " + request.getSession(true).getId());
167            PrintWriter writer = response.getWriter();
168            writer.println("&lt;!doctype html public \"-//w3c//dtd html 4.0 transitional//en\"&gt;");
169            writer.println("&lt;head&gt;&lt;title&gt;JSP Chat&lt;/title&gt;&lt;/head&gt;&lt;body bgcolor=\"#FFFFFF\"&gt;");
170            writer.flush();
171            synchronized(connections) {
172                connections.add(response);
173            }
174        } else if (event.getEventType() == CometEvent.EventType.ERROR) {
175            log("Error for session: " + request.getSession(true).getId());
176            synchronized(connections) {
177                connections.remove(response);
178            }
179            event.close();
180        } else if (event.getEventType() == CometEvent.EventType.END) {
181            log("End for session: " + request.getSession(true).getId());
182            synchronized(connections) {
183                connections.remove(response);
184            }
185            PrintWriter writer = response.getWriter();
186            writer.println("&lt;/body&gt;&lt;/html&gt;");
187            event.close();
188        } else if (event.getEventType() == CometEvent.EventType.READ) {
189            InputStream is = request.getInputStream();
190            byte[] buf = new byte[512];
191            do {
192                int n = is.read(buf); //can throw an IOException
193                if (n &gt; 0) {
194                    log("Read " + n + " bytes: " + new String(buf, 0, n)
195                            + " for session: " + request.getSession(true).getId());
196                } else if (n &lt; 0) {
197                    error(event, request, response);
198                    return;
199                }
200            } while (is.available() &gt; 0);
201        }
202    }
203
204    public class MessageSender implements Runnable {
205
206        protected boolean running = true;
207        protected ArrayList&lt;String&gt; messages = new ArrayList&lt;String&gt;();
208       
209        public MessageSender() {
210        }
211       
212        public void stop() {
213            running = false;
214        }
215
216        /**
217         * Add message for sending.
218         */
219        public void send(String user, String message) {
220            synchronized (messages) {
221                messages.add("[" + user + "]: " + message);
222                messages.notify();
223            }
224        }
225
226        public void run() {
227
228            while (running) {
229
230                if (messages.size() == 0) {
231                    try {
232                        synchronized (messages) {
233                            messages.wait();
234                        }
235                    } catch (InterruptedException e) {
236                        // Ignore
237                    }
238                }
239
240                synchronized (connections) {
241                    String[] pendingMessages = null;
242                    synchronized (messages) {
243                        pendingMessages = messages.toArray(new String[0]);
244                        messages.clear();
245                    }
246                    // Send any pending message on all the open connections
247                    for (int i = 0; i &lt; connections.size(); i++) {
248                        try {
249                            PrintWriter writer = connections.get(i).getWriter();
250                            for (int j = 0; j &lt; pendingMessages.length; j++) {
251                                writer.println(pendingMessages[j] + "&lt;br&gt;");
252                            }
253                            writer.flush();
254                        } catch (IOException e) {
255                            log("IOExeption sending message", e);
256                        }
257                    }
258                }
259
260            }
261
262        }
263
264    }
265
266}
267  </pre></td><td width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr><tr><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr></table></div>
268 
269  </blockquote></td></tr></table>
270  <table cellpadding="2" cellspacing="0" border="0"><tr><td bgcolor="#828DA6"><font face="arial,helvetica.sanserif" color="#ffffff"><a name="Comet timeouts"><strong>Comet timeouts</strong></a></font></td></tr><tr><td><blockquote>
271    <p>If you are using the NIO connector, you can set individual timeouts for your different comet connections.
272       To set a timeout, simple set a request attribute like the following code shows:
273       <div align="left"><table border="0" cellpadding="0" cellspacing="4"><tr><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr><tr><td width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#ffffff"><pre>CometEvent event.... event.setTimeout(30*1000);</pre></td><td width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr><tr><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr></table></div> or
274       <div align="left"><table border="0" cellpadding="0" cellspacing="4"><tr><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr><tr><td width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#ffffff"><pre>event.getHttpServletRequest().setAttribute("org.apache.tomcat.comet.timeout", new Integer(30 * 1000));</pre></td><td width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr><tr><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td><td height="1" width="1" bgcolor="#023264"><img border="0" hspace="0" vspace="0" height="1" width="1" src="./images/void.gif"></td></tr></table></div>
275       This sets the timeout to 30 seconds.
276       Important note, in order to set this timeout, it has to be done on the <code>BEGIN</code> event.
277       The default value is <code>soTimeout</code>
278    </p>
279    <p>If you are using the APR connector, all Comet connections will have the same timeout value. It is <code>soTimeout*50</code>
280    </p>
281  </blockquote></td></tr></table>
282
283  </blockquote></td></tr></table><table cellpadding="2" cellspacing="0" border="0"><tr><td bgcolor="#525D76"><font face="arial,helvetica.sanserif" color="#ffffff"><a name="Asynchronous writes"><strong>Asynchronous writes</strong></a></font></td></tr><tr><td><blockquote>
284
285  <p>
286    When APR or NIO is enabled, Tomcat supports using sendfile to send large static files.
287    These writes, as soon as the system load increases, will be performed
288    asynchronously in the most efficient way. Instead of sending a large response using
289    blocking writes, it is possible to write content to a static file, and write it
290    using a sendfile code. A caching valve could take advantage of this to cache the
291    response data in a file rather than store it in memory. Sendfile support is
292    available if the request attribute <code>org.apache.tomcat.sendfile.support</code>
293    is set to <code>Boolean.TRUE</code>.
294  </p>
295 
296  <p>
297    Any servlet can instruct Tomcat to perform a sendfile call by setting the appropriate
298    request attributes. It is also necessary to correctly set the content length
299    for the response. When using sendfile, it is best to ensure that neither the
300    request or response have been wrapped, since as the response body will be sent later
301    by the connector itself, it cannot be filtered. Other than setting the 3 needed
302    request attributes, the servlet should not send any response data, but it may use
303    any method which will result in modifying the response header (like setting cookies).
304  </p>
305 
306  <ul>
307  <li>org.apache.tomcat.sendfile.filename: Canonical filename of the file which will be sent as
308      a String</li>
309  <li>org.apache.tomcat.sendfile.start: Start offset as a Long</li>
310  <li>org.apache.tomcat.sendfile.end: End offset as a Long</li>
311  </ul>
312
313  </blockquote></td></tr></table></td></tr><!--FOOTER SEPARATOR--><tr><td colspan="2"><hr size="1" noshade></td></tr><!--PAGE FOOTER--><tr><td colspan="2"><div align="center"><font size="-1" color="#525D76"><em>
314        Copyright &copy; 1999-2008, Apache Software Foundation
315        </em></font></div></td></tr></table></body></html>
Note: See TracBrowser for help on using the repository browser.