Tomcat篇03-使用Jmeter對Tomcat9的三種IO模型進行持續(xù)壓力測試

image

本文主要包括Tomcat9的NIO缀磕、NIO2、APR三種I/O模型的工作原理以及使用Jmeter對其進行持續(xù)壓力測試。

1晶疼、connector的工作原理

這里我們說的Tomcat中三種不同的I/O模型主要指的是其連接器(connector)的工作模型,對于tomcat而言又憨,連接器一般指的是coyote翠霍,其工作原理大致如下圖所示:

image

連接器中的各個組件的作用如下:

1.1 EndPoint

EndPoint即Coyote通信端點,是通信監(jiān)聽的接口蠢莺,是具體Socket接收和發(fā)送處理器寒匙,是對傳輸層(四層)的抽象,因此EndPoint用來實現TCP/IP協議的躏将。Tomcat 并沒有EndPoint接口锄弱,而是提供了一個抽象類AbstractEndpoint, 里面定義了兩個內部類:AcceptorSocketProcessor耸携。Acceptor用于監(jiān)聽Socket連接請求棵癣。 SocketProcessor用于處理接收到的Socket請求,它實現Runnable接口夺衍,在Run方法里 調用協議處理組件Processor進行處理狈谊。為了提高處理能力,SocketProcessor被提交到線程池來執(zhí)行,而這個線程池叫作執(zhí)行器(Executor)河劝。

1.2 Processor

Processor是coyote的協議處理接口 壁榕。如果說EndPoint是用來實現TCP/IP協議的,那么 Processor用來實現HTTP協議赎瞎,Processor接收來自EndPoint的Socket牌里,讀取字節(jié)流解析成Tomcat的RequestResponse對象,并通過Adapter將其提交到容器處理务甥, Processor是對應用層(七層)協議的抽象牡辽。

1.3 ProtocolHandler

ProtocolHandler是Coyote的協議接口,通過Endpoint和Processor 敞临,實現對具體協議(HTTP或AJP)的處理态辛。Tomcat 按照協議和I/O 提供了6個實現類 : AjpNioProtocolAjpAprProtocol挺尿, AjpNio2Protocol 奏黑, Http11NioProtocolHttp11Nio2Protocol 编矾, Http11AprProtocol熟史。我們在配置tomcat/conf/server.xml 中的connecter塊時 , 至少要指定具體的ProtocolHandler , 當然也可以指定協議名稱(如HTTP/1.1)窄俏。

1.4 Adapter

由于協議不同蹂匹,客戶端發(fā)過來的請求信息也不盡相同,Tomcat定義了自己的Request類來存放這些請求信息裆操。ProtocolHandler接口負責解析請求并生成Tomcat的Request類怒详。 但是這個Request對象不是標準的ServletRequest,不能用來作為參數來調用容器踪区。因此需要引入CoyoteAdapter,連接器調用CoyoteAdapterSevice方法吊骤,傳入Tomcat的Request對象缎岗,CoyoteAdapter將Request轉成ServletRequest,再調用容器的Service方法白粉。

2传泊、三種I/O模型原理

在開始之前,我們先看一下tomcat官網給出的這三種I/O模型的工作參數的一個對比圖:

image

這里我們可以看到一般說的NIO鸭巴、NIO2和APR使用的是非阻塞方式指的就是在讀取請求報頭等待下一個請求的時候是使用的非阻塞方式眷细。

Tomcat的NIO是基于I/O復用(同步I/O)來實現的,而NIO2是使用的異步I/O鹃祖。參考經典書籍《UNIX網絡編程 卷1 套接字聯網API》溪椎,兩者的主要原理如下:

I/O復用(NIO)

