分布式應用連接池負載不均問題分析_第1頁
分布式應用連接池負載不均問題分析_第2頁
分布式應用連接池負載不均問題分析_第3頁
分布式應用連接池負載不均問題分析_第4頁
分布式應用連接池負載不均問題分析_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、負載均衡基本概念1.1負載均衡介紹在分布式架構(gòu)下隨著邏輯業(yè)務(wù)的快速發(fā)展,系統(tǒng)架構(gòu)也隨之變得龐大復雜,這中間對系統(tǒng)模塊的高并發(fā)、高可用、高擴展性也提出了新的要求,比如服務(wù)路由、負載均衡等。負載均衡是指將負載(如計算任務(wù)、數(shù)據(jù)流量等)分攤到多個操作單元(如服務(wù)器、網(wǎng)絡(luò)設(shè)備等)上進行執(zhí)行,以共同完成工作任務(wù)的一種技術(shù)。它建立在現(xiàn)有網(wǎng)絡(luò)結(jié)構(gòu)之上,提供了一種廉價、有效和透明的方法,可以擴展網(wǎng)絡(luò)設(shè)備和服務(wù)器的帶寬、增加吞吐量、加強網(wǎng)絡(luò)數(shù)據(jù)處理能力,并提高網(wǎng)絡(luò)的靈活性和可用性。負載均衡在實現(xiàn)上有硬件和軟件兩種方式:硬件負載均衡器功能強大、穩(wěn)定性高,適合吞吐量大、高并發(fā)的流量負載,但是成本相對較高,并且擴展性差;軟件負載部署上更加靈活,擴展性高,但是性能和穩(wěn)定性相對較差。

