在這裏我先簡單的說下bio和nio的區別apache
這裏我以電話客服的狀況來解釋tomcat
bio服務器
一個客戶對應一個客服,網絡
假如客戶比較麻煩,中途不掛電話,或者去作其餘事情了,而客服資源會被一直佔用socket
致使的後果是系統處理能力大大下降性能
Nio網絡傳輸協議
中間加入了一個協調員,假如遇到比較麻煩的用戶,請求能夠先到協調員這裏,當用戶準備好之後,在轉接給客服。spa
那這兩種方式有啥區別呢?.net
理論上來講,若是是徹底沒有網絡延遲,阻塞的狀況下,其實這二者的性能差很少。線程
可是實際狀況下,服務器根本沒法肯定客戶端的網絡狀況,因此,通常不使用bio
Tomcat處理請求核心流程圖
Acceptor (Acceptor的做用是控制與tomcat創建鏈接的數量,但Acceptor只負責創建鏈接)
接收socket線程,這裏雖然是基於NIO的connector,可是在接收socket方面仍是傳統的serverSocket.accept()方式,得到SocketChannel對象,而後封裝在一個tomcat的實現類org.apache.tomcat.util.net.NioChannel對象中。而後將NioChannel對象封裝在一個PollerEvent對象中,並將PollerEvent對象壓入一個隊列中裏。這是典型的生產者-消費者模式,Acceptor與Poller線程之間經過queue通訊,Acceptor是生產者,Poller是消費者。
Poller (socket內容的讀寫)
Poller線程中維護了一個Selector對象,NIO就是基於Selector來完成邏輯的。
Poller是NIO實現的主要線程。首先做爲消費者,從隊列中取出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。
核心參數說明
參數名稱 |
可選值 |
參數解釋 |
protocol |
HTTP/1.1 org.apache.coyote.http11.Http11NioProtocol |
網絡傳輸協議 bio Nio |
maxThreads |
|
工做線程的最大線程數 |
minSpareThreads |
|
工做線程的最小線程 |
connectionTimeout |
|
鏈接超時(當請求數量超過了 maxConnections,系統會繼續接收鏈接但不會超過acceptCount的值 ) |
acceptCount |
|
等待隊列的長度 |
acceptorThreadCount |
|
Acceptor線程數量 |
maxConnections |
|
最大鏈接數 |
pollerThreadCount |
|
Poller線程數量(nio獨有) |