I/O復用(I/O multiplexing)可以調用selectpoll,阻塞在這兩個系統(tǒng)調用中的某一個之上,而不是阻塞在真正的I/O系統(tǒng)調用上校读。進程阻塞于select調用沼侣,等待數據報套接字變?yōu)榭勺x。當select返回套接字可讀這一條件時歉秫,進程調用recvfrom把所讀數據報復制到應用進程緩沖區(qū)蛾洛,盡管這里需要使用selectrecvfrom兩個系統(tǒng)調用,但是使用select的可以等待多個描述符就緒雁芙,即可以等待多個請求轧膘。

image

異步IO(NIO2)

異步I/O(asynchronous I/O)的工作機制是:告知內核啟動某個操作,并讓內核在整個操作(包括將數據從內核復制到應用程序的緩沖區(qū))完成后通知應用程序兔甘。需要注意的是:異步I/O模型是由內核通知應用進程I/O操作何時完成谎碍。

image

最后我們可以把上面的過程結合剩下沒有提到的三種UNIX系統(tǒng)中的IO模型進行對比得到下圖:

image

NIO、NIO2和APR的區(qū)別

NIO NIO2 APR
實現 JAVA NIO庫 JDK1.7 NIO2庫 C
IO模型 同步非阻塞 異步非阻塞 取決于系統(tǒng)

APR的重點在于使用C語言實現并且能夠跨平臺使用裂明,它相當于將UNIX系統(tǒng)中的IO操作進行了一層封裝使得編程開發(fā)更容易

3椿浓、connector的幾個重要參數

connectionTimeout

The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Use a value of -1 to indicate no (i.e. infinite) timeout. The default value is 60000 (i.e. 60 seconds) but note that the standard server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds). Unless disableUploadTimeout is set to false, this timeout will also be used when reading the request body (if any).

在connector和請求的客戶端建立連接之后開始計時,當超過該值的時候就會超時闽晦,然后斷開連接扳碍。使用值-1表示無超時,默認值為60000(即60秒)仙蛉,但Tomcat中的server.xml將此值設置為20000(即20秒)笋敞。

除非disableUploadTimeout設置為false,否則在讀取請求正文(如果有)時也會使用此超時荠瘪。

maxThreads

The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool. Note that if an executor is configured any value set for this attribute will be recorded correctly but it will be reported (e.g. via JMX) as -1 to make clear that it is not used.

最大線程數夯巷,大并發(fā)請求時,tomcat能創(chuàng)建來處理請求的最大線程數哀墓,超過則放入請求隊列中進行排隊趁餐,默認值為200。

acceptCount

The maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 100.

當最大線程數(maxThreads)被使用完時篮绰,可以放入請求隊列排隊個數后雷,超過這個數返回connection refused(請求被拒絕),默認值為100吠各;

maxConnections

The maximum number of connections that the server will accept and process at any given time. When this number has been reached, the server will accept, but not process, one further connection. This additional connection be blocked until the number of connections being processed falls below maxConnections at which point the server will start accepting and processing new connections again. Note that once the limit has been reached, the operating system may still accept connections based on the acceptCount setting. The default value is 8192.For NIO/NIO2 only, setting the value to -1, will disable the maxConnections feature and connections will not be counted.

Tomcat在任意時刻接收和處理的最大連接數臀突。當Tomcat接收的連接數達到maxConnections時,Acceptor線程不會讀取accept隊列中的連接贾漏;這時accept隊列中的線程會一直阻塞著候学,直到Tomcat接收的連接數小于maxConnections。默認值為8192纵散。

對于NIO / NIO2梳码,將該值設置為-1將禁用maxConnections功能隐圾,并且不計算連接數。

圖解

按照被處理的先后順序我們可以把tomcat中的線程隊列和以上四個參數使用該圖進行表示

image
  • maxThreads + acceptCount < maxConnections的時候將不會有線程被阻塞
  • 當阻塞的線程時間超過connectionTimeout還沒得到返回值將返回連接超時

4边翁、配置測試環(huán)境

4.1 配置connector

