You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2005/11/26 06:43:35 UTC
svn commit: r349085 -
/tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
Author: costin
Date: Fri Nov 25 21:43:33 2005
New Revision: 349085
URL: http://svn.apache.org/viewcvs?rev=349085&view=rev
Log:
The nio endpoint. Uses the thread pool. Only accept is implemented - the
polling of keep alive needs merging some code in the http11protocol.
Added:
tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
Added: tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=349085&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java Fri Nov 25 21:43:33 2005
@@ -0,0 +1,316 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tomcat.util.net;
+
+import java.io.IOException;
+import java.net.BindException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.tomcat.util.threads.ThreadPool;
+import org.apache.tomcat.util.threads.ThreadPoolRunnable;
+import org.apache.tomcat.util.threads.ThreadWithAttributes;
+
+
+/** All threads blocked in accept(). New thread created on demand.
+ * No use of ThreadPool or ServerSocketFactory.
+ *
+ *
+ */
+public class NioEndpoint extends SimpleEndpoint {
+
+ private final Object threadSync = new Object();
+
+ // active acceptors
+ private int acceptors=0;
+
+ ThreadPool tp;
+
+ public NioEndpoint() {
+ tp=new ThreadPool();
+ tp.setMinSpareThreads(2);
+ tp.setMaxSpareThreads(8);
+ }
+
+ // -------------------- Configuration --------------------
+ // -------------------- Thread pool --------------------
+
+ public void setMaxThreads(int maxThreads) {
+ if( maxThreads > 0)
+ tp.setMaxThreads(maxThreads);
+ }
+
+ public int getMaxThreads() {
+ return tp.getMaxThreads();
+ }
+
+ public void setMaxSpareThreads(int maxThreads) {
+ if(maxThreads > 0)
+ tp.setMaxSpareThreads(maxThreads);
+ }
+
+ public int getMaxSpareThreads() {
+ return tp.getMaxSpareThreads();
+ }
+
+ public void setMinSpareThreads(int minThreads) {
+ if(minThreads > 0)
+ tp.setMinSpareThreads(minThreads);
+ }
+
+ public int getMinSpareThreads() {
+ return tp.getMinSpareThreads();
+ }
+
+ public void setThreadPriority(int threadPriority) {
+ tp.setThreadPriority(threadPriority);
+ }
+
+ public int getThreadPriority() {
+ return tp.getThreadPriority();
+ }
+
+ public void setDaemon(boolean b) {
+ daemon=b;
+ tp.setDaemon( b );
+ }
+
+ public boolean getDaemon() {
+ return tp.getDaemon();
+ }
+
+ public String getName() {
+ return tp.getName();
+ }
+
+ public void setName(String name) {
+ tp.setName(name);
+ }
+
+
+ // ----------------------
+ public String getStrategy() {
+ return "nio";
+ }
+
+ public int getCurrentThreadsBusy() {
+ return curThreads;
+ }
+
+ // -------------------- Public methods --------------------
+
+ public void initEndpoint() throws IOException, InstantiationException {
+ try {
+ if(serverSocket==null) {
+ try {
+ ServerSocketChannel ssc=ServerSocketChannel.open();
+ serverSocket = ssc.socket();
+ SocketAddress sa = null;
+ if (inet == null) {
+ sa = new InetSocketAddress( port );
+ } else {
+ sa = new InetSocketAddress(inet, port);
+ }
+ serverSocket.bind( sa , backlog);
+ } catch ( BindException be ) {
+ throw new BindException(be.getMessage() + ":" + port);
+ }
+ }
+ if( serverTimeout >= 0 )
+ serverSocket.setSoTimeout( serverTimeout );
+
+ } catch( IOException ex ) {
+ throw ex;
+ }
+ initialized = true;
+ }
+
+ public void startEndpoint() throws IOException, InstantiationException {
+ if (!initialized) {
+ initEndpoint();
+ }
+ if( maxSpareThreads == minSpareThreads ) {
+ maxSpareThreads = minSpareThreads + 4;
+ }
+ running = true;
+ paused = false;
+
+ tp.start();
+ try {
+ selector = Selector.open();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ addSocketAccept( serverSocket, new SocketDispatch());
+ Thread poller = new Thread( new PollerThread());
+ poller.start();
+ }
+
+
+ // -------------------------------------------------- Master Slave Methods
+
+
+
+
+ public boolean getPolling() {
+ return true;
+ }
+
+ public void addPolling(Socket s, Object context ) {
+
+ }
+
+
+ public void run() {
+ // nothing
+ }
+
+
+ public void addSocketRead(Socket s, Object o) throws IOException {
+ s.getChannel().register( selector, SelectionKey.OP_READ, o);
+ }
+
+ public void addSocketAccept( ServerSocket ss, Object o) throws IOException {
+ ServerSocketChannel ssc=ss.getChannel();
+ ssc.configureBlocking(false);
+ ssc.register( selector, SelectionKey.OP_ACCEPT, o);
+ }
+
+ Selector selector;
+
+ /** Uses NIO to implment selection.
+ * In addition to sockets, you can add other kind of objects.
+ *
+ * @author Costin Manolache
+ */
+ class PollerThread implements Runnable {
+
+ public PollerThread() {
+ }
+
+ public void run() {
+ while( running ) {
+
+ try {
+ int selRes = selector.select();
+
+ if( selRes == 0 ) {
+ System.err.println("Select with 0 keys " +
+ selector.keys().size() );
+ for( SelectionKey k : selector.keys() ) {
+ System.err.println("K " + k.interestOps() +
+ " " + k.readyOps() + " " + k.toString() + " "
+ + k.isValid() );
+ }
+ continue;
+ }
+
+ Set selected = selector.selectedKeys();
+ Iterator selI = selected.iterator();
+
+ while( selI.hasNext() ) {
+ SelectionKey sk = (SelectionKey)selI.next();
+ selI.remove();
+ Object skAt = sk.attachment();
+
+ int readyOps = sk.readyOps();
+ SelectableChannel sc = sk.channel();
+
+ // TODO: use the attachment to decide what's to do.
+ if( sk.isAcceptable() ) {
+ ServerSocketChannel ssc=(ServerSocketChannel)sc;
+ SocketChannel sockC = ssc.accept();
+
+
+ // process the connection in the thread pool
+ if( skAt instanceof ThreadPoolRunnable ) {
+ tp.runIt( (ThreadPoolRunnable) skAt, sockC);
+ }
+ //sk.interestOps( sk.interestOps() |
+ // SelectionKey.OP_ACCEPT );
+ System.err.println( sk.interestOps() );
+
+ continue;
+ }
+
+ // TODO: this is for keep alive
+ if( sk.isReadable() ) {
+ SocketChannel sockC = (SocketChannel)sc;
+
+ // Incoming data on keep-alive connection.
+ continue;
+ }
+
+ // dispatch the socket to a pool thread
+ System.err.println("Select: " + readyOps);
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ }
+
+ }
+
+ class SocketDispatch implements ThreadPoolRunnable {
+
+ public Object[] getInitData() {
+ // no synchronization overhead, but 2 array access
+ Object obj[]=new Object[2];
+ obj[1]= getConnectionHandler().init();
+ obj[0]=new TcpConnection();
+ return obj;
+ }
+
+ public void runIt(Object perThrData[]) {
+ ThreadWithAttributes t=(ThreadWithAttributes)Thread.currentThread();
+
+ SocketChannel sc=(SocketChannel)t.getParam(tp);
+ if (isRunning()) {
+ // Loop if endpoint is paused
+ while (isPaused()) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+
+ if (null != sc) {
+ processSocket(sc.socket(), (TcpConnection) perThrData[0],
+ (Object[]) perThrData[1]);
+ }
+
+ }
+ }
+
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: svn commit: r349085 - /tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
Posted by Costin Manolache <co...@gmail.com>.
On 11/25/05, Bill Barker <wb...@wilshire.com> wrote:
> Urm, APR uses blocking sockets. It uses APR to get around the fact that (at
> least with Sun's JVM) blocking NIO sockets totally s*ck.
>
> Just look at the differences between the logic for ChannelNioSocket and
> AjpAprProcessor.
>From what I've seen, apr does some reads with short timeout and some
non-blocking in sendfile.
I'm not interested in anything more complex for my experiments - at
least not right now. I kind of expect blocking NIO sockets to be
comparable with blocking java sockets and apr sockets for normal I/O
- maybe 1.4 has some problems, but probably 1.5 or 1.6 will improve
things.
I could try reading the http request in non-blocking mode - but what's
the point when the servlet will spend most of the time in service and
writing to a blocking stream ? It's more interesting how to do some of
the service() with a non-blocking socket, for files and few other
things.
Costin
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: svn commit: r349085 - /tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
Posted by Bill Barker <wb...@wilshire.com>.
----- Original Message -----
From: "Costin Manolache" <co...@gmail.com>
To: "Tomcat Developers List" <de...@tomcat.apache.org>
Sent: Friday, November 25, 2005 11:25 PM
Subject: Re: svn commit: r349085 -
/tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
On 11/25/05, Bill Barker <wb...@wilshire.com> wrote:
>> > The nio endpoint. Uses the thread pool. Only accept is implemented -
>> > the
>> > polling of keep alive needs merging some code in the http11protocol.
>> >
>>
>> Yup, it's still too incomplete to evaluate. However from my work with
>> NIO/AJP, using blocking sockets after the accept will totally s*ck in
>> performance with NIO. Unless you come up with something totally
>> brilliant
>> :), I still agree with JFA that non-blocking sockets is the only way to
>> go
>> with NIO.
>
>Well, I also agree that non-blocking sockets are faster than blocking.
>But as someone said, raw performance is not the most important thing
>for most people :-)
>My initial goal is to deal with the keep alives - i.e. not keep the
>threads busy for all the idle connections. That would be a nice
>improvement over the current non-nio connector, which can't do this,
>and is pretty minimal and consistent with the current model.
>
>I will eventually use the APR code for non-blocking parsing of the
>request. Not sure if in this endpoint or I'll try another one - I kind
>of like the fact that this code is very simple. I'm more interested in
>experiments with how to do non-blocking processing at coyote level,
>whatever happens in a servlet is limited by other factors - blocking
>socket is not the biggest overhead.
>
Urm, APR uses blocking sockets. It uses APR to get around the fact that (at
least with Sun's JVM) blocking NIO sockets totally s*ck.
Just look at the differences between the logic for ChannelNioSocket and
AjpAprProcessor.
>I'll announce when it's 'complete' or 'ready to evaluate' - right now
>it's just 'sandbox experiment'.
>Right now - there is little point in benchmarking.
>
>Costin
>
This message is intended only for the use of the person(s) listed above as the intended recipient(s), and may contain information that is PRIVILEGED and CONFIDENTIAL. If you are not an intended recipient, you may not read, copy, or distribute this message or any attachment. If you received this communication in error, please notify us immediately by e-mail and then delete all copies of this message and any attachments.
In addition you should be aware that ordinary (unencrypted) e-mail sent through the Internet is not secure. Do not send confidential or sensitive information, such as social security numbers, account numbers, personal identification numbers and passwords, to us via ordinary (unencrypted) e-mail.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: svn commit: r349085 - /tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
Posted by Costin Manolache <co...@gmail.com>.
On 11/25/05, Bill Barker <wb...@wilshire.com> wrote:
> > The nio endpoint. Uses the thread pool. Only accept is implemented - the
> > polling of keep alive needs merging some code in the http11protocol.
> >
>
> Yup, it's still too incomplete to evaluate. However from my work with
> NIO/AJP, using blocking sockets after the accept will totally s*ck in
> performance with NIO. Unless you come up with something totally brilliant
> :), I still agree with JFA that non-blocking sockets is the only way to go
> with NIO.
Well, I also agree that non-blocking sockets are faster than blocking.
But as someone said, raw performance is not the most important thing
for most people :-)
My initial goal is to deal with the keep alives - i.e. not keep the
threads busy for all the idle connections. That would be a nice
improvement over the current non-nio connector, which can't do this,
and is pretty minimal and consistent with the current model.
I will eventually use the APR code for non-blocking parsing of the
request. Not sure if in this endpoint or I'll try another one - I kind
of like the fact that this code is very simple. I'm more interested in
experiments with how to do non-blocking processing at coyote level,
whatever happens in a servlet is limited by other factors - blocking
socket is not the biggest overhead.
I'll announce when it's 'complete' or 'ready to evaluate' - right now
it's just 'sandbox experiment'.
Right now - there is little point in benchmarking.
Costin
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: svn commit: r349085 - /tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
Posted by Bill Barker <wb...@wilshire.com>.
----- Original Message -----
From: <co...@apache.org>
To: <to...@jakarta.apache.org>
Sent: Friday, November 25, 2005 9:43 PM
Subject: svn commit: r349085 -
/tomcat/sandbox/java/org/apache/tomcat/util/net/NioEndpoint.java
> Author: costin
> Date: Fri Nov 25 21:43:33 2005
> New Revision: 349085
>
> URL: http://svn.apache.org/viewcvs?rev=349085&view=rev
> Log:
> The nio endpoint. Uses the thread pool. Only accept is implemented - the
> polling of keep alive needs merging some code in the http11protocol.
>
Yup, it's still too incomplete to evaluate. However from my work with
NIO/AJP, using blocking sockets after the accept will totally s*ck in
performance with NIO. Unless you come up with something totally brilliant
:), I still agree with JFA that non-blocking sockets is the only way to go
with NIO.
This message is intended only for the use of the person(s) listed above as the intended recipient(s), and may contain information that is PRIVILEGED and CONFIDENTIAL. If you are not an intended recipient, you may not read, copy, or distribute this message or any attachment. If you received this communication in error, please notify us immediately by e-mail and then delete all copies of this message and any attachments.
In addition you should be aware that ordinary (unencrypted) e-mail sent through the Internet is not secure. Do not send confidential or sensitive information, such as social security numbers, account numbers, personal identification numbers and passwords, to us via ordinary (unencrypted) e-mail.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org