日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

Tomcat深入解析與性能優(yōu)化

 

前言

 

在 JAVA 應(yīng)用中,常用的 Web 服務(wù)器一般由 Tomcat、weblogic、jetty、undertwo等。但從 Java 2019和2020 生態(tài)使用報(bào)告可以看到,tomcat的用戶(hù)量對(duì)比明顯較大,當(dāng)然這也基于它開(kāi)源和免費(fèi)的特點(diǎn)。

 

Java 2019 年生態(tài)圈使用報(bào)告

Tomcat深入解析與性能優(yōu)化

 

2020 Java 生態(tài)系統(tǒng)報(bào)告

Tomcat深入解析與性能優(yōu)化

 

從軟件架構(gòu)的發(fā)展角度來(lái)看,軟件架構(gòu)大致經(jīng)歷了如下幾個(gè)階段:

Tomcat深入解析與性能優(yōu)化

 

從 Java Web 角度來(lái)說(shuō),架構(gòu)大致經(jīng)歷了:

Tomcat深入解析與性能優(yōu)化

 

從當(dāng)前企業(yè)使用的架構(gòu)角度來(lái)說(shuō),使用SSM架構(gòu)項(xiàng)目比較多,SSH基本被淘汰(大部分是老項(xiàng)目維護(hù)),很大一部分企業(yè)轉(zhuǎn)向微服務(wù)架構(gòu)了。

 

基于Spring 生態(tài)來(lái)說(shuō),大部分中小型企業(yè)都基本使用SpringBoot,SpringBoot本身集成了 tomcat、jetty和undertwo 容器,那么我們?yōu)槭裁葱枰〞r(shí)間來(lái)研究tomcat呢?

  1. 當(dāng)前tomcat依然是主流java web容器,研究它符合java 技術(shù)生態(tài)發(fā)展;
  2. 在java web項(xiàng)目調(diào)優(yōu)中,如ssm項(xiàng)目中,在優(yōu)化項(xiàng)目時(shí),jvm和tomcat同樣重要,都需要優(yōu)化;
  3. 盡管springboot內(nèi)置了tomcat容器,且配置了默認(rèn)的tomcat參數(shù),但當(dāng)默認(rèn)的tomcat參數(shù)滿足不了項(xiàng)目?jī)?yōu)化要求時(shí),就需要優(yōu)化人員手動(dòng)進(jìn)行相關(guān)的參數(shù)優(yōu)化,因此研究tomcat非常必要;
  4. 熟悉tomcat架構(gòu),是后續(xù)進(jìn)行項(xiàng)目?jī)?yōu)化的基礎(chǔ),也是必備條件。

Tomcat架構(gòu)說(shuō)明


知識(shí)點(diǎn):

 

  1. Tomcat目錄結(jié)構(gòu)
  2. Tomcat簡(jiǎn)要架構(gòu)
  3. Tomcat各組件及關(guān)系
  4. Tomcat server.xml配置詳解
  5. Tomcat啟動(dòng)參數(shù)說(shuō)明(啟動(dòng)腳本)

 

Tomcat 是一個(gè)基于JAVA的WEB容器,其實(shí)現(xiàn)了JAVA EE中的 Servlet 與 jsp 規(guī)范,與Nginx Apache 服務(wù)器不同在于一般用于動(dòng)態(tài)請(qǐng)求處理。在架構(gòu)設(shè)計(jì)上采用面向組件的方式設(shè)計(jì)。即整體功能是通過(guò)組件的方式拼裝完成。另外每個(gè)組件都可以被替換以保證靈活性。

Tomcat深入解析與性能優(yōu)化

 

通過(guò)Tomcat官方可以看到,目前已經(jīng)更新到Tomcat 10了,但當(dāng)前大部分企業(yè)使用的Tomcat 為8或者9版本。

Tomcat深入解析與性能優(yōu)化

 

Tomcat 目錄結(jié)構(gòu)

Tomcat深入解析與性能優(yōu)化

 

  • bin:可執(zhí)行文件,.sh結(jié)尾的表示linux可執(zhí)行文件,.bat結(jié)尾的表示windows可執(zhí)行文件
  • conf:配置文件
  • lib:tomcat相關(guān)jar包
  • temp:臨時(shí)文件
  • webApps:存放項(xiàng)目
  • work:工作目錄