首先我們需要在tomcat中配置三個connector翎承,分別對應三種I/O模型:

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
               connectionTimeout="20000"
               redirectPort="8443"
               acceptCount="20000"
               maxThreads="16"
               maxConnections="22000"/>
    <Connector port="8081" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
               connectionTimeout="20000"
               redirectPort="8444"
               acceptCount="20000"
               maxThreads="200"
               maxConnections="22000"/>
    <Connector port="8082" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="8445"
               acceptCount="20000"
               maxThreads="16"
               maxConnections="22000"/>

4.2 配置jmeter

4.2.1 測試環(huán)境

jmeter是apache旗下的一款開源的使用JAVA編寫的服務器壓力測試軟件,我們從官網下載源碼包符匾,分別部署在windows和Linux系統(tǒng)上叨咖,因為windows系統(tǒng)的硬件配置太差了,沒辦法進行高并發(fā)的壓力測試啊胶,所以windows平臺只進行jmeter的測試文件jmx的配置甸各,配置完成后再使用Linux測試機來進行壓力測試。(注意jmeter版本需要保持一致)

使用jmeter進行測試的機器系統(tǒng)和內核版本為:

[root@www ~]# lsb_release -a
LSB Version:    :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Distributor ID: RedHatEnterpriseServer
Description:    Red Hat Enterprise Linux Server release 6.9 (Santiago)
Release:        6.9
Codename:       Santiago
[root@www ~]# uname -r
2.6.32-696.el6.x86_64

安裝tomcat9的服務器系統(tǒng)和內核版本為:

[root@tmpsys conf]# lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: n/a
Description:    NAME="Red Hat Enterprise Linux Server"
Release:        n/a
Codename:       n/a
[root@tmpsys conf]# uname -r
3.10.0-1062.18.1.el7.x86_64

4.2.2 配置jmeter

jmeter使用前需要配置JDK和系統(tǒng)環(huán)境變量(JDK配置這里不再贅述)焰坪,我們在/etc/profile中導入相關變量并使用source命令保證生效趣倾。

export JMETER_HOME=/home/jmeter
export CLASSPATH=$JMETER_HOME/lib/ext/ApacheJMeter_core.jar:$JMETER_HOME/lib/jorphan.jar:$CLASSPATH
export PATH=$JMETER_HOME/bin:$PATH

配置成功后應該可以看到如下輸出

image

4.3 編輯JMX文件

JMX的文件配置不算復雜,最重要的是測試的時間和并發(fā)線程數量

image

這里我們使用持續(xù)壓力測試模式某饰,設置循環(huán)次數為永遠儒恋,然后設置持續(xù)時間為300秒即5分鐘,設置線程數為200并且ramp-up時間為1s即每秒200并發(fā)數黔漂,如果ramp-up時間為10s即每秒200÷10=20并發(fā)數诫尽,以此類推。對應到jmx文件中的xml文件塊為:

      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="線程組" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循環(huán)控制器" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <intProp name="LoopController.loops">-1</intProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">200</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <boolProp name="ThreadGroup.scheduler">true</boolProp>
        <stringProp name="ThreadGroup.duration">300</stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
      </ThreadGroup>

4.4 測試類型

這里我們分別測試五分鐘持續(xù)壓測情況下200炬守、400牧嫉、600、800减途、1000的并發(fā)情況酣藻,測試的頁面為tomcat的默認首頁,tomcat自帶的examples中的/examples/servlets/nonblocking/bytecounter.html/examples/servlets/nonblocking/numberwriter鳍置×删纾可以看到后面的兩個example都是使用非阻塞的方式進行編寫的sevlet。三者的主要操作如下:

  • tomcat首頁幾乎相當于一個靜態(tài)頁面税产,屬于簡單的網頁請求操作抖仅,應用程序發(fā)送請求到內核,內核從IO從讀取相應文件并返回砖第;
  • numberwriter是生成返回一串很長的數字,應用程序發(fā)送請求到內核并接收從內核生成返回的較大的數據环凿;
  • bytecounter需要上傳一個文件然后再計算字數(這里使用了一個大小約30KB的markdown文件作為測試)梧兼,需要進行IO傳輸和CPU計算再從內核返回一個簡單的數值到應用程序;

