1. 程式人生 > >Tomcat 7伺服器執行緒模型

Tomcat 7伺服器執行緒模型

Tomcat 7伺服器網路處理主要由NioEndpoint,其處理客戶端連線的主要流程如圖所示

圖中Acceptor及Worker分別是以執行緒池形式存在,Poller是一個單執行緒。注意,與BIO的實現一樣,預設狀態下,在server.xml中沒有配置<Executor>,則以Worker執行緒池執行,如果配置了<Executor>,則以基於java concurrent 系列的java.util.concurrent.ThreadPoolExecutor執行緒池執行。

Acceptor
接收socket執行緒,這裡雖然是基於NIO的connector,但是在接收socket方面還是傳統的serverSocket.accept()方式,獲得SocketChannel物件,然後封裝在一個tomcat的實現類org.apache.tomcat.util.net.NioChannel物件中。然後將NioChannel物件封裝在一個PollerEvent物件中,並將PollerEvent物件壓入events queue裡。這裡是個典型的生產者-消費者模式,Acceptor與Poller執行緒之間通過queue通訊,Acceptor是events queue的生產者,Poller是events queue的消費者。


Poller
Poller執行緒中維護了一個Selector物件,NIO就是基於Selector來完成邏輯的。在connector中並不止一個Selector,在socket的讀寫資料時,為了控制timeout也有一個Selector,在後面的BlockSelector中介紹。可以先把Poller執行緒中維護的這個Selector標為主Selector。
Poller是NIO實現的主要執行緒。首先作為events queue的消費者,從queue中取出PollerEvent物件,然後將此物件中的channel以OP_READ事件註冊到主Selector中,然後主Selector執行select操作,遍歷出可以讀資料的socket,並從Worker執行緒池中拿到可用的Worker執行緒,然後將socket傳遞給Worker。整個過程是典型的NIO實現。


Worker
Worker執行緒拿到Poller傳過來的socket後,將socket封裝在SocketProcessor物件中。然後從Http11ConnectionHandler中取出Http11NioProcessor物件,從Http11NioProcessor中呼叫CoyoteAdapter的邏輯,跟BIO實現一樣。在Worker執行緒中,會完成從socket中讀取http request,解析成HttpServletRequest物件,分派到相應的servlet並完成邏輯,然後將response通過socket發回client。在從socket中讀資料和往socket中寫資料的過程,並沒有像典型的非阻塞的NIO的那樣,註冊OP_READ或OP_WRITE事件到主Selector,而是直接通過socket完成讀寫,這時是阻塞完成的,但是在timeout控制上,使用了NIO的Selector機制,但是這個Selector並不是Poller執行緒維護的主Selector,而是BlockPoller執行緒中維護的Selector,稱之為輔Selector。