bin目錄

 

bin目錄存放可執(zhí)行文件,簡(jiǎn)要結(jié)束常用命令

Tomcat深入解析與性能優(yōu)化

 

這里主要解釋如下通用的命令,其他命令就不一一介紹

  • catalina.sh 真正啟動(dòng)Tomcat文件,可以在里面設(shè)置jvm參數(shù)
  • startup.sh 程序項(xiàng)目命令文件
  • version.sh 查看tomcat版本相關(guān)信息命令文件
  • shutdown.sh 關(guān)閉程序命令

 

conf目錄

 

conf文件夾用來(lái)存放tomcat相關(guān)配置文件

Tomcat深入解析與性能優(yōu)化

 

1.catalina.policy

 

項(xiàng)目安全文件,用來(lái)防止欺騙代碼或JSP執(zhí)行帶有像System.exit(0)這樣的命令的可能影響容器的破壞性代碼. 只有當(dāng)Tomcat用-security命令行參數(shù)啟動(dòng)時(shí)這個(gè)文件才會(huì)被使用,即啟動(dòng)tomcat時(shí), startup.sh -security 。

Tomcat深入解析與性能優(yōu)化

 

上圖中,tomcat容器下部署兩個(gè)項(xiàng)目,項(xiàng)目1和項(xiàng)目2。由于項(xiàng)目1中有代碼System.exit(0),當(dāng)訪問(wèn)該代碼時(shí),該代碼會(huì)導(dǎo)致整個(gè)tomcat停止,從而也導(dǎo)致項(xiàng)目2停止。

 

為了解決因項(xiàng)目1存在欺騙代碼或不安全代碼導(dǎo)致?lián)p害Tomcat容器,從而影響其他項(xiàng)目正常運(yùn)行的問(wèn)題,啟動(dòng)tomcat容器時(shí),加上-security參數(shù)就,即startup.sh -security,如此即使項(xiàng)目1中有代碼System.exit(0),也只會(huì)僅僅停止項(xiàng)目1,而不會(huì)影響Tomcat容器,然而起作用的配置文件就是catalina.policy文件。

 

2.catalina.properties

 

配置tomcat啟動(dòng)相關(guān)信息文件

 

3.context.xml

 

監(jiān)視并加載資源文件,當(dāng)監(jiān)視的文件發(fā)生發(fā)生變化時(shí),自動(dòng)加載

Tomcat深入解析與性能優(yōu)化

 

 

4.jaspic-providers.xml 和 jaspic-providers.xsd

 

這兩個(gè)文件不常用

 

5.logging.properties

 

該文件為tomcat日志文件,包括配置tomcat輸出格式,日志級(jí)別等

 

6.server.xml

 

tomcat核心架構(gòu)主件文件,下面會(huì)詳細(xì)解析。

 

7.tomcat-users.xml和tomcat-users.xsd

 

tomcat用戶(hù)文件,如配置遠(yuǎn)程登陸賬號(hào)

 

tomcat-users.xsd 為tomcat-users.xml描述和約束文件

 

8.web.xml

 

tomcat全局配置文件。

 

lib目錄

 

lib文件夾主要用來(lái)存放tomcat依賴(lài)jar包,如下為 tomcat 的lib文件夾下的相關(guān)jar包。

Tomcat深入解析與性能優(yōu)化

 

每個(gè)jar包功能,這里就不講解了,這里主要分析ecj-4.13.jar,這個(gè)jar包起到將.java編譯成.class字節(jié)碼作用。

 

假設(shè)要編譯MyTest.java,那么jdk會(huì)執(zhí)行兩步:

  • 第一步:將MyTest.java編譯成MyTest.class

javac MyTest.java

  • 第二步:執(zhí)行MyTest.class

java MyTest.class

  • 那么,使用ecj-4.13.jar如執(zhí)行MyTest.java呢?

java -jar ecj-4.13.jar MyTest.java

 

logs目錄

 

該文件夾表示tomcat日志文件,大致包括如下六類(lèi)文件:

Tomcat深入解析與性能優(yōu)化

 


Tomcat深入解析與性能優(yōu)化

 

temp目錄

 

temp目錄用戶(hù)存放tomcat在運(yùn)行過(guò)程中產(chǎn)生的臨時(shí)文件。(清空不會(huì)對(duì)tomcat運(yùn)行帶來(lái)影響)。

 