4.5 tomcat9啟動參數

此處我們使用的依舊是systemd調用jsvc啟動tomcat智听,啟動參數如下:

ExecStart=/home/tomcat9/bin/jsvc \
        -user tomcat \
        -nodetach \
        -java-home ${JAVA_HOME} \
        -Xms4096m \
        -Xmx8192m \
        -XX:NewRatio=3 \
        -XX:SurvivorRatio=4 \
        -pidfile ${CATALINA_BASE}/tomcat.pid \
        -classpath ${CATALINA_HOME}/bin/bootstrap.jar:${CATALINA_HOME}/bin/tomcat-juli.jar \
        -outfile ${CATALINA_BASE}/logs/catalina.out \
        -errfile ${CATALINA_BASE}/logs/catalina.err \
        -Dcatalina.home=${CATALINA_HOME} \
        -Dcatalina.base=${CATALINA_BASE} \
        -Djava.io.tmpdir=${CATALINA_TMPDIR} \
        -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager \
        -Djava.util.logging.config.file=${CATALINA_BASE}/conf/logging.properties \
        -Djava.library.path=/usr/local/apr/lib \
        org.apache.catalina.startup.Bootstrap

5羽杰、測試結果

5.1 tomcat首頁測試結果

image
image

對于簡單的請求渡紫,三種模式的所有表現數據都幾乎一樣,基本不存在測試誤差范圍外的差距考赛。

5.2 numberwriter測試結果

image
image

到了numberwrite這一種返回較長數據的請求惕澎,NIO2模型的錯誤率要比其他兩者低得多,到了1200并發(fā)的時候apr模型和NIO模型的錯誤率都已經超過了六成颜骤,個人認為此時的響應時間不具有參考性唧喉。

5.3 wordcount測試結果

image
image

和之前的numberwrite一樣,同樣是犧牲了響應時間而降低了錯誤率忍抽。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末八孝,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子鸠项,更是在濱河造成了極大的恐慌干跛,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祟绊,死亡現場離奇詭異楼入,居然都是意外死亡,警方通過查閱死者的電腦和手機牧抽,發(fā)現死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門嘉熊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阎姥,你說我怎么就攤上這事记舆。” “怎么了呼巴?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵泽腮,是天一觀的道長。 經常有香客問我衣赶,道長诊赊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任府瞄,我火速辦了婚禮碧磅,結果婚禮上,老公的妹妹穿的比我還像新娘遵馆。我一直安慰自己鲸郊,他們只是感情好,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布货邓。 她就那樣靜靜地躺著秆撮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪换况。 梳的紋絲不亂的頭發(fā)上职辨,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天盗蟆,我揣著相機與錄音,去河邊找鬼舒裤。 笑死喳资,一個胖子當著我的面吹牛,可吹牛的內容都是我干的腾供。 我是一名探鬼主播仆邓,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼台腥!你這毒婦竟也來了宏赘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤黎侈,失蹤者是張志新(化名)和其女友劉穎察署,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體峻汉,經...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡贴汪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了休吠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扳埂。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瘤礁,靈堂內的尸體忽然破棺而出阳懂,到底是詐尸還是另有隱情,我是刑警寧澤柜思,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布岩调,位于F島的核電站,受9級特大地震影響赡盘,放射性物質發(fā)生泄漏号枕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一陨享、第九天 我趴在偏房一處隱蔽的房頂上張望葱淳。 院中可真熱鬧,春花似錦抛姑、人聲如沸赞厕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坑傅。三九已至,卻和暖如春喷斋,著一層夾襖步出監(jiān)牢的瞬間唁毒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工星爪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留浆西,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓顽腾,卻偏偏與公主長得像近零,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子抄肖,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內容