亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Tomcat原理 分類: 原理 2015-06-28 19:26 5人

系統(tǒng) 2130 0

Tomcat的模塊結(jié)構(gòu)設(shè)計(jì)的相當(dāng)好,而且其Web 容器的性能相當(dāng)出色。JBoss直接就使用了Tomcat的web容器,WebLogic的早期版本也是使用了Tomcat的代碼。
Web容器的工作過程在下面的第二個(gè)參考文檔中的文檔已經(jīng)說得相當(dāng)清楚,我也就不再重復(fù)說了。如果不清楚調(diào)用過程,需要先看這個(gè)文檔。這里分析一下Connector的處理過程。
1. 一個(gè)簡(jiǎn)單的Web Server示例
這個(gè)例子也是從網(wǎng)上找得,不知道原作者,也就不在參考資料中引用了。
這個(gè)啟動(dòng)服務(wù)的主程序。
public class HttpServer {
?public static void main(String args[]) {
??int port;
??ServerSocket server_socket; // 讀取服務(wù)器端口號(hào)
??try {
???port = Integer.parseInt(args[0]);
??} catch (Exception e) {
???port = 8080;
??}
??try {
???// 監(jiān)聽服務(wù)器端口,等待連接請(qǐng)求
???server_socket = new ServerSocket(port);
???System.out.println(”httpServer running on port “
?????+ server_socket.getLocalPort());
???// 顯示啟動(dòng)信息
???while (true) {
????Socket socket = server_socket.accept();
????System.out.println(”New connection accepted “
??????+ socket.getInetAddress() + “:” + socket.getPort());
????// 創(chuàng)建分線程
????try {
?????HttpRequestHandler request = new HttpRequestHandler(socket);
?????Thread thread = new Thread(request);
?????// 啟動(dòng)線程
?????thread.start();
????} catch (Exception e) {
?????System.out.println(e);
????}
???}
??} catch (IOException e) {
???System.out.println(e);
??}
?}
}?

?

