How Tomcat Works 學習-我們到底能走多遠系列(8)

來源:互聯網
上載者:User
我們到底能走多遠系列(8)

扯淡:

  我們到底能走多遠?是想提醒自己不要停止學習和部落格的更新,這個系列會一直和web開發有關,我的目標是寫完100個。慢慢來,階段性目標15個吧。哈哈

  學得好不如做的好,做得好不如扯得好啊!

主題:

  在上一輪學習中:Servlet-我們到底能走多遠系列(7) 發現要想理解web中的servlet,還是需要深入學習servlet 容器:tomcat(因為它是開源的嘛!)

  為了不迷失在tomcat茫茫的源碼中,我先學習下最外圍的一些知識,然後先把《How Tomcat Works 》第一章看了。有人評論說這本書就是代碼太多,我到很喜歡這個寫作風格,程式員嘛,代碼就是我們的文章!

  HTTP(Hypertext Transfer Protocol):

    想要自己看http訊息可以利用抓包工具比如wireshark來抓取http訊息。(wireshark是一個很不錯的抓包工具,介面也蠻漂亮的,功能強大。)
    官方下載:http://www.wireshark.org/download.html

    訪問網站時抓到的包:包括了request 和 response(沒有包括body部分)

    詳細的http協議的學習可以查看:http://www.cnblogs.com/tankxiao/archive/2012/02/13/2342672.html

    其中關於method的get還是post可以查看:http://www.cnblogs.com/killbug/archive/2012/08/05/2624286.html

一個簡單的webServer:

  知道了http訊息的格式,就可以來學習下《How Tomcat Works 》第一章提供的代碼了

分成3部分:

HttpServer :負責監聽伺服器的連接埠,將監聽到的訊息交給Request處理,然後執行個體特定的Response返回除去。

Request :負責把http訊息中的Uri取出來。

Response :根據Request取得的Uri,到到響應的檔案中讀取內容,把內容返回出去。

上面的整個流程基本完成了響應 - 返回的效果。

HttpServer:

package code.tomcat.simpleWebServer;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;public class HttpServer {    // 項目放置的檔案夾    public static final String WEB_ROOT = System.getProperty("user.id") + File.separator + "webroot";    // SHUTDOWN命令    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";    // 判斷是否Shutdown標示符,控製程序運行    private boolean isShutdown = false;    // 主程式    public static void main(String[] args) {        HttpServer httpSever = new HttpServer();        // 不能叫wait,你懂的        httpSever.await();    }        private void await(){        ServerSocket serverSocket = null;        int port = 8080;                try {            // 用ServerSocket等待連接埠訊息            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));        } catch (IOException e) {            e.printStackTrace();            System.exit(1);//異常後,把java虛擬機器都關掉        }        while( ! isShutdown ){            Socket socket = null;             InputStream input = null;             OutputStream output = null;            try {                // 建立socket                socket = serverSocket.accept();                // socket的輸入                input = socket.getInputStream();                // socket的輸出                output = socket.getOutputStream();                Request request = new Request(input);                request.parse();//Request來解析出uri                Response response = new Response(output);                response.setRequest(request);//把Request放進去,是要用解析出來的uri                response.sendStaticResource();//把產生的返回內容發送出去                // 關閉socket                socket.close();                isShutdown = request.getUri().equals(SHUTDOWN_COMMAND);            } catch (IOException e) {                e.printStackTrace();                continue;            }        }    }}

Request :

package code.tomcat.simpleWebServer;import java.io.IOException;import java.io.InputStream;public class Request {    private InputStream input;    private String uri;        public Request(InputStream input) {        this.input = input;    }    public void parse() {        StringBuffer request = new StringBuffer(2048);        int i;        byte[] buffer = new byte[2048];        try {            // 把InputStream讀出來,放進byte[2048]大小的buffer中            i = input.read(buffer);        } catch (IOException e) {            e.printStackTrace();            i = -1;        }        // 傳化成StringBuffer        for (int j = 0; j < i; j++) {            request.append((char) buffer[j]);        }        // 然後再以String的形式傳經解析方法中去        uri = parseUri(request.toString());    }    // 真正解析uri出來的方法,相當於是解析request的第一行:GET /killbug/ HTTP/1.1 想要取出“/killbug/”這段,即兩個空格之間那一段    private String parseUri(String requestString) {        int index1, index2;        // 第一個空格位置        index1 = requestString.indexOf(' ');        if (index1 != -1) {            // 第二個空格位置            index2 = requestString.indexOf(' ', index1 + 1);            if (index2 > index1)                // 根據兩個空格的位置截斷出需要的一段                return requestString.substring(index1 + 1, index2);        }        return null;    }    public String getUri() {        return uri;    }}

Response :

package code.tomcat.simpleWebServer;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;public class Response {    private static final int BUFFER_SIZE = 1024;    Request request;    OutputStream output;    public Response(OutputStream output) {        this.output = output;    }    public void setRequest(Request request) {        this.request = request;    }    public void sendStaticResource() throws IOException {        byte[] bytes = new byte[BUFFER_SIZE];        //檔案輸入資料流        FileInputStream fis = null;        // request.getUri()相當於:“/killbug/”,把路徑和檔案起來定位到具體的檔案,可以是項目中的一個html檔案        File file = new File(HttpServer.WEB_ROOT, request.getUri());        if (file.exists()) {            fis = new FileInputStream(file);            int ch = fis.read(bytes, 0, BUFFER_SIZE);            while (ch != -1) {                // 寫進socket的output中去,就成了傳回值了                output.write(bytes, 0, ch);                ch = fis.read(bytes, 0, BUFFER_SIZE);            }        }else { // 找不到檔案的情況相當於404啦                String errorMessage = "HTTP/1.1 404 File Not Found\r\n"                         + "Content-Type: text/html\r\n"                         + "Content-Length: 23\r\n"                         + "\r\n"                         + "<h1>File Not Found</h1>";                 output.write(errorMessage.getBytes());                 }        }    }
  Tomcat外圍的一些知識:

1,tomcat的目錄結構:

window的(linux下目錄結構大同小異):

 

各檔案夾各自的分管作用:

bin: 存放各種平台下啟動和關閉Tomcat的指令檔.其中有個檔是catalina.bat,開啟這個windos設定檔,在非注釋行加入JDK路徑,例如 : SET  JAVA_HOME=C:\j2sdk1.4.2_06 儲存後,就配置好tomcat環境了. startup.bat是windows下啟動tomcat的檔案,shutdown.bat是關閉tomcat的檔案.

work : Tomcat把各種由jsp產生的servlet檔案放在這個目錄下.

logs : 存放Tomcat的記錄檔

conf : Tomcat的各種設定檔,最重要的是 server.xml

lib: 在server/webapps目錄中,存放Tomcat內建的兩個APP-admin和manager應用,使用來管理Tomcat-web服務用的.在server/lib目錄中,存放tomcat伺服器所需要的各,web應用不能訪問種jar

temp:存放Tomcat運行時的臨時檔案;,

2,tomcat串連數:

在tomcat設定檔server.xml中的<Connector ... />配置中,和串連數相關的參數有:
minProcessors:最小空閑連接線程數,用於提高系統處理效能,預設值為10
maxProcessors:最大連接線程數,即:並發處理的最大請求數,預設值為75
acceptCount:允許的最大串連數,應大於等於maxProcessors,預設值為100
enableLookups:是否反查網域名稱,取值為:true或false。為了提高處理能力,應設定為false
connectionTimeout:網路連接逾時,單位:毫秒。設定為0表示永不逾時,這樣設定有隱患的。通常可設定為30000毫秒。
其中和最大串連數相關的參數為maxProcessors和acceptCount。如果要加大並發串連數,應同時加大這兩個參數。
web server允許的最大串連數還受制於作業系統的核心參數設定,通常Windows是2000個左右,Linux是1000個左右。Unix中如何設定這些參數,請參閱Unix常用監控和管理命令
tomcat4中的配置樣本:
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8080" minProcessors="10" maxProcessors="1024"
enableLookups="false" redirectPort="8443"
acceptCount="1024" debug="0" connectionTimeout="30000" />

對於其他連接埠的偵聽配置,以此類推。

3,如何加大tomcat可以使用的記憶體

tomcat預設可以使用的記憶體為128MB,在較大型的應用項目中,這點記憶體是不夠的,需要調大。
Unix下,在檔案{tomcat_home}/bin/catalina.sh的前面,增加如下設定:
JAVA_OPTS='-Xms【初始化記憶體大小】 -Xmx【可以使用的最大記憶體】'
需要把這個兩個參數值調大。例如:
JAVA_OPTS='-Xms256m -Xmx512m'
表示初始化記憶體為256MB,可以使用的最大記憶體為512MB

4,關於虛擬機器主機

tomcat伺服器中在 $CATALINA_HOME/conf/service.xml中配置設定<host>的name屬性來配置不同主機名稱對應的網站:
<Engine name="Catalina" defaultHost="localhost">
 
     <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
            resourceName="UserDatabase"/>
 
     <Host name="localhost"  appBase="webapps"
           unpackWARs="true" autoDeploy="true"
           xmlValidation="false" xmlNamespaceAware="false">
     </Host>
     <!-虛擬機器主機配置-->
     <Host name="http://www.cnblogs.com/" appBase="webapps"
       unpackWARs="true" autoDeploy="true"
       xmlValidation="false" xmlNamespaceAware="false">
       <Context path="" docBase="G:\dev\apache-tomcat-6.0.33\webapps\killbug\" debug="1" reloadable="true" allowLinking="true"></Context>
   </Host>
   </Engine>

service.xml中<host>標籤用於配置網站,一個<host>建立一個WEB網站,可以使用多個<host>配置多個網站,但同一個<Engine>中<host>的name不能相同,name屬性對應該網站的主機名稱,appBase="webappa"設定了一個路徑,該路徑將作為嵌套在<host>中<context>的屬性docBase的基準路徑,docBase可以是絕對路徑也可以是相對於appBase的相對路徑,如:docBase="Jquery\",當tomcat接受到一個請求,會取出主機名稱來跟<host>的name值來對應,來訪問對應的context中docBase配置的網站,若沒有找到對應的host,則會訪問在<Engine>中defaultHost配置的預設網站,將defaultHost值設定為<Engine>中某個<host>的name值,則該host就會作為該Engine引擎的預設網站。
當配置多個<host>時就不能使用IP來作為主機名稱來訪問tomcat,因為Host的name值對應同一個IP,這時就不知道訪問哪一個網站。

在建立基於主機名稱的虛擬機器主機時,除了在service.xml中配置主機名稱與網站的映射外,還要配置主機名稱與IP地址的映射,這樣在網路中才會找到該WEB伺服器。配置主機名稱與IP地址的映射有兩種方式:

1.通過DNS(網域名稱解析伺服器)系統來配置

2.通過在用戶端本地Hosts檔案中配置。

Hosts檔案可用於小型的企業內部網,而DNS用於大型網路服務(如:Internet上對外提供服務)。客戶機會首先在本地Hosts檔案中找主機名稱與IP的映射,若沒有找到才會去DNS系統中去尋找。

下面介紹在hosts檔案中配置。

在C:\Windows\System32\drivers\etc下找到Hosts檔案,用EditPlus開啟該檔案會看到預設有127.0.0.1  localhost,這時為什麼我們訪問http://localhost:8080/,下面我們在新的一行寫127.0.0.1 www.cnblogs.com   ,就建立起來127.0.0.1與www.cnblogs.com主機名稱的映射。

我們如上面圖所示配置Service.xml,就完成了虛擬機器主機的配置。啟動tomcat,訪問http://www.cnblogs.com:8080/killbug就可以訪問killbug網站了。

 

總結:tomcat 作為容器需要監聽http訊息,調用響應servlet,做出回應。這個基本的流程似乎只是tomcat的冰山一角,讓我們繼續前行。

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不會成功。
共勉

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.