日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Tomcat 处理 HTTP 请求源码分析(下)【转】

發(fā)布時間:2025/4/5 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tomcat 处理 HTTP 请求源码分析(下)【转】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文地址:https://www.infoq.cn/article/zh-tomcat-http-request-2

很多開源應用服務器都是集成 tomcat 作為 web container 的,而且對于 tomcat 的 servlet container 這部分代碼很少改動。這樣,這些應用服務器的性能基本上就取決于 Tomcat 處理 HTTP 請求的 connector 模塊的性能。本文首先從應用層次分析了 tomcat 所有的 connector 種類及用法,接著從架構(gòu)上分析了 connector 模塊在整個 tomcat 中所處的位置,最后對 connector 做了詳細的源代碼分析。并且我們以 Http11NioProtocol 為例詳細說明了 tomcat 是如何通過實現(xiàn) ProtocolHandler 接口而構(gòu)建 connector 的。

上篇地址為《Tomcat 處理 HTTP 請求源碼分析(上)》 ,本文是系列下篇。

4 如何實現(xiàn) Connector

由上面的介紹我們可以知道,實現(xiàn) Connector 就是實現(xiàn) ProtocolHander 接口的過程。

AjpAprProtocol、AjpProtocol、Http11AprProtocol、Http11Protocol、JkCoyoteHandler、MemoryProtocolHandler 這些實現(xiàn)類的實現(xiàn)流程與 Http11NioProtocol 相同,下面我們以 Http11NioProtocol 為類重點說明 tomcat 中如何實現(xiàn) ProtocolHander 接口的。

Http11NioProtocol 實現(xiàn)了 ProtocolHander 接口,它將所有的操作委托給 NioEndpoint 類去做,如下圖:

NioEndpoint 類中的 init 方法中首先以普通阻塞方式啟動了 SocketServer:

NioEndpoint 類的 start 方法是關鍵,如下:

可以看出,在 start 方法中啟動了兩個線程和一個線程池:

  • Acceptor 線程,該線程以普通阻塞方式接收客戶端請求(socket.accep()),將客戶 Socket 交由線程池是處理,線程池要將該 Socket 配置成非阻塞模式(socket.configureBlocking(false)), 并且向 Selector 注冊 READ 事件。該線程數(shù)目可配置,默認為 1 個。
  • Poller 線程,由于 Acceptor 委托線程為客戶端 Socket 注冊了 READ 事件,當 READ 準備好時,就會進入 Poller 線程的循環(huán),Poller 線程也是委托線程池去做,線程池將 NioChannel 加入到 ConcurrentLinkedQueue<NioChannel> 隊列中。該線程數(shù)目可配置,默認為 1 個。
  • 線程池,就是上面說的做 Acceptor 與 Poller 線程委托要做的事情。

4.1 Init 接口實現(xiàn)方法中阻塞方式啟動 ServerSocketChannel

在 Init 接口實現(xiàn)方法中阻塞方式啟動 ServerSocketChannel。

4.2 Start 接口實現(xiàn)方法中啟動所有線程

Start 方法中啟動了線程池,acceptor 線程與 Poller 線程。其中 acceptor 與 poller 線程一般數(shù)目為 1,當然,數(shù)目也可配置。

可以看出,線程池有兩種實現(xiàn)方式:

  • 普通 queue + wait + notify 方式,默認使用的方式,據(jù)說實際測試這種比下種效率高
  • JDK1.5 自帶的線程池方式

4.3 Acceptor 線程接收客戶請求、注冊 READ 事件

在 Acceptor 線程中接收了客戶請求,同時委托線程池注冊 READ 事件。

  • 在 Acceptior 線程中接收了客戶請求(serverSock.accept())
  • 委托線程池處理
  • 在線程池的 Worker 線程的 run 方法中有這么幾句:
  • 在 setSocketOptions 方法中,首先將 socket 配置成非阻塞模式:

    在 setSocketOptions 方法中,最后調(diào)用 getPoller0().register(channel); 一句為 SocketChannel 注冊 READ 事件,register 方法代碼如下 (注意:這是 Poller 線程的方法):

    其中 attachment 的結(jié)構(gòu)如下,它可以看做是一個共享的數(shù)據(jù)結(jié)構(gòu):

    4.4 Poller線程讀請求、生成響應數(shù)據(jù)、注冊 WRITE 事件

  • 在上面說的 setSocketOptions 方法中調(diào)用 Poller 線程的 register 方法注冊讀事件之后,當 READ 準備就緒之后,就開始讀了。下面代碼位于 Poller 線程的 run 方法之中:
  • 可以看到,可讀之后調(diào)用 processSocket 方法,該方法將讀處理操作委拖給線程池處理 (注意此時加入到線程池的是 NioChannel,不是 SocketChannel):
  • 線程池的 Worker 線程中的 run 方法中的部分代碼如下(請注意 handler.process(socket) 這一句):
  • 注意:

    • 調(diào)用了 hanler.process(socket) 來生成響應數(shù)據(jù))
    • 數(shù)據(jù)生成完之后,注冊 WRITE 事件的,代碼如下:

    4.5 Handle 接口實現(xiàn)類通過 Adpater 調(diào)用 Servlet 容器生成響應數(shù)據(jù)

    NioEndpoint 類中的 Handler 接口定義如下:

    其中 process 方法通過 Adapter 來調(diào)用 Servlet Container 生成返回結(jié)果。Adapter 接口定義如下:

    4.6 小結(jié)

    實現(xiàn)一個 tomcat 連接器 Connector 就是實現(xiàn) ProtocolHander 接口的過程。Connector 用來接收 Socket Client 端的請求,通過內(nèi)置的線程池去調(diào)用 Servlet Container 生成響應結(jié)果,并將響應結(jié)果同步或異步的返回給 Socket Client。在第三方應用集成 tomcat 作為 Web 容器時,一般不會動 Servlet Container 端的代碼,那么 connector 的性能將是整個 Web 容器性能的關鍵。

    轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/11253524.html

    總結(jié)

    以上是生活随笔為你收集整理的Tomcat 处理 HTTP 请求源码分析(下)【转】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。