1)硬件負載均衡設(shè)備F5負載均衡器(LTM):F5BIG-IP負載均衡設(shè)備,支持4-7層負載均衡,具備負載均衡、應用交換、狀態(tài)監(jiān)控等功能CDN負載均衡設(shè)備:專門用于CDN的負載均衡設(shè)備,通常采用多層架構(gòu)設(shè)計,包括全局負載均衡設(shè)備、局部負載均衡設(shè)備和緩存服務(wù)器等2)軟件負載均衡LVS:LVS軟件工作在網(wǎng)絡(luò)四層,通過vrrp協(xié)議轉(zhuǎn)發(fā),有著高可用性、高性能、擴展性的優(yōu)點,是Linux內(nèi)核的一款負載均衡軟件。Nginx:Nginx軟件工作在網(wǎng)絡(luò)七層,它屬于反向代理服務(wù)器,并且能夠支持虛擬主機,是開源的負載均衡軟件。HAProxy:HAProxy支持TCP和HTTP兩種代理模式,它是一個反向代理服務(wù)器,支持虛擬主機,也可以用作HTTPS代理、基于內(nèi)容的負載均衡等。1.2負載均衡常用的算法負載均衡是將業(yè)務(wù)流量負載到不同的服務(wù)器,而負載均衡算法就是實現(xiàn)在不同服務(wù)器之間分配網(wǎng)絡(luò)流量的邏輯。負載均衡算法的選擇會影響負載的分配機制,從而影響到性能和業(yè)務(wù)連續(xù)性,下面將介紹幾種常用的負載均衡算法。1)RoundRobin(輪詢算法)輪詢算法很簡單,將前端請求按照順序輪流分配到后臺服務(wù)器上,不用關(guān)心后臺服務(wù)器的負載和實際連接情況。輪詢算法適用于后端服務(wù)器性能大致相當?shù)那闆r,如果某臺機器性能異常承載不了這么多的流量,會造成業(yè)務(wù)訪問異常。當然在實際的運維工作中,會采用標準化的配置相同的服務(wù)器,以減少維護成本。如下圖所示流量請求安裝順序分發(fā)到后臺三個節(jié)點中,保證了流量均衡。2)WeightedRoundRobin(加權(quán)輪詢算法)加權(quán)輪詢算法是對輪詢算法的優(yōu)化,因為后臺服務(wù)器在配置和性能上有差異,在負載配置上將配置高、負載低的機器分配更高的權(quán)重,使其能處理更多的請求,而配置低、負載高的機器,則給其分配較低的權(quán)重,降低其系統(tǒng)負載。加權(quán)輪詢算法適用于后端具備不同負載容量的服務(wù)器,但是配置上更為復雜,也不利于標準化的配置。3)FastestResponseTime(最快響應算法)最快響應算法根據(jù)負載均衡器到每一個后端服務(wù)器節(jié)點的網(wǎng)絡(luò)響應時間(RTT時延),并將下一個到達的連接請求動態(tài)分配給響應時間最短的節(jié)點。該算法能夠?qū)崿F(xiàn)應用請求的快速響應,提高業(yè)務(wù)請求的響應時間,但是會出現(xiàn)請求集中在幾個響應最快的節(jié)點上。如下圖所示,節(jié)點1和節(jié)點3的響應時間為20ms、節(jié)點2為30ms,根據(jù)最快響應算法,連接請求負載分發(fā)到節(jié)點1和節(jié)點3中。4)LeastConnections(最小連接算法)像前面的輪詢算法按照前端的請求次數(shù)均衡分配,實現(xiàn)后端服務(wù)器的負載均衡,但是實際上連接請求并不能真實反映服務(wù)器的負載情況。因此引入了最小連接算法,根據(jù)后端服務(wù)器當前的連接情況,動態(tài)的選取其中當前積壓連接數(shù)最少的一臺服務(wù)器來處理當前請求,盡可能的提高后臺服務(wù)器利用率。最小連接算法在本質(zhì)上是從后端服務(wù)器的角度來觀察系統(tǒng)的負載,能夠最大限度的利用后端服務(wù)器的資源,不足之處是負載均衡需要更多的資源來判斷后端服務(wù)的連接情況。如下圖所示最小連接算法的實現(xiàn):除了上面4種,負載均衡算法還有隨機法、加權(quán)隨機法、源地址哈希法等不多介紹,實際應用中輪詢算法和最小連接算法應用的較多。2、Druid連接池介紹2.1Druid連接概覽Druid是開源的數(shù)據(jù)庫連接池,它結(jié)合了C3P0、DBCP、Proxool等DB池的優(yōu)點,同時加入了日志監(jiān)控,可以很好的監(jiān)控DB池連接和SQL的執(zhí)行情況。在druidDataSource中有一個重入鎖和衍生的兩個condition:一個監(jiān)控連接池是否為空,一個監(jiān)控連接池不為空。在druidDataSource中有兩個線程,一個生成連接CreateConnectionThread,一個回收連接DestoryConnectionThread。在創(chuàng)建、獲取、回收的時候都會使用這些鎖和condition。每次獲取Connection都會調(diào)用init,內(nèi)部使用inited標識DataSource是否已經(jīng)初始化OK。每次獲取Connection都會需要進行加鎖保證線程安全,所有操作都在加鎖后執(zhí)行。如果連接池內(nèi)沒有連接了,則調(diào)用empty.signal(),通知CreateThread創(chuàng)建連接,并且等待指定的時間,被喚醒之后再去查看是否有可用連接。2.2Druid參數(shù)配置說明