webapps目錄

 

webapps目錄用來(lái)存放應(yīng)用程序,當(dāng)tomcat啟動(dòng)時(shí)會(huì)去加載webapps目錄下的應(yīng)用程序。可以以文件夾、war包、jar包的形式發(fā)布應(yīng)用。

當(dāng)然,你也可以把應(yīng)用程序放置在磁盤(pán)的任意位置,在配置文件中映射好就行。

 

work目錄

 

work目錄用來(lái)存放tomcat在運(yùn)行時(shí)的編譯后文件,例如JSP編譯后的文件。

清空work目錄,然后重啟tomcat,可以達(dá)到清除緩存的作用。

 

Tomcat 簡(jiǎn)要架構(gòu)

 

Tomcat深入解析與性能優(yōu)化

 

Tomcat 各組件及關(guān)系

  • Server 和 Service
  • Connector 連接器
    • HTTP 1.1
    • SSL https
    • AJP( Apache JServ Protocol) apache 私有協(xié)議,用于apache 反向代理Tomcat
  • Container
    • Engine 引擎 catalina
    • Host 虛擬機(jī) 基于域名 分發(fā)請(qǐng)求
    • Context 隔離各個(gè)WEB應(yīng)用 每個(gè)Context的 ClassLoader都是獨(dú)立
  • Component
    • Manager (管理器)
    • logger (日志管理)
    • loader (載入器)
    • pipeline (管道)
    • valve (管道中的閥)

 

Tomcat深入解析與性能優(yōu)化

 

Tomcat server.xml 配置詳解


Server 的基本基本配置:

<Server>
    <Listener /><!-- 監(jiān)聽(tīng)器 -->
    <GlobaNamingResources> <!-- 全局資源 -->
    </GlobaNamingResources
    <Service>          <!-- 服務(wù) 用于 綁定 連接器與 Engine -->
        <Connector 8080/> <!-- 連接器-->
        <Connector 8010 /> <!-- 連接器-->
        <Connector 8030/> <!-- 連接器-->
        
        <Engine>      <!-- 執(zhí)行引擎-->
            <Logger />
            <Realm />
               <host "www.test.com" appBase="">  <!-- 虛擬主機(jī)-->
                   <Logger /> <!-- 日志配置-->
                   <Context "/applction" path=""/> <!-- 上下文配置-->
               </host>
        </Engine>
    </Service>
</Server>

 

server

root元素:server 的頂級(jí)配置

主要屬性:

port:執(zhí)行關(guān)閉命令的端口號(hào)

shutdown:關(guān)閉命令

 

  • 演示shutdown的用法
#基于telent 執(zhí)行SHUTDOWN 命令即可關(guān)閉
telent 127.0.0.1 8005
SHUTDOWN

 

service

 

服務(wù):將多個(gè)connector 與一個(gè)Engine組合成一個(gè)服務(wù),可以配置多個(gè)服務(wù)。

 

Connector

 

連接器:用于接收 指定協(xié)議下的連接 并指定給唯一的Engine 進(jìn)行處理。

 

