- 浏览: 6909 次
- 性别:
- 来自: 北京
文章分类
最新评论
上回我们说到Http11Protocol,它的init 和start方法:
/* * NOTE: There is no maintenance of state or checking for valid transitions * within this class. It is expected that the connector will maintain state * and prevent invalid state transitions. */ @Override public void init() throws Exception { if (getLog().isInfoEnabled()) getLog().info(sm.getString("abstractProtocolHandler.init", getName())); if (oname == null) { // Component not pre-registered so register it oname = createObjectName(); if (oname != null) { Registry.getRegistry(null, null).registerComponent(this, oname, null); } } if (this.domain != null) { try { tpOname = new ObjectName(domain + ":" + "type=ThreadPool,name=" + getName()); Registry.getRegistry(null, null).registerComponent(endpoint, tpOname, null); } catch (Exception e) { getLog().error(sm.getString( "abstractProtocolHandler.mbeanRegistrationFailed", tpOname, getName()), e); } rgOname=new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName()); Registry.getRegistry(null, null).registerComponent( getHandler().getGlobal(), rgOname, null ); } String endpointName = getName(); endpoint.setName(endpointName.substring(1, endpointName.length()-1)); try { endpoint.init(); } catch (Exception ex) { getLog().error(sm.getString("abstractProtocolHandler.initError", getName()), ex); throw ex; } } @Override public void start() throws Exception { if (getLog().isInfoEnabled()) getLog().info(sm.getString("abstractProtocolHandler.start", getName())); try { endpoint.start(); } catch (Exception ex) { getLog().error(sm.getString("abstractProtocolHandler.startError", getName()), ex); throw ex; } }
2个逻辑主要都调用了endpoint的对应方法,endpoint是JIoEndpoint的实例,JIoEndpoint实现了一个简单的服务器模型:监听线程接收到一个socket连接就会启动一个工作线程来处理。这里面有我们期待已久的Socket出现了。JIoEndpoint实现了虚类AbstractEndpoint,上面提到的endpoint.init()和endpoint.start()都是AbstractEndpoint里的方法
public final void init() throws Exception { if (bindOnInit) { bind(); bindState = BindState.BOUND_ON_INIT; } } public final void start() throws Exception { if (bindState == BindState.UNBOUND) { bind(); bindState = BindState.BOUND_ON_START; } startInternal(); }
我们看JIoEndpoint的bind方法:
public void bind() throws Exception { // Initialize thread count defaults for acceptor if (acceptorThreadCount == 0) { acceptorThreadCount = 1; } // Initialize maxConnections if (getMaxConnections() == 0) { // User hasn't set a value - use the default setMaxConnections(getMaxThreads()); } if (serverSocketFactory == null) { if (isSSLEnabled()) { serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this); } else { serverSocketFactory = new DefaultServerSocketFactory(this); } } if (serverSocket == null) { try { if (getAddress() == null) { serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog()); } else { serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress()); } } catch (BindException orig) { String msg; if (getAddress() == null) msg = orig.getMessage() + " <null>:" + getPort(); else msg = orig.getMessage() + " " + getAddress().toString() + ":" + getPort(); BindException be = new BindException(msg); be.initCause(orig); throw be; } } }
bind方法主要实例化了serverSocket,接着看startInternal方法
@Override public void startInternal() throws Exception { if (!running) { running = true; paused = false; // Create worker collection if (getExecutor() == null) { createExecutor(); } initializeConnectionLatch(); // Start acceptor threads for (int i = 0; i < acceptorThreadCount; i++) { Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i); acceptorThread.setPriority(threadPriority); acceptorThread.setDaemon(getDaemon()); acceptorThread.start(); } // Start async timeout thread Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout"); timeoutThread.setPriority(threadPriority); timeoutThread.setDaemon(true); timeoutThread.start(); } } startInternal 首先创建了一个处理队列, 然后生成一个最大连接数限制对象LimitLatch, 生成一组接收线程,并启动所有线程。 生成一个后台线程用以检查超时请求。 我们看Acceptor的run方法: public void run() { int errorDelay = 0; // Loop until we receive a shutdown command while (running) { // Loop if endpoint is paused while (paused && running) { try { Thread.sleep(1000); } catch (InterruptedException e) { // Ignore } } if (!running) { break; } try { //if we have reached max connections, wait countUpOrAwaitConnection(); Socket socket = null; try { // Accept the next incoming connection from the server // socket socket = serverSocketFactory.acceptSocket(serverSocket); } catch (IOException ioe) { // Introduce delay if necessary errorDelay = handleExceptionWithDelay(errorDelay); // re-throw throw ioe; } // Successful accept, reset the error delay errorDelay = 0; // Configure the socket if (setSocketOptions(socket)) { // Hand this socket off to an appropriate processor if (!processSocket(socket)) { // Close socket right away try { socket.close(); } catch (IOException e) { // Ignore } } } else { // Close socket right away try { socket.close(); } catch (IOException e) { // Ignore } } } catch (IOException x) { if (running) { log.error(sm.getString("endpoint.accept.fail"), x); } } catch (NullPointerException npe) { if (running) { log.error(sm.getString("endpoint.accept.fail"), npe); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("endpoint.accept.fail"), t); } // The processor will recycle itself when it finishes } } } 这是一个典型的socket监听处理程序。目前我们不去追究里面太多的细节,先形成一个整体的形象上的认识,到目前 为止,监听真正的建立起来了,意味着tomcat可以接受、处理请求了。
发表评论
-
tomcat源码分析系列之请求处理---大厨颠勺
2011-08-13 22:04 0上一回,我们已经吃上了香喷喷的狗肉,味道好是好,但作为 ... -
tomcat源码分析系列之请求处理---关门打狗
2011-08-13 17:06 1484上回我们把请求放进来了,这回我们关上门,好好修理修理它 ... -
tomcat源码分析系列之请求处理---请君入瓮
2011-08-13 14:31 1298费了九牛二虎之力 ... -
tomcat源码分析系列之启动
2011-07-31 16:36 1466对于tomcat这么一个庞大的东西,要去分析 ... -
tomcat源码分析系列之启动---暗度陈仓
2011-08-10 22:27 1171前面我们分析了tomcat是如何启动的,但我们好像 ... -
tomcat源码分析系列之HTTP
2011-07-25 23:33 0tomcat是一个web容器,对于互联网来说,H ... -
tomcat源码分析系列之前言
2011-07-24 11:40 30我这人很懒,工作中经常使用tomcat,一直以来就 ...
相关推荐
tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-...
apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-...
tomcat 源码分析系列文档 http深入分析,tomcat中类的加载,tomcat的启动,tomcat的容器思想,
Tomcat8亲测可用 tomcat-redis-session-manager的jar包 修改了tomcat-redis-session-manager源码进行的编译生成的jar包
tomcat9负载均衡tomcat-cluster-redis-session-manager_4.0
tomcat-redis-session-manager源码
解决tomcat8-maven-plugin-3.0-r1655215.jar阿里云同有的问题。放到路径org\apache\tomcat\maven\tomcat8-maven-plugin\3.0-r1655215\就可以了
tomcat6-dta-ssl-1.0.0.jar 此类文件将有助于tomcat支持ssl协议
开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-...
支持tomcat8的redis-session-manager-master,测试环境jdk-8u191、apache-tomcat-8.0.53
tomcat-redis-session-manager-2.0.0.jar jedis-2.5.2.jar commons-pool2-2.2.jar 2.修改 conf 目录下的 context.xml 文件 <Valve className="com.orangefunction.tomcat.redissessions....
apache-tomcat-9.0.45-srcapache-tomcat-9.0.45-srcapache-tomcat-9.0.45-srcapache-tomcat-9.0.45-srcapache-tomcat-9.0.45-srcapache-tomcat-9.0.45-srcapache-tomcat-9.0.45-srcapache-tomcat-9.0.45-srcapache-...
apache-tomcat-7.0.53apache-tomcat-7.0.53apache-tomcat-7.0.53apache-tomcat-7.0.53
支持tomcat8的sessionManager,kuanrf-tomcat-redis-session-manager-1.0.jar
tomcat-redis-session-manager-2.0.0.jar
apache-tomcat-8.5.20.tar.gz源码包和context.xml文件,这套配置是我自己亲测可用的。。另外我用的redis4这个版本。注意:如果你使用的TOMCAT其他版本。例如tomcat6或者7这套JAR包可能不可用,tomcat8.0没有测试。...
tomcat6-maven-plugin-2.1插件包
文件名写错了,此压缩文件支持tomcat8.5。是否支持8.0请自行测试,本人只测试了8.5,可以使用。压缩文件包括tomcat-redis-session-manager-...apache-tomcat-8.5.33.tar.gz,nginx-1.6.2.tar.gz也打包进去,一步到位。
apache-tomcat-10.0.8.exe、 apache-tomcat-10.0.8.tar.gz、 apache-tomcat-10.0.8.zip、 apache-tomcat-10.0.8-windows-x64.zip、 apache-tomcat-10.0.8-windows-x86.zip、 apache-tomcat-10.0.8-deployer.tar.gz、...