1)基本屬性name:配置這個屬性的意義在于,如果存在多個數(shù)據(jù)源,監(jiān)控的時候可以通過名字來區(qū)分開來。如果沒有配置,將會生成一個名字,格式是:"DataSource-"+System.identityHashCode(this).url:連接數(shù)據(jù)庫的url,不同數(shù)據(jù)庫不一樣。例如:mysql:jdbc:mysql://04:3306/druid2、oracle:jdbc:oracle:thin:@5:1521:ocnautousername:連接數(shù)據(jù)庫的用戶名password:連接數(shù)據(jù)庫的密碼driverClassName:這一項可配可不配,如果不配置druid會根據(jù)url自動識別dbType,然后選擇相應的driverClassName2)連接池大小initialSize:初始化時建立物理連接的個數(shù)。初始化發(fā)生在顯示調(diào)用init方法,或者第一次getConnection時。缺省值為0maxActive:最大連接池數(shù)量。缺省值為8minIdle:最小連接池數(shù)量。缺省值為0maxWait:獲取連接時最大等待時間,單位毫秒。配置了maxWait之后,缺省啟用公平鎖,并發(fā)效率會有所下降,如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。缺省值為-13)連接檢測testOnBorrow:申請連接時執(zhí)行validationQuery檢測連接是否有效,做了這個配置會降低性能。缺省值為truetestOnReturn:歸還連接時執(zhí)行validationQuery檢測連接是否有效,做了這個配置會降低性能。缺省值為falsetestWhileIdle:建議配置為true,不影響性能,并且保證安全性。申請連接的時候檢測,如果空閑時間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測連接是否有效。缺省值為falsetimeBetweenEvictionRunsMillis:有兩個含義:1)Destroy線程會檢測連接的間隔時間,如果連接空閑時間大于等于minEvictableIdleTimeMillis則關(guān)閉物理連接。2)testWhileIdle的判斷依據(jù)。缺省值為60smaxEvictableIdleTimeMillis:連接空閑時間大于該值,不管minidle是多少都關(guān)閉這個連接。缺省值為7小時minEvictableIdleTimeMillis:連接空閑時間大于該值并且池中空閑連接數(shù)大于minidle則關(guān)閉這個連接。缺省值為30分鐘maxPoolPreparedStatementPerConnectionSize:要啟用PSCache,必須配置大于0,當大于0時,poolPreparedStatements自動觸發(fā)修改為true。在Druid中,不會存在Oracle下PSCache占用內(nèi)存過多的問題,可以把這個數(shù)值配置大一些,比如說100。缺省值為-1PhyTimeoutMillis:物理連接打開的時間超過這個超時時間,并且不再使用時會關(guān)閉這個物理連接,一般不建議打開validationQuery:用來檢測連接是否有效的sql,要求是一個查詢語句,常用select'x'。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會起作用。缺省值為nullvalidationQueryTimeout:單位:秒,檢測連接是否有效的超時時間。底層調(diào)用jdbcStatement對象的voidsetQueryTimeout(intseconds)方法。缺省值為-1keepAlive:連接池中的minIdle數(shù)量以內(nèi)的連接,并且連接的空閑時間大于keepAliveBetweenTimeMillis但小于minEvictableIdleTimeMillis,則會執(zhí)行validationQuery來保持連接的有效性。缺省值為falsekeepAliveBetweenTimeMillis:打開KeepAlive時,當連接的空閑時間超過該值,會使用validationQuery執(zhí)行一次查詢,檢查連接是否可用。缺省值為120s

4)緩存語句poolPreparedStatements:是否緩存preparedStatement,也就是PSCache。PSCache對支持游標的數(shù)據(jù)庫性能提升巨大,比如說oracle。在mysql下建議關(guān)閉。缺省值為falsesharePrepareStatementsmaxPoolPreparedStatementPerConnectionSize:要啟用PSCache,必須配置大于0,當大于0時,poolPreparedStatements自動觸發(fā)修改為true。在Druid中,不會存在Oracle下PSCache占用內(nèi)存過多的問題,可以把這個數(shù)值配置大一些,比如說100。缺省值為-12.3連接?;詈突厥諜C制2.3.1連接?;顬榱朔乐挂粋€數(shù)據(jù)庫連接太久沒有使用,而被其它下層的服務(wù)關(guān)閉,druid中定義了KeepAlive選項,機制上與TCP中的類似。?;顧C制能夠保證連接池中的連接是真實有效的連接,假如遇到特殊情況導致連接不可用時,keepAlive機制將無效連接進行驅(qū)逐。?;顧C制是由守護線程DestroyConnectionThread發(fā)起的,啟動后守護線程會進入無線循環(huán),根據(jù)心跳間隔時間timeBetweenEvictionRunsMillis循環(huán)調(diào)用DestoryTask線程,默認時間為60s。1)開啟KeepAlive//