主要屬性:

  • protocol 監(jiān)聽(tīng)的協(xié)議,默認(rèn)是http/1.1
  • port 指定服務(wù)器端要?jiǎng)?chuàng)建的端口號(hào)
  • minThread 服務(wù)器啟動(dòng)時(shí)創(chuàng)建的處理請(qǐng)求的線程數(shù)
  • maxThread 最大可以創(chuàng)建的處理請(qǐng)求的線程數(shù)
  • enableLookups 如果為true,則可以通過(guò)調(diào)用request.getRemoteHost()進(jìn)行DNS查詢(xún)來(lái)得到遠(yuǎn)程客戶(hù)端的實(shí)際主機(jī)名,若為false則不進(jìn)行DNS查詢(xún),而是返回其ip地址
  • redirectPort 指定服務(wù)器正在處理http請(qǐng)求時(shí)收到了一個(gè)SSL傳輸請(qǐng)求后重定向的端口號(hào)
  • acceptCount 指定當(dāng)所有可以使用的處理請(qǐng)求的線程數(shù)都被使用時(shí),可以放到處理隊(duì)列中的請(qǐng)求數(shù),超過(guò)這個(gè)數(shù)的請(qǐng)求將不予處理,默認(rèn)100;
  • address 綁定客戶(hù)端特定地址,127.0.0.1
  • bufferSize 每個(gè)請(qǐng)求的緩沖區(qū)大小 bufferSize * maxThreads
  • compression 是否啟用文檔壓縮
  • compressionMinSize 文檔壓縮的最小大小
  • compressableMimeTypes text/html,text/xml,text/plain
  • connectionTimeout 客戶(hù)端發(fā)起鏈接到服務(wù)端接收為止,指定超時(shí)的時(shí)間數(shù)(以毫秒為單位)
  • connectionUploadTimeout upload情況下連接超時(shí)時(shí)間
  • disableUploadTimeout 如果為true則使用 connectionTimeout
  • keepAliveTimeout 當(dāng)長(zhǎng)鏈接閑置 指定時(shí)間主動(dòng)關(guān)閉 鏈接 ,前提是客戶(hù)端請(qǐng)求頭 帶上這個(gè) head"connection" " keep-alive"
  • maxKeepAliveRequests 最大的 長(zhǎng)連接數(shù) 默認(rèn)最大100
  • maxSpareThreads BIO 模式下 最多線閑置線程數(shù)
  • minSpareThreads BIO 模式下 最小線閑置線程數(shù)
  • SSLEnabled 是否開(kāi)啟 sll 驗(yàn)證,在Https 訪問(wèn)時(shí)需要開(kāi)啟。

 

  • 演示配置多個(gè)Connector
 <Connector port="8860" protocol="org.apache.coyote.http11.Http11NioProtocol"
                connectionTimeout="20000"
                redirectPort="8862"
                URIEncoding="UTF-8"
                useBodyEncodingForURI="true"
                compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/JavaScript,text/css,application/x-json,application/json,application/x-javascript"
                maxThreads="1024" minSpareThreads="200"
                acceptCount="800"
                enableLookups="false"
        />

 

Engine

 

引擎:用于處理連接的執(zhí)行器,默認(rèn)的引擎是catalina。一個(gè)service 中只能配置一個(gè)Engine。

主要屬性:name 引擎名稱(chēng) defaultHost 默認(rèn)host

 

Host

虛擬機(jī):基于域名匹配至指定虛擬機(jī)。類(lèi)似于nginx 當(dāng)中的server,默認(rèn)的虛擬機(jī)是localhost.

  • 演示配置多個(gè)Host
<Host name="www.test.com"  appBase="/usr/www/test"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"               prefix="www.luban.com.access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
</Host>

 

Context

 

應(yīng)用上下文:一個(gè)host 下可以配置多個(gè)Context ,每個(gè)Context 都有其獨(dú)立的classPath。相互隔離,以免造成ClassPath 沖突。

 

  • 演示配置多個(gè)Context
<Context docBase="hello" path="/h" reloadable="true"/>

 

Valve

 

閥門(mén):可以理解成request 的過(guò)濾器,具體配置要基于具體的Valve 接口的子類(lèi)。以下即為一個(gè)訪問(wèn)日志的Valve.

 

 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="www.luban.com.access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

 

Tomcat啟動(dòng)參數(shù)說(shuō)明

 

我們平時(shí)啟動(dòng)Tomcat過(guò)程是怎么樣的?

  1. 復(fù)制WAR包至Tomcat webapp 目錄。
  2. 執(zhí)行starut.bat 腳本啟動(dòng)。
  3. 啟動(dòng)過(guò)程中war 包會(huì)被自動(dòng)解壓裝載。

但是我們?cè)贓clipse 或idea 中啟動(dòng)WEB項(xiàng)目的時(shí)候 也是把War包復(fù)雜至webapps 目錄解壓?jiǎn)幔匡@然不是,其真正做法是在Tomcat程序文件之外創(chuàng)建了一個(gè)部署目錄,在一般生產(chǎn)環(huán)境中也是這么做的 即:Tomcat 程序目錄和部署目錄分開(kāi) 。

我們只需要在啟動(dòng)時(shí)指定CATALINA_HOME 與 CATALINA_BASE 參數(shù)即可實(shí)現(xiàn)。

Tomcat深入解析與性能優(yōu)化

 

可以編寫(xiě)一個(gè)腳本 來(lái)實(shí)現(xiàn)自定義配置:

更新 啟動(dòng) 腳本

#!/bin/bash -e
export now_time=$(date +%Y-%m-%d_%H-%M-%S)
echo "deploy time:$now_time"

app=$1
version=$2
mkdir -p war/
#從svn下載程序至 war目錄
war=war/${app}_${version}.war
echo "$war"
svn export svn://192.168.0.253/release/${app}_${version}.war $war

deploy_war() {
#解壓版本至當(dāng)前目錄
target_dir=war/${app}_${version}_${now_time}
unzip -q $war -d $target_dir
rm -f appwar
ln -sf $target_dir appwar
target_ln=`pwd`/appwar
echo '<?xml version="1.0" encoding="UTF-8" ?>
<Context docBase="'$target_ln'" allowLinking="false">
</Context>' > conf/Catalina/localhost/ROOT.xml
#重啟Tomcat服務(wù)
./tomcat.sh restart
}

deploy_war
```

 

自動(dòng)部署腳本

#!/bin/bash -e
export now_time=$(date +%Y-%m-%d_%H-%M-%S)
echo "deploy time:$now_time"

app=$1
version=$2
mkdir -p war/
#從svn下載程序至 war目錄
war=war/${app}_${version}.war
echo "$war"
svn export svn://192.168.0.253/release/${app}_${version}.war $war

deploy_war() {
#解壓版本至當(dāng)前目錄
target_dir=war/${app}_${version}_${now_time}
unzip -q $war -d $target_dir
rm -f appwar
ln -sf $target_dir appwar
target_ln=`pwd`/appwar
echo '<?xml version="1.0" encoding="UTF-8" ?>
<Context docBase="'$target_ln'" allowLinking="false">
</Context>' > conf/Catalina/localhost/ROOT.xml
#重啟Tomcat服務(wù)
./tomcat.sh restart
}

deploy_war
```

 

Tomcat 網(wǎng)絡(luò)通信模型剖析


Tomcat 支持四種線程模型介紹

 

什么是IO?

IO是指為數(shù)據(jù)傳輸所提供的輸入輸出流,其輸入輸出對(duì)象可以是:文件、網(wǎng)絡(luò)服務(wù)、內(nèi)存等。

Tomcat深入解析與性能優(yōu)化

 

什么是IO模型?

 

提問(wèn):

假設(shè)應(yīng)用在從硬盤(pán)中讀取一個(gè)大文件過(guò)程中,此時(shí)CPU會(huì)與硬盤(pán)一樣處于高負(fù)荷狀態(tài)么?

 

演示:

  • 演示觀察大文件的讀寫(xiě)過(guò)程當(dāng)中CPU 有沒(méi)有發(fā)生大波動(dòng)。

 

演示結(jié)果:CPU 沒(méi)有太高的增長(zhǎng)

 

通常情況下IO操作是比較耗時(shí)的,所以為了高效的使用硬件,應(yīng)用程序可以用一個(gè)專(zhuān)門(mén)線程進(jìn)行IO操作,而另外一個(gè)線程則利用CPU的空閑去做其它計(jì)算。這種為提高應(yīng)用執(zhí)行效率而采用的IO操作方法即為IO模型。

 

各IO模型簡(jiǎn)要說(shuō)明

BIO

阻塞式IO,即Tomcat使用傳統(tǒng)的java.io進(jìn)行操作。該模式下每個(gè)請(qǐng)求都會(huì)創(chuàng)建一個(gè)線程,對(duì)性能開(kāi)銷(xiāo)大,不適合高并發(fā)場(chǎng)景。優(yōu)點(diǎn)是穩(wěn)定,適合連接數(shù)目小且固定架構(gòu)。

NIO

非阻塞式IO,jdk1.4 之后實(shí)現(xiàn)的新IO。該模式基于多路復(fù)用選擇器監(jiān)測(cè)連接狀態(tài)在通知線程處理,從而達(dá)到非阻塞的目的。比傳統(tǒng)BIO能更好的支持并發(fā)性能。Tomcat 8.0之后默認(rèn)采用該模式

APR

全稱(chēng)是 Apache Portable Runtime/Apache可移植運(yùn)行庫(kù)),是Apache HTTP服務(wù)器的支持庫(kù)。可以簡(jiǎn)單地理解為,Tomcat將以JNI的形式調(diào)用Apache HTTP服務(wù)器的核心動(dòng)態(tài)鏈接庫(kù)來(lái)處理文件讀取或網(wǎng)絡(luò)傳輸操作。使用需要編譯安裝APR 庫(kù)

AIO

異步非阻塞式IO,jdk1.7后之支持 。與nio不同在于不需要多路復(fù)用選擇器,而是請(qǐng)求處理線程執(zhí)行完成進(jìn)行回調(diào)調(diào)制,已繼續(xù)執(zhí)行后續(xù)操作。Tomcat 8之后支持。

Tomcat深入解析與性能優(yōu)化

 

使用指定IO模型的配置方式:

 

配置 server.xml 文件當(dāng)中的 <Connector protocol="HTTP/1.1"> 修改即可。

默認(rèn)配置 8.0 protocol=“HTTP/1.1” 8.0 之前是 BIO, 8.0 之后是 NIO

 

  • BIO

protocol=“org.apache.coyote.http11.Http11Protocol”

  • NIO

protocol=“org.apache.coyote.http11.Http11NioProtocol”

  • AIO

protocol=“org.apache.coyote.http11.Http11Nio2Protocol”

  • APR

protocol=“org.apache.coyote.http11.Http11AprProtocol”

 

Tomcat BIO、NIO實(shí)現(xiàn)過(guò)程源碼解析

 

BIO 與NIO區(qū)別

分別演示在高并發(fā)場(chǎng)景下BIO與NIO的線程數(shù)的變化?

Tomcat深入解析與性能優(yōu)化

 

BIO 配置

<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on" compressionMinSize="1024"
               compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript"
               maxThreads="500" minSpareThreads="1"/>

 

NIO配置

 <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on" compressionMinSize="1024"
               compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript"
               maxThreads="500" minSpareThreads="1"/>

 

演示數(shù)據(jù):

Tomcat深入解析與性能優(yōu)化

 

生成環(huán)境重要因素:

  1. 網(wǎng)絡(luò)
  2. 程序執(zhí)行業(yè)務(wù)用時(shí)

 

源代碼地址:https://github.com/org-hejianhui/bit-bigdata-transmission

 

BIO 線程模型

Tomcat深入解析與性能優(yōu)化

 

BIO 源碼

 

線程組:

Accept 線程組 acceptorThreadCount 默認(rèn)1個(gè)

exec 線程組 maxThread

JIoEndpoint

Acceptor extends Runnable

SocketProcessor extends Runnable

Tomcat深入解析與性能優(yōu)化

 

NIO 線程模型

Tomcat深入解析與性能優(yōu)化

 

NIO 線程模型

 

Accept 線程組 默認(rèn)兩個(gè)輪詢(xún)器

Poller Selector PollerEvent輪詢(xún)線程狀態(tài)

SocketProcessor

Tomcat深入解析與性能優(yōu)化

 

 

BIO

線程數(shù)量 會(huì)受到 客戶(hù)端阻塞、網(wǎng)絡(luò)延遲、業(yè)務(wù)處理慢===>線程數(shù)會(huì)更多。

 

NIO

線程數(shù)量 會(huì)受到業(yè)務(wù)處理慢===>線程數(shù)會(huì)更多。

 

Tomcat connector 并發(fā)參數(shù)解讀

 

Tomcat深入解析與性能優(yōu)化

 

Tomcat 類(lèi)加載機(jī)制源碼解析

 

類(lèi)加載的本質(zhì)

 

是用來(lái)加載 Class 的。它負(fù)責(zé)將 Class 的字節(jié)碼形式轉(zhuǎn)換成內(nèi)存形式的 Class 對(duì)象。字節(jié)碼可以來(lái)自于磁盤(pán)文件 .class,也可以是 jar 包里的 .class,也可以來(lái)自遠(yuǎn)程服務(wù)器提供的字節(jié)流,字節(jié)碼的本質(zhì)就是一個(gè)字節(jié)數(shù)組 []byte,它有特定的復(fù)雜的內(nèi)部格式。

 

