Tomcat 原始碼分析之Socket通訊

來源:互聯網
上載者:User

 

Tomcat 原始碼分析之Socket通訊

此系列文章皆為Tomcat 7.0代碼程式碼分析。

 

1.    Socket通訊:

Tomcat對於 Socket的處理方式主要分為以下幾種:

 

  1.  BIO方式:採用Java阻塞Socket通訊的方式處理串連。
  2.  NIO方式:之前採用BIO(阻塞方式),現在由於在Java1.4之後引入NIO,提供了NIO的實現。
  3. APR方式:為了和本地機器更好的整合,有更高的效能,例如一些進階的系統IO功能(sendfile, epoll and OpenSSL),本地操作的處理(shared memory, NT pipes and Unix sockets以及OS Level的功能(random number generation, system status, etc),Tomcat使用JNI調用處理Socket連結。
  4. AJP和ARP結合的方式。
  5. AJP方式:通過AJP協議進行通訊 : AJP主要用於Apache的HTTP伺服器和Servlet Web容器之間通訊,它是Packet_Oriented的,換句話說,它發送給瀏覽器(其他Web Server)的資料是Packet(s),得到Servlet 容器的響應也是Packet(s),這裡有特殊情況,如果Servlet 容器發送的資料是二進位的,則直接發送給瀏覽器。此外,AJP還可以重用和Servlet容器之間的Socket串連(Socket Connection),降低建立開銷。 具體請看:http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html。
2.    模型介紹

Connector由ProtocolHandler和一個串連連接埠組成,ProtocolHandler使用以上介紹的各種方式處理Socket。

根據配置選取不同的ProtocolHandler實作類別的代碼如下:

 

Java代碼 
  1. /** 
  2.      * Set the Coyote protocol which will be used by the connector. 
  3.      * 
  4.      * @param protocol The Coyote protocol name 
  5.      */  
  6.     public void setProtocol(String protocol) {  
  7.   
  8.         if (AprLifecycleListener.isAprAvailable()) {  
  9.             if ("HTTP/1.1".equals(protocol)) {  
  10.                 setProtocolHandlerClassName  
  11.                     ("org.apache.coyote.http11.Http11AprProtocol");  
  12.             } else if ("AJP/1.3".equals(protocol)) {  
  13.                 setProtocolHandlerClassName  
  14.                     ("org.apache.coyote.ajp.AjpAprProtocol");  
  15.             } else if (protocol != null) {  
  16.                 setProtocolHandlerClassName(protocol);  
  17.             } else {  
  18.                 setProtocolHandlerClassName  
  19.                     ("org.apache.coyote.http11.Http11AprProtocol");  
  20.             }  
  21.         } else {  
  22.             if ("HTTP/1.1".equals(protocol)) {  
  23.                 setProtocolHandlerClassName  
  24.                     ("org.apache.coyote.http11.Http11Protocol");  
  25.             } else if ("AJP/1.3".equals(protocol)) {  
  26.                 setProtocolHandlerClassName  
  27.                     ("org.apache.coyote.ajp.AjpProtocol");  
  28.             } else if (protocol != null) {  
  29.                 setProtocolHandlerClassName(protocol);  
  30.             }  
  31.         }  
  32.   
  33.     }  

 

 

其相應的配置例子如下:

 

Java代碼 
  1. <Connector port="8080" protocol="HTTP/1.1"  
  2.                connectionTimeout="20000"  
  3.                redirectPort="8443" />  

 

 

Connector調用ProtocolHandler對象處理Socket,主要代碼在該Connector類的startInternal()裡,如下

 

Java代碼 
  1. /** 
  2.      * Begin processing requests via this Connector. 
  3.      * 
  4.      * @exception LifecycleException if a fatal startup error occurs 
  5.      */  
  6.     @Override  
  7.     protected void startInternal() throws LifecycleException {  
  8.   
  9.         setState(LifecycleState.STARTING);  
  10.   
  11.         try {  
  12.             protocolHandler.start();  
  13.         } catch (Exception e) {  
  14.             String errPrefix = "";  
  15.             if(this.service != null) {  
  16.                 errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";  
  17.             }  
  18.   
  19.             throw new LifecycleException  
  20.                 (errPrefix + " " + sm.getString  
  21.                  ("coyoteConnector.protocolHandlerStartFailed"), e);  
  22.         }  
  23.   
  24.         mapperListener.start();  
  25. }  

 

而ProtocolHandler對象會啟動一個相應的AbstractEndpoint對象來建立ServerSocket,監聽服務相應的連接埠,並啟動線程池處理訊息。

ProtocolHandler對象啟動AbstractEndpoint對象的代碼在org.apache.coyote.AbstractProtocolHandler類裡,如下:

 

Java代碼 
  1. @Override  
  2.     public void start() throws Exception {  
  3.         if (getLog().isInfoEnabled())  
  4.             getLog().info(sm.getString("abstractProtocolHandler.start",  
  5.                     getName()));  
  6.         try {  
  7.             endpoint.start();  
  8.         } catch (Exception ex) {  
  9.             getLog().error(sm.getString("abstractProtocolHandler.startError",  
  10.                     getName()), ex);  
  11.             throw ex;  
  12.         }  
  13. }  

 

各種不同的ProtocolHandler對應的AbstractEndpoint如下:

ProtocolHandler

AbstractEndpoint

AjpAprProtocol

AprEndpoint

AjpProtocol

JIoEndpoint

Http11AprProtocol

AprEndpoint

Http11NioProtocol

NioEndpoint

Http11Protocol

JIoEndpoint

不同協議處理方式請看這個類的實現:AprEndpoint,JIoEndpoint,NioEndpoint。

JIoEndpoint採用BIO方式處理,NioEndpoint採用NIO的方式處理,AprEndpoint調用大量的Poll的大量native方法處理Socket。具體不再一一介紹。

我們最後為這三個組件畫出一個簡單的模型,如下:

3.    Tomcat中Server,Service和Connector之間的關係:

一個Server包含多個Service,而一個Service由多個Connector組成。

一個Server對應一個Servlet容器的執行個體,而一個Service可以由多個Connector組成,但是這些Connector必須是一個Engine的,Engine代表一台實際的物理或者虛擬機器,因為Tomcat可以實現叢集的,配置片段樣本如下:

 

Java代碼
  1. <Service name="Catalina">  
  2.         <Connector port="8080" protocol="HTTP/1.1"  
  3.                connectionTimeout="20000"  
  4.                redirectPort="8443" />  
  5.         <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />  
  6.        <Engine  …>  
  7.                ….  
  8.        </Engine>  
  9. </Service>  

 

今天就講到這裡了,後續繼續把自己已看的東西整理出來。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.