程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> How Tomcat works — 五、tomcat啟動(4),tomcatworks

How Tomcat works — 五、tomcat啟動(4),tomcatworks

編輯:JAVA綜合教程

How Tomcat works — 五、tomcat啟動(4),tomcatworks


前面擺了三節的姿勢,現在終於要看到最終tomcat監聽端口,接收請求了。

目錄

  • Connector
  • Http11Protocol
  • JIoEndpoint
  • 總結

在前面的初始化都完成之後,進行Connector的初始化,也是執行一些生命周期方法。

Connector

在啟動過程中這個類的主要作用是初始化並啟動CoyoteAdapter和Http11Protocol:

initInternal

  • 新建一個CoyoteAdapter,並調用protocolHandler.setAdapter方法設置adapter(最後protocol創建processor處理完成之後會調用adapter.service方法)
  • 初始化protocolHandler(在Connector構造函數中就獲得了該實例),實際調用的是超類的init方法
  • 初始化mapperListener

startInternal

作用很簡單了

  • 啟動protocolHandler
  • 啟動mapperListener

Http11Protocol

前面在第一節中說到Connector的時候繪制了tomcat中關於協議的類圖,對於不同的協議有不同的連接器,這裡主要說關於http11的,ajp也類似。這個類的主要作用就是啟動一個JIoEndpoint)(其內部類Acceptor是最終啟動線程接收請求的類)。

特別需要關注的是該構造函數:

  • new JIoEndpoint()
  • new Http11ConnectionHandler(),這個類是Http11Protocol的內部類,負責獲取processor來處理請求
  • ((JIoEndpoint)endpoint).setHandler設置endpoint中handler

init

雖然是Http11Protocol的實例,但是執行的是父類的init方法,主要的操作在父類的父類的init方法中AbstractProtocol.init

  • 注冊MBean
  • 調用JIoEndpoint.init(該類在)初始化JIoEndpoint

start

  • endpoint.start()啟動JIoEndpoint

JIoEndpoint

來到了tomcat啟動的最後一站,要啟動線程監聽端口接收請求了。繼承關系

所以也用到了很多父類的方法,這個的作用就是新建socket,綁定到對應端口

綁定到端口之後,就可以調用socket.accept()接受請求了

所以startInternal方法主要進行了一下操作

  • 如果Executor(用來執行processor線程)為null則新建
  • 啟動Acceptor線程,接受請求就在這個線程裡面
  • 啟動一個請求超時檢測線程JIoEndpoint$AsyncTimeout
protected class Acceptor extends AbstractEndpoint.Acceptor { @Override public void run() { int errorDelay = 0; // Loop until we receive a shutdown command while (running) { // Loop if endpoint is paused while (paused && running) { state = AcceptorState.PAUSED; try { Thread.sleep(50); } catch (InterruptedException e) { // Ignore } } if (!running) { break; } state = AcceptorState.RUNNING; 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) { countDownConnection(); // Introduce delay if necessary errorDelay = handleExceptionWithDelay(errorDelay); // re-throw throw ioe; } // Successful accept, reset the error delay errorDelay = 0; // Configure the socket if (running && !paused && setSocketOptions(socket)) { // Hand this socket off to an appropriate processor if (!processSocket(socket)) { countDownConnection(); // Close socket right away closeSocket(socket); } } else { countDownConnection(); // Close socket right away closeSocket(socket); } } 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); } } state = AcceptorState.ENDED; } } View Code

終於看到夢寐以求的socket.accept了!雖然只是為了最後這一步,tomcat廢了這麼多周折,作用還是很重要的:

  • 用來管理生命周期的Lifecycle,給這個容器的生命周期提供了規范和基本實現
  • 便於擴展的容器架構,多Host可用來分布式,多Context部署多個webapp,Wrapper用來作為servlet的直接容器(比如如果是SingleThreadModel的話需要有多個servlet實例)
  • 可以處理多種協議的Connector

總結

到這裡tomcat 這個啟動過程算是完成了,當然了裡面還是有很多細節略過了,不過還是很值得仔細進行專題學習,比如:server.xml的解析,web.xml的解析(這樣也能明白平時配置的都有什麼作用),tomcat的熱加載功能是怎麼實現的(對的,就在啟動過程中啟動了一個線程)等等。這些都做了筆記,以後再整理下。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved