自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

接口流量突增,如何做好性能優(yōu)化?

開發(fā) 前端
今天我們分享了 Tomcat 的核心組件,接著講解了 Tomcat 處理請(qǐng)求過(guò)程時(shí)的 3 個(gè)核心參數(shù)及其調(diào)優(yōu)經(jīng)驗(yàn)。

?大家好,我是樹哥!

對(duì)于提供接口服務(wù)的應(yīng)用來(lái)說(shuō),很多都是用 SpringBoot 默認(rèn)的 Servlet 容器 Tomcat。在一開始上線的時(shí)候,由于大多數(shù)流量較小,我們也并不會(huì)為 Tomcat 做專門的參數(shù)調(diào)整。但隨著流量越來(lái)越大,應(yīng)用的各項(xiàng)性能指標(biāo)越來(lái)越差,此時(shí)我們大多數(shù)都會(huì)選擇擴(kuò)容。

除了擴(kuò)容之外,我們還可以選擇對(duì) Tomcat 進(jìn)行性能調(diào)優(yōu),從而在不增加成本的情況下提升性能。如果面試官問(wèn)你,流量突增你們一般怎么做,你只會(huì)答擴(kuò)容可就太差勁了。

今天樹哥就跟大家簡(jiǎn)單分享下,如何對(duì) Tomcat 進(jìn)行簡(jiǎn)單地性能調(diào)優(yōu),從而提升應(yīng)用的性能!

圖片

組件架構(gòu)

要對(duì) Tomcat 進(jìn)行性能調(diào)優(yōu),我們需要先了解其組件架構(gòu)。Tomcat 的組件架構(gòu)如下圖所示:

圖片

Tomcat 組件結(jié)構(gòu)示意圖

從上圖可以看到,Tomcat 將其業(yè)務(wù)抽象成了 Server、Service、Connector、Container 等等組件,每個(gè)組件都有不同的作用。

  • Server 組件。Server 組件是 Tomcat 最外層的組件,該組件是 Tomcat 實(shí)例本身的抽象,代表著 Tomcat 自身。一個(gè) Server 組件可以有一個(gè)或多個(gè) Service 組件。
  • Service 組件。Service 組件是 Tomcat 中一組提供服務(wù)、處理請(qǐng)求的組件,一個(gè) Service 組件可以有多個(gè) Connector 連接器和一個(gè) Container,有多個(gè) Connector 表示其可以同時(shí)使用多種協(xié)議接收用戶請(qǐng)求。
  • Connector 組件。Connector 負(fù)責(zé)處理客戶端的連接,它提供各種服務(wù)協(xié)議支持,包括:BIO、NIO、AIO 等等。其存在的價(jià)值在于,為 Container 容器屏蔽了多協(xié)議的復(fù)雜性,統(tǒng)一了 Container 容器的處理標(biāo)準(zhǔn)。
  • Container 組件。Container 組件是負(fù)責(zé)具體業(yè)務(wù)邏輯處理的容器,當(dāng) Connector 組件與客戶端建立連接后,便會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給 Container 組件的 Engine 組件處理。

到這里,Tomcat 的核心組件基本上講完了。實(shí)際上 Container 組件里還細(xì)分了很多組件,其實(shí)對(duì)業(yè)務(wù)的抽象,感興趣的可以繼續(xù)看看。

  • Engine 組件。Engine 組件表示可運(yùn)行的 Servlet 實(shí)例,包含了 Servlet 容器的核心功能,其可以有一個(gè)或多個(gè)虛擬主機(jī)(Host)。其主要功能是將請(qǐng)求委托給合適的虛擬主機(jī)處理,即根據(jù) URL 路徑的配置匹配到合適的虛擬主機(jī)處理。
  • Host 組件。Host 組件負(fù)責(zé)運(yùn)行多個(gè)應(yīng)用,其負(fù)責(zé)安裝這些應(yīng)用,其主要作用是解析 web.xml 文件,并將其匹配到對(duì)應(yīng)的 Context 組件。
  • Context 組件。Context 組件代表具體的 Web 應(yīng)用程序本身,其最重要的功能就是管理里面的 Servlet 實(shí)例。一個(gè) Context 可以有一個(gè)或者多個(gè) Servlet 實(shí)例。
  • Wrapper 組件。一個(gè) Wrapper 組件代表一個(gè) Servlet,它負(fù)責(zé)管理一個(gè) Servlet,包括 Servlet 的裝載、初始化、執(zhí)行以及資源回收。Wrapper 是最底層的容器。

可以看到,Host 是虛擬主機(jī)的抽象,Context 是應(yīng)用程序的抽象,Wrapper 是 Servlet 的抽象,而 Engine 則是處理層的抽象。

核心參數(shù)

在了解核心參數(shù)之前,我們我們需要大致了解一下 Tomcat 對(duì)于請(qǐng)求的處理流程。Tomcat 對(duì)請(qǐng)求的處理流程如下所示:

  • 首先,客戶端向 Tomcat 服務(wù)器發(fā)起請(qǐng)求,Connector 組件監(jiān)聽到請(qǐng)求,于是與客戶端建立起連接。
  • 接著,Connector 將請(qǐng)求封裝后轉(zhuǎn)發(fā)給 Engine 組件處理。
  • 最后,Engine 組件處理完之后將結(jié)果返回給 Connector,Connector 組件再將結(jié)果返回給客戶端。

上述過(guò)程可以用如下示意圖來(lái)表示:

圖片

Tomcat 核心參數(shù)示意圖

在上面的示意圖中有三個(gè)非常關(guān)鍵的核心參數(shù),這幾個(gè)關(guān)鍵的參數(shù)也是性能調(diào)優(yōu)的關(guān)鍵,它們分別是:

  • acceptCount:當(dāng) Container 線程池達(dá)到最大數(shù)量且沒(méi)有空閑線程,同時(shí) Connector 隊(duì)列達(dá)到最大數(shù)量時(shí),操作系統(tǒng)最多能接受的連接數(shù)。
  • maxConnections:當(dāng) Container 線程池達(dá)到最大數(shù)量且沒(méi)有空閑線程時(shí),Connector 的隊(duì)列能接收的最大線程數(shù)。
  • maxThreads:Container 線程池的處理線程的最大數(shù)量。

從上面三個(gè)參數(shù)的含義我們可以知道如下幾點(diǎn)結(jié)論:

  • 客戶端并不是直接與 Tomcat 的 Connector 組件建立聯(lián)系的,而是先與操作系統(tǒng)建立,然后再移交給 Connector 的。這點(diǎn)很重要,不然你就無(wú)法理解 acceptCount 這個(gè)參數(shù)。
  • 不僅僅 Connector 組件中有隊(duì)列,操作系統(tǒng)中也有隊(duì)列來(lái)臨時(shí)存儲(chǔ)與客戶端的連接,這也是很關(guān)鍵的點(diǎn)。
  • 我們所說(shuō)的線程池,指的是 Container 這個(gè)容器里的線程池。

明白這三個(gè)核心參數(shù)的含義是非常重要的,不然沒(méi)有辦法進(jìn)行后續(xù)的性能調(diào)優(yōu)工作。

maxThreads

我們知道 maxThreads 指的是請(qǐng)求處理線程的最大數(shù)量,在 Tomcat7 和 Tomcat8 中都是默認(rèn) 200 個(gè)。

對(duì)于這個(gè)參數(shù)的設(shè)置,需要根據(jù)任務(wù)的執(zhí)行內(nèi)容去調(diào)整,一般來(lái)說(shuō)計(jì)算公式為:最大線程數(shù) = ((IO時(shí)間 + CPU時(shí)間)/CPU時(shí)間) * CPU 核數(shù)。這個(gè)公式的思路其實(shí)很簡(jiǎn)單,就是最大化利用 CPU 的資源。一個(gè)任務(wù)的耗時(shí)分為 IO 耗時(shí)和 CPU 耗時(shí),基本上 IO 耗時(shí)是最多的,這時(shí)候 CPU 是沒(méi)事干的。

因此如果可以讓 CPU 在任務(wù)等待 IO 的時(shí)候處理其他任務(wù),那么 CPU 利用率不就上來(lái)了么。一般來(lái)說(shuō),由于 IO 耗時(shí)遠(yuǎn)大于 CPU 耗時(shí),因此根據(jù)公式計(jì)算出來(lái)的 maxThreads 數(shù)都會(huì)遠(yuǎn)大于 CPU 核數(shù),這是很正常的。

要注意的是,這個(gè)數(shù)值也不是越高越好。因?yàn)橐坏┚€程數(shù)太多了,CPU 需要進(jìn)行上下文切換,這就消耗了一部分 CPU 資源。因此最好的辦法是用上述公式去計(jì)算一個(gè)基準(zhǔn)值,隨后再進(jìn)行壓力測(cè)試,去調(diào)整到一個(gè)合理的值。

一般來(lái)說(shuō),如果調(diào)高了 maxThreads 的值,但是吞吐量沒(méi)有提升或者下降的話,那么表明可能到達(dá)了了瓶頸了。

maxConnections

maxConnections 指的是當(dāng)線程池的線程達(dá)到最大值,并且都在忙的時(shí)候,Connector 中的隊(duì)列最多能容納多少個(gè)連接。一般來(lái)說(shuō),我們都要設(shè)置一個(gè)合理的數(shù)值,不能讓其無(wú)限制堆積。

因?yàn)?Tomcat 的處理能力肯定是有限的,到達(dá)一定程度肯定就處理不過(guò)來(lái)了,因此你堆積太多了也沒(méi)啥用,反而會(huì)造成內(nèi)存堆積,最終導(dǎo)致內(nèi)存溢出 OOM 的發(fā)生。

一般來(lái)說(shuō),一個(gè)經(jīng)驗(yàn)值是可以設(shè)置成為 maxThreads 同樣的大小。 我想這樣也是比較合理的,因?yàn)樵陉?duì)列中的連接最多只需要等待線程處理一個(gè)任務(wù)的時(shí)間即可,不會(huì)等待太久,響應(yīng)時(shí)間也不會(huì)太長(zhǎng)。

如果你想縮短響應(yīng)時(shí)間,那么可以將 maxConnections 調(diào)低于 maxThreads 一些,這樣可以降低一些響應(yīng)時(shí)間。但要注意的是,如果降得太低的話,可能就會(huì)嚴(yán)重降低性能,降低吞吐量。

acceptCount

acceptCount 指的是當(dāng) Container 線程池達(dá)到最大數(shù)量且沒(méi)有空閑線程,同時(shí) Connector 隊(duì)列達(dá)到最大數(shù)量時(shí),操作系統(tǒng)最多能接受的連接數(shù)。 當(dāng)

隊(duì)列中的個(gè)數(shù)達(dá)到最大值后,進(jìn)來(lái)的請(qǐng)求一律被拒絕,默認(rèn)值是 100。這可以理解成是操作系統(tǒng)的一種自我保護(hù)機(jī)制吧,堆積太多無(wú)法處理,那就直接拒絕掉,保護(hù)自身資源。

這個(gè)參數(shù)的調(diào)優(yōu)資料比較少,但根據(jù)其含義,這個(gè)值不建議比 maxConnections 大。 因?yàn)樵谶@個(gè)隊(duì)列中的連接,是需要等待的。如果數(shù)值太大,就說(shuō)明會(huì)有很多連接沒(méi)有被處理。

連接越多,那么其等待的時(shí)間就越長(zhǎng),其響應(yīng)時(shí)間就越慢。如果你想響應(yīng)時(shí)間短一些,或許應(yīng)該調(diào)低一下這個(gè)值。

有同學(xué)會(huì)疑惑,為啥有了 maxConnections 了還要有 acceptCount 呢?這不是重復(fù)了么?其實(shí)在 BIO 的時(shí)代,這兩個(gè)數(shù)值基本都是相同的。我猜是因?yàn)楹竺娉霈F(xiàn)了 NIO、AIO 等技術(shù),操作系統(tǒng)可以接受更多的客戶端連接了。

于是就可以先讓操作系統(tǒng)先建立連接緩存著,隨后 Connnector 直接從操作系統(tǒng)處獲取連接即可,這樣就不需要等待操作系統(tǒng)進(jìn)行耗時(shí)的 TCP 連接了,從而提高了效率。

除了上面這三個(gè)參數(shù)之外,還有幾個(gè)非核心參數(shù),但我覺得還是有些作用的。

  • connectionTimeout 參數(shù),表示建立連接后的等待超時(shí)時(shí)間,如果超過(guò)這個(gè)時(shí)間,那么就會(huì)直接返回超時(shí)。
  • minSpareThreads 參數(shù),表示最小存活線程數(shù),也就是如果沒(méi)有請(qǐng)求了,那么最低要保持幾個(gè)線程存活。這個(gè)參數(shù)與是否有突發(fā)流程相關(guān)聯(lián),在有突發(fā)流量的情況下,如果這個(gè)數(shù)值太低,那么就會(huì)導(dǎo)致瞬時(shí)的響應(yīng)時(shí)間比較長(zhǎng)。

總結(jié)

今天我們分享了 Tomcat 的核心組件,接著講解了 Tomcat 處理請(qǐng)求過(guò)程時(shí)的 3 個(gè)核心參數(shù)及其調(diào)優(yōu)經(jīng)驗(yàn)。

對(duì)于 maxThreads 參數(shù)而言,如果按照公式計(jì)算的話,我們需要獲取 IO 時(shí)間和 CPU 時(shí)間,但實(shí)際上這兩個(gè)值并不是很好獲取。所以一般情況下,我們可以通過(guò)壓測(cè)的方式來(lái)獲得一個(gè)比較合適的 maxThreads。

對(duì)于 maxConnections 參數(shù)而言,可以設(shè)置一個(gè)與 maxThreads 相同的值,再根據(jù)具體情況進(jìn)行調(diào)整。如果想降低響應(yīng)時(shí)間,那么可以稍微調(diào)低一些,否則可以調(diào)高一些。

對(duì)于 acceptCount 參數(shù)而言,其調(diào)優(yōu)邏輯與 maxConnections 類似,可以設(shè)置與 maxConnections 相似,再根據(jù)對(duì)相應(yīng)時(shí)間的要求,做一個(gè)微調(diào)。

責(zé)任編輯:武曉燕 來(lái)源: 樹哥聊編程
相關(guān)推薦

2020-02-05 14:49:04

網(wǎng)絡(luò)性能優(yōu)化微調(diào)

2014-10-30 10:53:22

Android內(nèi)存優(yōu)化

2022-08-03 09:11:31

React性能優(yōu)化

2011-06-03 17:35:04

SEO

2017-01-19 18:06:19

聽云Network

2019-04-29 09:52:46

容器安全漏洞網(wǎng)絡(luò)安全

2011-03-03 10:11:15

數(shù)據(jù)庫(kù)優(yōu)化

2011-05-26 16:27:24

SEO

2020-07-22 07:00:00

微服務(wù)架構(gòu)

2020-02-01 16:02:11

物聯(lián)網(wǎng)通信技術(shù)

2021-01-19 09:59:02

招聘管理團(tuán)隊(duì)

2022-06-22 08:02:01

業(yè)務(wù)監(jiān)控Web站點(diǎn)監(jiān)控

2011-04-18 13:20:40

單元測(cè)試軟件測(cè)試

2013-07-10 09:22:59

云配置云實(shí)踐云應(yīng)用程序接口

2022-11-03 17:01:10

2010-09-07 16:09:29

2022-05-07 19:18:16

防御性編碼代碼

2011-05-19 10:20:23

2021-04-07 14:45:56

軟件測(cè)試編程

2013-01-22 11:10:11

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)