JVM 運(yùn)行實(shí)例中會(huì)存在多個(gè) ClassLoader,不同的 ClassLoader 會(huì)從不同的地方加載字節(jié)碼文件。它可以從不同的文件目錄加載,也可以從不同的 jar 文件中加載,也可以從網(wǎng)絡(luò)上不同的靜態(tài)文件服務(wù)器來(lái)下載字節(jié)碼再加載。

 

jvm里ClassLoader的層次結(jié)構(gòu)

Tomcat深入解析與性能優(yōu)化

 

類(lèi)加載器層次結(jié)構(gòu)

 

BootstrapClassLoader(啟動(dòng)類(lèi)加載器)

 

稱(chēng)為啟動(dòng)類(lèi)加載器,是Java類(lèi)加載層次中最頂層的類(lèi)加載器,負(fù)責(zé)加載JDK中的核心類(lèi)庫(kù),如:rt.jar、resources.jar、charsets.jar等,可通過(guò)如下程序獲得該類(lèi)加載器從哪些地方加載了相關(guān)的jar或class文件:

URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL url : urLs) {
    System.out.println(url.toExternalForm());
}

程序執(zhí)行結(jié)果如下:

file:/Library/Java/JavaVirtualmachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/classes

從rt.jar中選擇String類(lèi),看一下String類(lèi)的類(lèi)加載器是什么

ClassLoader classLoader = String.class.getClassLoader();
System.out.println(classLoader);

執(zhí)行結(jié)果如下:

null

 

可知由于BootstrapClassLoader對(duì)Java不可見(jiàn),所以返回了null,我們也可以通過(guò)某一個(gè)類(lèi)的加載器是否為null來(lái)作為判斷該類(lèi)是不是使用BootstrapClassLoader進(jìn)行加載的依據(jù)。

 

ExtensionClassLoader

 

ExtClassLoader稱(chēng)為擴(kuò)展類(lèi)加載器,主要負(fù)責(zé)加載Java的擴(kuò)展類(lèi)庫(kù),默認(rèn)加載JAVA_HOME/jre/lib/ext/目錄下的所有jar包或者由java.ext.dirs系統(tǒng)屬性指定的jar包.放入這個(gè)目錄下的jar包對(duì)AppClassLoader加載器都是可見(jiàn)的(因?yàn)镋xtClassLoader是AppClassLoader的父加載器,并且Java類(lèi)加載器采用了委托機(jī)制)。

 

ExtClassLoader的類(lèi)掃描路徑通過(guò)執(zhí)行下面代碼來(lái)看一下:

String extDirs = System.getProperty("java.ext.dirs");
for (String path : extDirs.split(";")) {
System.out.println(path);
}

執(zhí)行結(jié)果如下(Mac系統(tǒng)):

/Users/hjh/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

jre/lib/ext路徑下內(nèi)容為:

Tomcat深入解析與性能優(yōu)化

 

從上面的路徑中隨意選擇一個(gè)類(lèi),來(lái)看看它的類(lèi)加載器是什么:

sun.misc.Launcher$ExtClassLoader@4439f31e
null

從上面的程序運(yùn)行結(jié)果可知ExtClassLoader的父加載器為null,之前說(shuō)過(guò)BootstrapClassLoader對(duì)Java不可見(jiàn),所以返回了null。ExtClassLoader的父加載器返回的是null,那是否說(shuō)明ExtClassLoader的父加載器是BootstrapClassLoader?

 

Bootstrap ClassLoader是由C/C++編寫(xiě)的,它本身是虛擬機(jī)的一部分,所以它并不是一個(gè)JAVA類(lèi),也就是無(wú)法在java代碼中獲取它的引用,JVM啟動(dòng)時(shí)通過(guò)Bootstrap類(lèi)加載器加載rt.jar等核心jar包中的class文件,之前的int.class,String.class都是由它加載。然后呢,我們前面已經(jīng)分析了,JVM初始化sun.misc.Launcher并創(chuàng)建Extension ClassLoader和AppClassLoader實(shí)例。并將ExtClassLoader設(shè)置為AppClassLoader的父加載器。Bootstrap沒(méi)有父加載器,但是它卻可以作用一個(gè)ClassLoader的父加載器。比如ExtClassLoader。這也可以解釋之前通過(guò)ExtClassLoader的getParent方法獲取為Null的現(xiàn)象

 

AppClassLoader

