`
zddava
  • 浏览: 243030 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Tomcat NIO源代码分析(一) -- Acceptor

阅读更多
这里主要讲一下Tomcat使用NIO启动和进行请求处理的大致流程,使用的源码版本是7.0.5,对于其他处理等流程就不写了,我在别的文章里已经大致写过了,不过是用的6.0版本:http://zddava.iteye.com/category/53603

当Tomcat配置成使用NIO时,启动过程其实和过去差不多,也是Connector#startInternal -> Protocol(Http11NioProtocol)#start() -> Endpoint(NioEndPoint)#start()的过程,这里主要看一下NioEndPoint:

	public void start() throws Exception {
		// 初始化
		if (!initialized) {
			init();
		}
		if (!running) {
			running = true;
			paused = false;

			// 创建一个ThreadPoolExecutor对象,和JDK里的功能一样,只不过进行了一些扩展
			if (getExecutor() == null) {
				createExecutor();
			}

			// 开启poll的线程
			pollers = new Poller[getPollerThreadCount()];
			for (int i = 0; i < pollers.length; i++) {
				pollers[i] = new Poller();
				Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-" + i);
				pollerThread.setPriority(threadPriority);
				pollerThread.setDaemon(true);
				pollerThread.start();
			}

			// 开启Acceptor的线程
			for (int i = 0; i < acceptorThreadCount; i++) {
				Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
				acceptorThread.setPriority(threadPriority);
				acceptorThread.setDaemon(getDaemon());
				acceptorThread.start();
			}
		}
	}


这里先看一下init()方法,没有全列出来,最主要的一点就是初始化ServerSocketChannel:

	public void init() throws Exception {

		if (initialized)
			return;

		// 初始化ServerSocketChannel,这里用的是阻塞的方式,没有用Selector
		serverSock = ServerSocketChannel.open();
		socketProperties.setProperties(serverSock.socket());
		InetSocketAddress addr = (getAddress() != null ? new InetSocketAddress(getAddress(), getPort())
				: new InetSocketAddress(getPort()));
		serverSock.socket().bind(addr, getBacklog());
		serverSock.configureBlocking(true); // mimic APR behavior
		serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout());

		......

	}


Tomcat每种Endpoint的Acceptor线程其实作用都一样,对来访的请求进行最初的处理之用,NioEndpoint的Acceptor也不例外,它内部也只定义一个继承自Runnable的方法:

        public void run() {
            while (running) {
                
                while (paused && running) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }

                if (!running) {
                    break;
                }
                try {
		    // 接受请求
                    SocketChannel socket = serverSock.accept();
                    if ( running && (!paused) && socket != null ) {
                    	// 将SocketChannel给pollor处理
                        if (!setSocketOptions(socket)) {
                            try {
                                socket.socket().close();
                                socket.close();
                            } catch (IOException ix) {
                                if (log.isDebugEnabled())
                                    log.debug("", ix);
                            }
                        } 
                    }
                } catch (SocketTimeoutException sx) {
                    //normal condition
                } catch (IOException x) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), x);
                    }
                } catch (OutOfMemoryError oom) {
                    try {
                        oomParachuteData = null;
                        releaseCaches();
                        log.error("", oom);
                    }catch ( Throwable oomt ) {
                        try {
                            try {
                                System.err.println(oomParachuteMsg);
                                oomt.printStackTrace();
                            }catch (Throwable letsHopeWeDontGetHere){
                                ExceptionUtils.handleThrowable(letsHopeWeDontGetHere);
                            }
                        }catch (Throwable letsHopeWeDontGetHere){
                            ExceptionUtils.handleThrowable(letsHopeWeDontGetHere);
                        }
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
        }
    }


方法其实挺容易理解,就是得到请求用的SocketChannel后交给Poller处理,这里poll是一个UNIX的系统调用名字,Java开发者可以google下,我也是才准备开始啃《UNIX网络编程》,闲言少叙,看一下#setSocketOptions()方法吧:

	protected boolean setSocketOptions(SocketChannel socket) {
		// Process the connection
		try {
			// disable blocking, APR style, we are gonna be polling it
			// 这里终于看到了印象中的NIO的影子了
			socket.configureBlocking(false);
			Socket sock = socket.socket();
			socketProperties.setProperties(sock);

			// NioChannel是ByteChannel的子类
			// 从队列里取出第一个可用的Channel,这样的话NioChannel应该是设计成非GC的
			// 感觉其目的主要是对SocketChannel进行下封装
			NioChannel channel = nioChannels.poll();
			if (channel == null) {
				// 不过这里如果没有可用的就初始化一个的话请求数陡然增高再慢慢回落的时候不就浪费了内存了吗?
				// NioBufferHandler里分别分配了读缓冲区和写缓冲区
				// SSL setup
				if (sslContext != null) {
					SSLEngine engine = createSSLEngine();
					int appbufsize = engine.getSession().getApplicationBufferSize();
					NioBufferHandler bufhandler = new NioBufferHandler(Math.max(appbufsize,
							socketProperties.getAppReadBufSize()), Math.max(appbufsize,
							socketProperties.getAppWriteBufSize()), socketProperties.getDirectBuffer());
					channel = new SecureNioChannel(socket, engine, bufhandler, selectorPool);
				} else {
					// normal tcp setup
					NioBufferHandler bufhandler = new NioBufferHandler(socketProperties.getAppReadBufSize(),
							socketProperties.getAppWriteBufSize(), socketProperties.getDirectBuffer());

					channel = new NioChannel(socket, bufhandler);
				}
			} else {
				// 这里就是对Channel的重用了
				channel.setIOChannel(socket);
				if (channel instanceof SecureNioChannel) {
					SSLEngine engine = createSSLEngine();
					((SecureNioChannel) channel).reset(engine);
				} else {
					channel.reset();
				}
			}
			// 这里就是将SocketChannel注册到Poller了。
			// getPoller0用的循环的方式来返回Poller,即Poller 1, 2, 3... n 然后再回到1, 2, 3....
			getPoller0().register(channel);
		} catch (Throwable t) {
			ExceptionUtils.handleThrowable(t);
			try {
				log.error("", t);
			} catch (Throwable tt) {
				ExceptionUtils.handleThrowable(t);
			}
			// Tell to close the socket
			return false;
		}
		return true;
	}


好了,终于到了Poller了,下一篇开始Poller。
3
0
分享到:
评论

相关推荐

    xnio-nio-3.8.4.Final-API文档-中英对照版.zip

    赠送源代码:xnio-nio-3.8.4.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.4.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.4.Final-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    xnio-nio-3.8.0.Final-API文档-中文版.zip

    赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.0.Final-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jboss.xnio:...

    xnio-nio-3.8.4.Final-API文档-中文版.zip

    赠送源代码:xnio-nio-3.8.4.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.4.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.4.Final-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jboss.xnio:...

    xnio-nio-3.8.0.Final-API文档-中英对照版.zip

    赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.0.Final-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    httpcore-nio-4.4.15-API文档-中文版.zip

    赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:httpcore-nio,...

    apache-tomcat-8.5.64-windows-x64.zip

    8. **性能优化**:可以通过调整`server.xml`中的线程池设置、启用NIO连接器、增加JVM堆大小等方式优化Tomcat性能。 9. **集成其他应用服务器**:Tomcat可以与其他Java EE服务器(如JBoss、WebLogic)一起使用,作为...

    httpcore-nio-4.4.6-API文档-中文版.zip

    赠送源代码:httpcore-nio-4.4.6-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.6-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:httpcore-nio,...

    apache-tomcat-8.5.97-windows-x.zip

    Apache Tomcat 是一个开源软件应用服务器,主要用于部署和运行Java Servlet和JavaServer Pages(JSP)应用程序。这个压缩包文件 "apache-tomcat-8.5.97-windows-x.zip" 包含了Apache Tomcat 8.5.97 版本在Windows...

    Tomcat8源代码

    **Apache Tomcat 8源代码解析** Apache Tomcat是一款开源的Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,是许多Web应用开发者的重要工具。Tomcat 8是其发展的一个重要版本,引入了许多新...

    apache-tomcat-7.0.88-src.tar

    首先,`apache-tomcat-7.0.88-src.tar`是一个包含Apache Tomcat 7.0.88版本源代码的压缩文件,`.tar`后缀表明它是用tar工具打包的,通常用于Linux或Unix系统。要访问这些源代码,你需要先解压文件,这通常可以通过...

    tomcat6 源代码

    这个源代码压缩包提供了Tomcat6的完整源码,对于开发者来说,深入理解其内部工作原理、优化性能或者定制功能都具有极大的价值。下面将详细介绍Tomcat6的一些关键知识点。 1. **Servlet容器**: Tomcat作为一个...

    httpcore-nio-4.4.10-API文档-中英对照版.zip

    赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档:httpcore-nio-4.4.10-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    tomcat7源代码

    《深入剖析Tomcat7源代码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用规范,包括Servlet、JSP和EL(Expression Language)等。本资源包含Tomcat7的源代码以及运行所需的jar包,...

    最新版windows apache-tomcat-9.0.54-windows-x64.zip

    Apache Tomcat是一款开源的Java应用服务器,主要用于运行Java Servlet和JavaServer Pages(JSP)技术。这个最新的版本,即apache-tomcat-9.0.54,是针对Windows操作系统设计的64位版本,提供了在Windows环境下部署和...

    apache-tomcat-9.0.74-windows-x64

    Apache Tomcat 9.0.74 是一个广泛使用的开源软件,它是一个实现了Java Servlet、JavaServer Pages(JSP)和Java EE的Web应用程序容器。这个版本是专门为Windows x64平台设计的,确保在64位操作系统上高效运行。在...

    httpcore-nio-4.4.15-API文档-中英对照版.zip

    赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:...

    网络编程(socket、NIO、mina)---demo

    接下来,Non-blocking I/O(NIO)是Java中用于处理大量并发连接的一种高效方法。传统的Java I/O(Blocking I/O)在读写操作时会阻塞线程,直到操作完成。而NIO引入了选择器(Selector)和通道(Channel)的概念,...

    apache-tomcat-9.0.55-windows-x64位官方版

    Apache Tomcat是一款开源的Java应用服务器,主要用于运行Java Servlet和JavaServer Pages(JSP)技术。这个"apache-tomcat-9.0.55-windows-x64位官方版"是Tomcat的9.0.55版本,针对64位Windows操作系统设计。在这一...

    tomcat-native-1.2.25-src-build

    "tomcat-native-1.2.25-src-build" 指的是该扩展的源代码版本1.2.25,用于编译生成适用于不同操作系统的本地库文件。 【编译过程】:下载的源码包"tomcat-native-1.2.25-src-build"需要经过编译才能生成适用于目标...

    httpcore-nio-4.4.10-API文档-中文版.zip

    赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档:httpcore-nio-4.4.10-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache....

Global site tag (gtag.js) - Google Analytics