下面是創(chuàng)建輸出的線程
public class HttpRequestHandler implements Runnable {
?final static String CRLF = “/r/n”;
?Socket socket;
?InputStream input;
?OutputStream output;
?BufferedReader br;
?// 構(gòu)造方法
?public HttpRequestHandler(Socket socket) throws Exception {
??this.socket = socket;
??this.input = socket.getInputStream();
??this.output = socket.getOutputStream();
??this.br = new BufferedReader(new InputStreamReader(socket
????.getInputStream()));
?}

?

?// 實(shí)現(xiàn)Runnable 接口的run()方法
?public void run() {
??try {
???processRequest();
??} catch (Exception e) {
???System.out.println(e);
??}
?}

?

?private void processRequest() throws Exception {
??while (true) {
???// 讀取并顯示W(wǎng)eb 瀏覽器提交的請(qǐng)求信息
???String headerLine = br.readLine();
???System.out.println(”The client request is ” + headerLine);
???if (headerLine.equals(CRLF) || headerLine.equals(”"))
????break;
???StringTokenizer s = new StringTokenizer(headerLine);
???String temp = s.nextToken();
???if (temp.equals(”GET”)) {
????String fileName = s.nextToken();
????fileName = “.” + fileName;
????// 打開所請(qǐng)求的文件
????FileInputStream fis = null;
????boolean fileExists = true;
????try {
?????fis = new FileInputStream(”D:/workspace/tomcat/bin/”+fileName);
????} catch (FileNotFoundException e) {
?????fileExists = false;
????}
????// 完成回應(yīng)消息
????String serverLine = “Server: a simple java httpServer”;
????String statusLine = null;
????String contentTypeLine = null;
????String entityBody = null;
????String contentLengthLine = “error”;
????if (fileExists) {
?????statusLine = “HTTP/1.0 200 OK” + CRLF;
?????contentTypeLine = “Content-type: ” + contentType(fileName) + CRLF;
?????contentLengthLine = “Content-Length: “
???????+ (new Integer(fis.available())).toString() + CRLF;
????} else {
?????statusLine = “HTTP/1.0 404 Not Found” + CRLF;
?????contentTypeLine = “text/html”;
?????entityBody = “<HTML>”
???????+ “<HEAD><TITLE>404 Not Found</TITLE></HEAD>” + “<BODY>404 Not Found” + “<br>usage:http://yourHostName:port/” + “fileName.html</BODY></HTML>”;
????}
????// 發(fā)送到服務(wù)器信息
????output.write(statusLine.getBytes());
????output.write(serverLine.getBytes());
????output.write(contentTypeLine.getBytes());
????output.write(contentLengthLine.getBytes());
????output.write(CRLF.getBytes());
????// 發(fā)送信息內(nèi)容
????if (fileExists) {
?????sendBytes(fis, output);
?????fis.close();
????} else {
?????output.write(entityBody.getBytes());
????}
???}
??}
??// 關(guān)閉套接字和流
??try {
???output.close();
???br.close();
???socket.close();
??} catch (Exception e) {
??}
?}

?

?private static void sendBytes(FileInputStream fis, OutputStream os)
???throws Exception {
??// 創(chuàng)建一個(gè) 1K buffer
??byte[] buffer = new byte[1024];
??int bytes = 0;
??// 將文件輸出到套接字輸出流中
??while ((bytes = fis.read(buffer)) != -1) {
???os.write(buffer, 0, bytes);
??}
?}

?

?private static String contentType(String fileName) {
??if (fileName.endsWith(”.htm”) || fileName.endsWith(”.html”)) {
???return “text/html”;
??}
??return “fileName”;
?}
}?
這個(gè)簡(jiǎn)單的例子說明的web服務(wù)的基本實(shí)現(xiàn)。Tomcat在此之上模塊化出線程池,網(wǎng)絡(luò)連接和WebHttp協(xié)議3個(gè)包。線程池可獨(dú)立使用,網(wǎng)絡(luò)連接使用池化,WebHttp直接從網(wǎng)絡(luò)連接池中獲取即可。
2. 線程池的實(shí)現(xiàn)
這個(gè)功能的實(shí)現(xiàn)在包 org.apache.tomcat.util.thread 中。
ThreadPool是線程池,是這個(gè)功能實(shí)現(xiàn)的核心。它使用了所有的其他類進(jìn)行工作。在類圖中,所有的其他類都是被此類的使用關(guān)系。
我們來看此類是如何工作得。
啟動(dòng)連接池的方法:
?public synchronized void start() {
??stopThePool = false;
??currentThreadCount = 0;
??currentThreadsBusy = 0;

?

??adjustLimits();
??pool = new ControlRunnable[maxThreads];
??openThreads(minSpareThreads);
??if (maxSpareThreads < maxThreads) {
???monitor = new MonitorRunnable(this);
??}
?}?
方法中,根據(jù)配置情況,初始化所有線程進(jìn)入備用狀態(tài)。
首先定義maxThreads數(shù)目的數(shù)組,但是僅僅初始化其中minSpareThreads個(gè)。MonitorRunnable用于檢查,是否空閑數(shù)目超過 maxSpareThreads個(gè)。
currentThreadCount 是當(dāng)前初始化可以使用的線程數(shù)目,而currentThreadsBusy 是當(dāng)前正在使用的線程數(shù)目。
使用連接池的方法:
?public void runIt(ThreadPoolRunnable r) {
??if (null == r) {
???throw new NullPointerException();
??}
??ControlRunnable c = findControlRunnable();
??c.runIt(r);
?}?
該方法中,先尋找可用的線程,找到后在其中運(yùn)行即可。
找可用線程的方法也很簡(jiǎn)單,就是將線程數(shù)組中第 currentThreadCount - currentThreadsBusy - 1 個(gè)元素取出返回,然后將此元素設(shè)成null。
線程運(yùn)行完畢后,設(shè)置currentThreadsBusy– ,然后將 currentThreadCount - currentThreadsBusy - 1 的線程放回就可以了。
線程不夠用就等待,等待失敗就拋出異常。
說明一下上面未提到的類的功能:
ThreadPoolRunnable 這是一個(gè)接口,規(guī)定了一個(gè)線程運(yùn)行時(shí)需要運(yùn)行的一些動(dòng)作。這里需要寫一些業(yè)務(wù)邏輯的代碼了。
ThreadWithAttributes 這個(gè)類從上面的代碼中沒有看到,這個(gè)類標(biāo)識(shí)當(dāng)前運(yùn)行線程的一些特征,比如記錄當(dāng)前運(yùn)行線程的一些狀態(tài)。
ThreadPoolListener 用于監(jiān)控ThreadPool中新增線程的情況。
ControlRunnable 這個(gè)類是ThreadPool的內(nèi)部類,用于運(yùn)行ThreadPoolRunnable 。當(dāng)ThreadPoolRunnable 運(yùn)行完畢后,通知ThreadPool回收線程。它時(shí)刻處于備用狀態(tài)。此對(duì)象實(shí)例化后,就一直在死循環(huán)檢查是否有它需要運(yùn)行的東西。
3. 網(wǎng)絡(luò)連接功能的實(shí)現(xiàn)
這個(gè)功能的實(shí)現(xiàn)在包 org.apache.tomcat.util.net 中。
網(wǎng)絡(luò)連接功能構(gòu)建于線程池之上,實(shí)現(xiàn)了一個(gè)連接服務(wù)模型。服務(wù)器打開端口,池化進(jìn)入連接,為進(jìn)入的連接創(chuàng)建工作線程。
Tomcat的網(wǎng)絡(luò)連接兩個(gè)主要的應(yīng)用是1. 自己提供的web應(yīng)用。2. 給Apache提供的web應(yīng)用。這兩個(gè)過程的解析過程都是一樣的。僅僅在于網(wǎng)絡(luò)連接協(xié)議有差別而已。兩個(gè)應(yīng)用都使用此包的功能實(shí)現(xiàn)。

?

PoolTcpEndpoint是核心,它使用了ThreadPool。TcpWorkerThread通過調(diào)用接口TcpConnectionHandler來完成一次連接需要完成的工作。TcpConnection標(biāo)識(shí)了一個(gè)連接對(duì)象。
PoolTcpEndpoint的初始化方法代碼很簡(jiǎn)單,在構(gòu)建器中創(chuàng)建或引用ThreadPool,在初始化時(shí)創(chuàng)建ServerSocket,用于偵聽客戶端連接。
下面是初始化方法
?public void initEndpoint() throws IOException, InstantiationException {
??try {
???if (factory == null)
????factory = ServerSocketFactory.getDefault();
???if (serverSocket == null) {
????try {
?????if (inet == null) {
??????serverSocket = factory.createSocket(port, backlog);
?????} else {
??????serverSocket = factory
????????.createSocket(port, backlog, inet);
?????}
????} catch (BindException be) {
?????throw new BindException(be.getMessage() + “:” + port);
????}
???}
???if (serverTimeout >= 0)
????serverSocket.setSoTimeout(serverTimeout);
??} catch (IOException ex) {
???// log(”couldn’t start endpoint”, ex, Logger.DEBUG);
???throw ex;
??} catch (InstantiationException ex1) {
???// log(”couldn’t start endpoint”, ex1, Logger.DEBUG);
???throw ex1;
??}
??initialized = true;
?}
?
啟動(dòng)的方法同樣簡(jiǎn)單,僅僅將TcpWorkerThread作為線程池的工作線程,啟動(dòng)連接池,就大功告成了。
?public void startEndpoint() throws IOException, InstantiationException {
??if (!initialized) {
???initEndpoint();
??}
??if (isPool) {
???tp.start();
??}
??running = true;
??paused = false;
??if (isPool) {
???listener = new TcpWorkerThread(this);
???tp.runIt(listener);
??} else {
???log.error(”XXX Error - need pool !”);
??}
?}
?
偵聽的細(xì)節(jié)包裝在TcpWorkerThread類中。運(yùn)行時(shí),它在ServerSocket端口偵聽。當(dāng)發(fā)現(xiàn)有連接進(jìn)入后,立刻開啟一個(gè)新線程繼續(xù)偵聽,本線程開始處理連接。下面是代碼:
?public void runIt(Object perThrData[]) {
??// Create per-thread cache
??if (endpoint.isRunning()) {
???// Loop if endpoint is paused
???while (endpoint.isPaused()) {
????try {
?????Thread.sleep(1000);
????} catch (InterruptedException e) {
?????// Ignore
????}
???}
???// Accept a new connection
???Socket s = null;
???try {
????s = endpoint.acceptSocket();
???} finally {
????// Continue accepting on another thread…
????if (endpoint.isRunning()) {
?????endpoint.tp.runIt(this);
????}
???}
???// Process the connection
???if (null != s) {
????TcpConnection con = null;
????int step = 1;
????try {
?????// 1: Set socket options: timeout, linger, etc
?????endpoint.setSocketOptions(s);
?????// 2: SSL handshake
?????step = 2;
?????if (endpoint.getServerSocketFactory() != null) {
?endpoint.getServerSocketFactory().handshake(s);
?????}
?????// 3: Process the connection
?????step = 3;
?????con = (TcpConnection) perThrData[0];
?????con.setEndpoint(endpoint);
?????con.setSocket(s);
?endpoint.getConnectionHandler().processConnection(con,
???????(Object[]) perThrData[1]);
????} catch (SocketException se) {
……?
4. 協(xié)議 web http的實(shí)現(xiàn)
這個(gè)功能的實(shí)現(xiàn)在包 org.apache.coyote.http11 中。
對(duì)于Http協(xié)議的實(shí)現(xiàn)核心類是Http11Protocol。具體功能的實(shí)現(xiàn)類有MXPoolListener(實(shí)現(xiàn)ThreadPoolListener),Http11ConnectionHander(實(shí)現(xiàn)TcpConnectionHandler)。
Http11Protocol的初始化方法比較簡(jiǎn)單,就是設(shè)置一下讓網(wǎng)絡(luò)連接開始運(yùn)行。
Http11ConnectionHander則初始化類Http11Processor,由它解析請(qǐng)求的字符串,交給生成此Connection的Connector的Container,也就是Engine完成。Engine通過遞歸,解析應(yīng)返回用戶的數(shù)據(jù)。這個(gè)過程在參考文檔中有介紹了。

Tomcat原理 分類: 原理 2015-06-28 19:26 5人閱讀 評(píng)論(0) 收藏


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 久久中文字幕一区二区 | 波多野结衣 一区二区 | 国产精品久久久久久久久ktv | 欧美日韩一区二区三在线 | 日本aⅴ在线不卡免费观看 日本aaaa | 免费看欧美一级特黄a大片 免费看欧美一级特黄a大片一 | 九九在线精品视频 | 四虎国产精品免费久久久 | 91亚洲精品一区二区福利 | 日本一线一区二区三区免费视频 | 精品午夜寂寞影院在线观看 | 日韩不卡在线播放 | zzz色| 日本成人久久 | 国产成人咱精品视频免费网站 | 成 人国产在线观看高清不卡 | 成人精品一区二区www | 四虎网站最新网址 | 91精品日本久久久久久牛牛 | 国产精品99久久久久久小说 | 亚洲不卡免费视频 | 色网站综合| 国产区精品在线 | 97视频免费上传播放 | 亚洲伦理一二三四 | 国产尤物视频 | 久热996re这里有精品 | 永久国产 | 国产一区二区三区不卡在线观看 | 天天搞天天搞 | 精品热99| 亚洲精品乱码久久久久久蜜桃欧美 | 激情久久久久久久久久 | 亚洲欧美精品成人久久91 | 亚洲人成伊人成综合网久久久 | 不卡无毒免费毛片视频观看 | 成年人看的黄色 | a色毛片免费视频 | 久久精品图片 | 久久久久久久久一级毛片 | 波多野结衣国产精品 |