才是直接面向我們用戶(hù)的加載器,它會(huì)加載 Classpath 環(huán)境變量里定義的路徑中的 jar 包和目錄。我們自己編寫(xiě)的代碼以及使用的第三方 jar 包通常都是由它來(lái)加載的。

 

加載System.getProperty("java.class.path")所指定的路徑或jar。在使用Java運(yùn)行程序時(shí),也可以加上-cp來(lái)覆蓋原有的Classpath設(shè)置,例如: java -cp ./lavasoft/classes HelloWorld

 

public class AppClassLoaderTest {
    public static void main(String[] args) {
        System.out.println(ClassLoader.getSystemClassLoader());
    }
}

 

輸出結(jié)果如下:

sun.misc.Launcher$AppClassLoader@18b4aac2

 

以上結(jié)論說(shuō)明調(diào)用ClassLoader.getSystemClassLoader()可以獲得AppClassLoader類(lèi)加載器。

protected ClassLoader() {
    this(checkCreateClassLoader(), getSystemClassLoader());
}

通過(guò)查看ClassLoader的源碼發(fā)現(xiàn)并且在沒(méi)有特定說(shuō)明的情況下,用戶(hù)自定義的任何類(lèi)加載器都將該類(lèi)加載器作為自定義類(lèi)加載器的父加載器。

 

通過(guò)執(zhí)行上面的代碼即可獲得classpath的加載路徑。

 

在上面的main函數(shù)的類(lèi)的加載就是使用AppClassLoader加載器進(jìn)行加載的,可以通過(guò)執(zhí)行下面的代碼得出這個(gè)結(jié)論

public class AppClassLoaderTest {

    public static void main(String[] args) {
        ClassLoader classLoader = Test.class.getClassLoader();
        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
    }

    private static class Test {

    }

}

 

執(zhí)行結(jié)果如下:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@2d209079

從上面的運(yùn)行結(jié)果可以得知AppClassLoader的父加載器是ExtClassLoader

 

Tomcat的 類(lèi)加載順序

 

Tomcat深入解析與性能優(yōu)化

 

在Tomcat中,默認(rèn)的行為是先嘗試在Bootstrap和Extension中進(jìn)行類(lèi)型加載,如果加載不到則在Webapp ClassLoader中進(jìn)行加載,如果還是找不到則在Common中進(jìn)行查找。

 

NoClassDefFoundError

 

NoClassDefFoundError是在開(kāi)發(fā)JavaEE程序中常見(jiàn)的一種問(wèn)題。該問(wèn)題會(huì)隨著你所使用的JavaEE中間件環(huán)境的復(fù)雜度以及應(yīng)用本身的體量變得更加復(fù)雜,尤其是現(xiàn)在的JavaEE服務(wù)器具有大量的類(lèi)加載器。

在JavaDoc中對(duì)NoClassDefFoundError的產(chǎn)生是由于JVM或者類(lèi)加載器實(shí)例嘗試加載類(lèi)型的定義,但是該定義卻沒(méi)有找到,影響了執(zhí)行路徑。換句話說(shuō),在編譯時(shí)這個(gè)類(lèi)是能夠被找到的,但是在執(zhí)行時(shí)卻沒(méi)有找到。

這一刻IDE是沒(méi)有出錯(cuò)提醒的,但是在運(yùn)行時(shí)卻出現(xiàn)了錯(cuò)誤。

 

NoSuchMethodError

 

在另一個(gè)場(chǎng)景中,我們可能遇到了另一個(gè)錯(cuò)誤,也就是NoSuchMethodError。

NoSuchMethodError代表這個(gè)類(lèi)型確實(shí)存在,但是一個(gè)不正確的版本被加載了。

 

ClassCastException

 

ClassCastException,在一個(gè)類(lèi)加載器的情況下,一般出現(xiàn)這種錯(cuò)誤都會(huì)是在轉(zhuǎn)型操作時(shí),比如:A a = (A) method();,很容易判斷出來(lái)method()方法返回的類(lèi)型不是類(lèi)型A,但是在 JavaEE 多個(gè)類(lèi)加載器的環(huán)境下就會(huì)出現(xiàn)一些難以定位的情況。

 

部分圖片來(lái)源于網(wǎng)絡(luò),版權(quán)歸原作者,侵刪。

分享到:
標(biāo)簽:Tomcat
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定