一個連接在連接池中最小生存的時間dataSurce.setMinEvictableIdleTimeMillis(60

*

1000);單位毫秒//

開啟keepAlivedataSource.setKeepAlive(true);有兩個參數(shù)KeepAlive和MinEvictableIdleTimeMillis2)DruidDataSource中的兩個成員變量//

存放檢查需要拋棄的連接private

DruidConnectionHolder[]

evictConnections;//

用來存放需要連接檢查的存活連接privateDruidConnectionHolder[]keepAliveConnections;如果KeepAlive打開,當一個連接的空閑時間超過keepAliveBetweenTimeMillis時,則會將此連接放入此連接放入keepAliveConnections數(shù)組,然后使用validationQuery執(zhí)行一次查詢。if(keepAlive&&idleMillis>=keepAliveBetweenTimeMillis){keepAliveConnections[keepAliveCount++]=connection;}…if(keepAliveCount>0){//keeporderfor(inti=keepAliveCount-1;i>=0;--i){DruidConnectionHolderholer=keepAliveConnections[i];Connectionconnection=holer.getConnection();holer.incrementKeepAliveCheckCount();booleanvalidate=false;try{this.validateConnection(connection);validate=true;}catch(Throwableerror){if(LOG.isDebugEnabled()){LOG.debug("keepAliveErr",error);}//skip

}如果本次validationQuery執(zhí)行失敗,則關(guān)閉該鏈接,并丟棄。2.3.2數(shù)據(jù)源收縮

在Druid數(shù)據(jù)源初始化的時候,會創(chuàng)建一個定時運行的DestroyTask,該任務(wù)的主要目的是將已空閑時間滿足關(guān)閉條件的連接關(guān)閉。1)當前連接存活時長>配置的物理連接時間時長,則放入evictConnectionsif(phyConnectTimeMillis>phyTimeoutMillis){evictConnections[evictCount++]=connection;continue;}2)空閑時間>最小驅(qū)逐時間if(idleMillis>=minEvictableIdleTimeMillis){if(checkTime&&i<checkCount){evictConnections[evictCount++]=connection;continue;}elseif(idleMillis>maxEvictableIdleTimeMillis){evictConnections[evictCount++]=connection;continue;}}…if(evictCount>0){for(inti=0;i<evictCount;++i){DruidConnectionHolderitem=evictConnections[i];Connectionconnection=item.getConnection();JdbcUtils.close(connection);destroyCountUpdater.incrementAndGet(this);}Arrays.fill(evictConnections,null);

}從代碼邏輯中可以看到,對于要關(guān)閉的空閑連接選擇邏輯如下:對于空閑時間>minEvictableIdleTimeMillis的連接,僅會關(guān)閉poolingCount-minIdle個,后面的連接不受影響處于>maxEvictableIdleTimeMillis的空閑連接則會直接關(guān)閉timeBetweenEvictionRunsMillis即為該定時任務(wù)運行的間隔minEvictableIdleTimeMillis為可關(guān)閉連接的最小空閑時間2.4Druid連接生命周期Druid連接的生命周期從兩個維度去看:一個是應用使用方,包括連接的申請、使用和關(guān)閉;一個是Druid自己管理的連接池,包括連接的創(chuàng)建和回收、保活機制等。具體如下所示:1)客戶端連接管理客戶端發(fā)起連接請求從Druid連接池申請連接,如果連接池內(nèi)連接不夠會調(diào)用CreateThread創(chuàng)建連接;客戶端拿到連接后,訪問數(shù)據(jù)庫進行操作;連接操作完成后,釋放數(shù)據(jù)庫資源并close連接,這一步通常是由應用主動去做的,連接關(guān)閉后會回收,歸還給Druid連接池。2)Druid連接池管理Druid連接池設(shè)置最小連接數(shù)minIdle和最大連接數(shù)maxActive,最小連接數(shù)支持預熱功能,應用每次申請連接的時候不需要重新初始化,高并發(fā)下可以提升性能;連接池會定時進行連接?;?,KeepAlive的周期由timeBetweenEvictionRunsMillis控制(默認值60s),當發(fā)現(xiàn)連接的空閑時長超過keepAliveBetweenTimeMillis(默認值120s)時,會主動發(fā)起鏈路?;?,一般是向數(shù)據(jù)庫發(fā)起SQL查詢,這個SQL語句可以自定義,通常為“select1fromdual”為了防止連接泄露,會定時回收空閑的連接,對于連接空閑時間大于minEvictableIdleTimeMillis(默認為30分鐘)并且連接池中空閑連接數(shù)大于minIdle則關(guān)閉這個連接;如果連接空閑時間大于maxEvictableIdleTimeMillis(默認值為7小時)則直接關(guān)閉連接從上可以看出,如果沒有連接?;睿斣O(shè)置minIdle后會有一部分在最小連接內(nèi)的連接因為空閑連接超時被關(guān)閉;當然如果設(shè)置了KeepAlive并且當?;畹臋z測頻率和keepAliveBetweenTimeMillis小于minEvictableIdleTimeMillis時,就不會出現(xiàn)空閑連接被關(guān)閉的情況。3、Druid連接池下數(shù)據(jù)庫負載不均問題3.1負載均衡后端成員啟動先后問題在日常應用系統(tǒng)架構(gòu)中,應用->負載均衡->數(shù)據(jù)庫鏈路如下圖所示,應用側(cè)配置連接池以提升性能、負載均衡如F5設(shè)備實現(xiàn)后端成員的管理,如后端成員UP/DOWN狀態(tài)監(jiān)測、流量負載分發(fā)等。負載均衡通過定時檢測機制如TCP監(jiān)聽或者SQL語句探測,以監(jiān)測后端成員的狀態(tài),記錄到負載均衡設(shè)備中進行管理。在上圖中部署了3個應用服務(wù)器,每個上面配置最小空閑連接minIdle=20,總的初始化連接數(shù)有60個。當后端成員維護或者升級等原因集體處于DOWN狀態(tài)然后再變成UP,但是對于負載均衡檢測到后端成員的UP狀態(tài)是有先后順序的,比如DB1最先處于UP狀態(tài),后面其它DB陸續(xù)起來,這樣大量的連接最先到DB1節(jié)點,后面的DB節(jié)點也陸續(xù)有流量。整個過程可能很快,1~2s的時間,但是反映在后端成員的流量負載上已經(jīng)不均勻了(DB1=30、DB2=16、DB3=8、DB4=6)。如果此時DB1節(jié)點的資源和性能不足以支撐50%的業(yè)務(wù)流量,業(yè)務(wù)運行會變慢或者數(shù)據(jù)庫請求失敗,造成業(yè)務(wù)連續(xù)性影響。上述問題的一個優(yōu)化方法是,如果是計劃內(nèi)的操作,在實施流程上進行優(yōu)化,在后端成員都就緒以后再將業(yè)務(wù)負載接入,這樣會將流量請求相對均衡的負載到各個后端實例上。3.2負載均衡后端成員故障后接入另一個場景是負載均衡后端成員故障后再重新接入的問題,如上圖所示,3個應用初始化連接為60,在負載均衡4個后端DB實例中平均為15。當后端成員DB1故障后,其中的連接

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論