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

連接池要這么配,干貨收藏!

開發(fā) 前端
本篇總結(jié)了Tomcat,線程池,RestTemplate 的一些日常優(yōu)化策略。平時(shí)應(yīng)該多注意總結(jié),在不同的情況下,優(yōu)化參數(shù)均有不同。所以就要多一些測(cè)試,才能得到最好的配置。看完這些不妨在項(xiàng)目中試一下,增強(qiáng)記憶。

哈嘍,大家好,最近周邊的同事,鄰居逐漸都羊了。

而指北君還在堅(jiān)挺碼字。等待陽(yáng)的到來。

相信羊過之后,必是一片彩虹!

如果很多資源的使用如果不從共享資源池中獲取,極容易造成內(nèi)存泄漏和內(nèi)存溢出。要想實(shí)現(xiàn)高并發(fā)并且合理利用資源,大部分設(shè)計(jì)方案都會(huì)用到各種連接池,線程池等等。所有的可重復(fù)利用資源均從一組資源池中進(jìn)行調(diào)用。也類似于近幾年火爆的共享經(jīng)濟(jì),然而共享經(jīng)濟(jì)就和軟件設(shè)計(jì)中的共享資源池類似。不單獨(dú)持有某個(gè)資源,在需要使用的時(shí)候再去資源池中進(jìn)行申請(qǐng)。

下面我們盤一盤各種資源共享池的一些配置,以及優(yōu)化策略!

1、Tomcat中的各種connection

廢話少說,我們看一下一個(gè)簡(jiǎn)單的SpringBoot tomcat配置

server:
tomcat:
accept-count: 500 //accept隊(duì)列長(zhǎng)度
max-connections: 1000//最大連接數(shù)
threads:
max: 200 //最大工作線程數(shù)量
min-spare: 10 //最小工作線程數(shù)量

HTTP Connector

其工作流程如下:

  • 每個(gè)非異步請(qǐng)求都需要一個(gè)線程來處理,如果并發(fā)請(qǐng)求大于當(dāng)前可處理的線程數(shù)量,則會(huì)創(chuàng)建額外的線程來處理,至多創(chuàng)建到maxThreads 的數(shù)量。
  • 此時(shí)仍然接收到更多的并發(fā)請(qǐng)求,Tomcat會(huì)接受新的connection,直到connection數(shù)到達(dá)最大數(shù)maxConnections。此時(shí)這些connection會(huì)在Connector中創(chuàng)建的 server socket中排隊(duì),直到有線程可以來處理這些connection。
  • 一旦上面的排隊(duì)數(shù)量達(dá)到maxC onnections,然后還有新的請(qǐng)求進(jìn)來,那么新進(jìn)來的connection會(huì)在OS中排隊(duì),操作系統(tǒng)提供的排隊(duì)數(shù)量為acceptCount。如果這個(gè)隊(duì)列滿了的話,后面進(jìn)來的請(qǐng)求有可能被拒絕或者超時(shí)timeout

關(guān)于這個(gè)咱們講一個(gè)食堂干飯的例子:

  • 某學(xué)校有一個(gè)食堂,大廳里面日常至少擺100把椅子(min-spare)供學(xué)生們吃飯。
  • 然而當(dāng)同時(shí)吃飯的同學(xué)大于100人的時(shí)候,食堂會(huì)增加一些椅子(創(chuàng)建線程),并且這些椅子也不會(huì)立馬收回去,一段時(shí)間沒有人使用才會(huì)收回。
  • 但是食堂里面最多可以擺500把椅子(maxThreads)。然后超過500人吃飯同時(shí)吃飯的話,其他人就只能在大廳里面排隊(duì)等別人吃完。食堂大廳里面可以容納1000人進(jìn)行排隊(duì)等候(maxConnections)。
  • 當(dāng)食堂大廳1000人都排滿了,那么就只能到食堂外面排隊(duì)了,外面排隊(duì)最多一直能排200人(acceptCount)。這個(gè)時(shí)候如果再有人過來要吃飯,而且還排不上隊(duì),就會(huì)等到不耐煩(time out),也會(huì)有人來告訴后來的同學(xué),別來了人都滿了,上其他地方吃飯去吧。(reject)

通過上面的例子,我相信大家都能清楚tomcat的一些基本參數(shù)配置作用,并且針對(duì)不同的情況進(jìn)行調(diào)優(yōu)了。

2 ThreadPool

關(guān)于Java線程池,大家都比較熟悉了吧。下面是基本參數(shù)

public ThreadPoolExecutor(
int corePoolSize, //核心線程數(shù)
int maximumPoolSize,//最大線程數(shù)
long keepAliveTime, //大于核心線程數(shù)量的線程存活時(shí)間,如果沒有新任務(wù)就會(huì)關(guān)閉
TimeUnit unit, // 時(shí)間單位
BlockingQueue<Runnable> workQueue, //線程等待隊(duì)列
ThreadFactory threadFactory,//創(chuàng)建線程的工廠
RejectedExecutionHandler handler//拒絕策略
){

線程池基本運(yùn)行原理介紹

  • 提交任務(wù)給線程池后,線程池會(huì)檢查線程池中正在運(yùn)行的線程數(shù)量,如果線程數(shù)量小于核心線程,則創(chuàng)建一個(gè)新的線程來處理任務(wù)。
  • 如果線程池中線程數(shù)量達(dá)到和corePoolSize的大小,則將線程放入等待隊(duì)列BlockingQueue中。
  • 如果提交任務(wù)時(shí)連等待隊(duì)列都已經(jīng)滿了的話,線程池會(huì)繼續(xù)創(chuàng)建新的線程來處理任務(wù),直到線程池?cái)?shù)量達(dá)到maximumPoolSize。
  • 如果線程數(shù)量達(dá)到了最大容量,則會(huì)執(zhí)行拒絕策略。

這里線程池的方案和tomcat Connector 的方案稍微有點(diǎn)不同。前者是先排隊(duì)然后再把池子容量擴(kuò)大代最大,后者是先擴(kuò)大池子,然后再排2個(gè)隊(duì)。

我覺得對(duì)于ThreadPoolExecutor線程池的理解,用工廠工人的例子比較好理解。

  • 有一家工廠建立,開始的時(shí)候只有10個(gè)工人,然后工廠的活越來越多,招聘新的工人肯定不是最好的策略,所以多出來的活暫時(shí)只能等著,進(jìn)行排隊(duì)。(這個(gè)例子中工廠的活多了,立馬去招人肯定是不可能,只能先排單)
  • 后面工廠的業(yè)務(wù)越來越多,任務(wù)擠壓過多,原來的工人干活已經(jīng)不能滿足業(yè)務(wù)需求了。為了最大化效益,招聘新的工人勢(shì)在必行,于是就招聘了新的工人,所有的工人一起來干活,加快效率。
  • 當(dāng)工廠的工人數(shù)量達(dá)到飽和之后,仍然不停的新增業(yè)務(wù),此時(shí)工廠已經(jīng)飽和,沒有辦法再繼續(xù)接單。那么只能采取別的方案(拒絕策略),找別的工廠干,或者新建工廠。
  • 當(dāng)后面業(yè)務(wù)量比較小的時(shí)候,新招的工人就會(huì)慢慢的裁剪(線程一段時(shí)間不使用就會(huì)關(guān)掉!)。

對(duì)線程池的優(yōu)化思路:

  • 如果線程需要執(zhí)行的任務(wù)耗時(shí)比較少,是High CPU類型,則核心線程數(shù)量可以根據(jù)CPU的核數(shù)來進(jìn)行設(shè)置。最大線程數(shù)量也不應(yīng)該設(shè)置的太大。線程隊(duì)列可以根據(jù)使用場(chǎng)景設(shè)置大一點(diǎn),提高線程池效率。
  • 如果線程需要執(zhí)行的任務(wù)耗時(shí)比較長(zhǎng),是High IO型,依賴其他系統(tǒng),CPU需要等待的時(shí)間比較長(zhǎng),則核心線程數(shù)可以大一點(diǎn),相應(yīng)的線程隊(duì)列長(zhǎng)度也應(yīng)該針對(duì)不同的使用場(chǎng)景進(jìn)行調(diào)整。
  • 線程數(shù)量也不宜設(shè)置過大,不然會(huì)導(dǎo)致頻繁的GC。

3、RestTemplate的坑與優(yōu)化

SpringBoot微服務(wù)與其他Restful的資源進(jìn)行交互的時(shí)候會(huì)使用到RestTemplate。如果你直接new RestTemplate,那么就需要特別注意了。使用不慎就會(huì)造成內(nèi)存泄漏,引發(fā)GC等。

RestTemplate底層依舊是使用org.apache.http包下的HttpClient。

SpringBoot中可以通過PoolingHttpClientConnectionManager設(shè)置一些connection pool 的參數(shù)

PoolingHttpClientConnectionManager connectionPoolManager = new PoolingHttpClientConnectionManager();
connectionPoolManager.setMaxTotal(100);//最大連接數(shù)
connectionPoolManager.setDefaultMaxPerRoute(200);//

通過HttpRequestFactory可以設(shè)置connectTimeOut,connectionRequestTimeout,SocketTimeout

HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(3000);//獲取鏈接超時(shí)時(shí)間
httpRequestFactory.setConnectTimeout(3000);// 指客戶端和服務(wù)器建立連接的timeout
httpRequestFactory.setReadTimeout(120000);// 讀取數(shù)據(jù)的超時(shí)時(shí)間

小結(jié)一下比較重要的幾個(gè)參數(shù)如下:

maxTotal : 連接池里面的最大連接數(shù)

defaultMaxPerRoute  : 每個(gè)路由默認(rèn)接收的最大連接數(shù)

socketTimeout :它是指客戶端和服務(wù)器建立連接后,客戶端從服務(wù)器讀取數(shù)據(jù)的超時(shí)時(shí)間,超出后會(huì)拋出SocketTimeOutException。

connectionRequestTimout:指從連接池獲取連接的timeout

connetionTimeout:指客戶端和服務(wù)器建立連接的timeout。

可以通過如下方式構(gòu)建RestTemplate,其中的參數(shù)也可以自定以從配置文件中引入。

@Bean
public RestTemplate buildPoolingRestTemplate(RestTemplateBuilder builder){
PoolingHttpClientConnectionManager connectionPoolManager = new PoolingHttpClientConnectionManager();
connectionPoolManager.setMaxTotal(100);//最大連接數(shù)
connectionPoolManager.setDefaultMaxPerRoute(200);//每個(gè)路由默認(rèn)接收的最大連接數(shù)

HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connectionPoolManager).build();

HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setHttpClient(httpClient);
httpRequestFactory.setConnectionRequestTimeout(3000);//獲取鏈接超時(shí)時(shí)間
httpRequestFactory.setConnectTimeout(3000);// 指客戶端和服務(wù)器建立連接的timeout
httpRequestFactory.setReadTimeout(120000);// socketTimeout 讀取數(shù)據(jù)的超時(shí)時(shí)間

return builder.requestFactory(()-> httpRequestFactory).build();
}

對(duì)于RestTemplate的一些建議

  • 應(yīng)該從資源池中獲取RestTemplate(PoolingHttpClientConnectionManager)
  • 使用RestTemplateBuilder來創(chuàng)建RestTemplate
  • 針對(duì)maxTotal ,defaultMaxPerRoute  ,可以增大maxTotal以增大并發(fā)量,同時(shí)也需要調(diào)整每個(gè)路由的最大并發(fā)連接數(shù),此時(shí)也可以提高某條路由的并發(fā)量。
  • connectionRequestTimeout和connectTimeout設(shè)置不要太長(zhǎng),socketTimeout根據(jù)需求可以設(shè)置相應(yīng)的時(shí)間。

當(dāng)然還有其他的一些優(yōu)化的地方,比如使用不同的ConnectionKeepAliveStrategy等,設(shè)置maxIdleTime最大空閑時(shí)間等。

總結(jié)

本篇總結(jié)了Tomcat,線程池,RestTemplate 的一些日常優(yōu)化策略。平時(shí)應(yīng)該多注意總結(jié),在不同的情況下,優(yōu)化參數(shù)均有不同。所以就要多一些測(cè)試,才能得到最好的配置??赐赀@些不妨在項(xiàng)目中試一下,增強(qiáng)記憶。


責(zé)任編輯:武曉燕 來源: Java技術(shù)指北
相關(guān)推薦

2022-11-11 09:41:04

連接池微服務(wù)數(shù)據(jù)庫(kù)

2019-12-30 15:30:13

連接池請(qǐng)求PHP

2011-06-01 13:54:10

MySQL

2017-01-05 14:16:28

連接池數(shù)據(jù)代碼

2018-02-07 16:23:58

連接池內(nèi)存池AI

2009-09-22 16:04:50

Hibernate連接

2009-09-22 14:52:55

Hibernate p

2009-06-17 16:22:45

Hibernate連接

2009-07-15 11:00:48

proxool連接池

2010-06-25 10:36:27

Java連接池

2015-04-27 09:50:45

Java Hibern連接池詳解

2009-06-17 09:59:46

Hibernate 連

2020-02-03 15:15:27

Druid連接池性能超出競(jìng)品

2009-12-25 15:38:12

ADO連接池

2024-12-04 15:55:19

2009-06-24 07:53:47

Hibernate數(shù)據(jù)

2022-07-19 13:51:47

數(shù)據(jù)庫(kù)Hikari連接池

2021-03-24 09:06:01

MySQL長(zhǎng)連接短連接

2009-08-24 15:48:53

Java連接池

2010-01-04 16:24:07

ADO連接池
點(diǎn)贊
收藏

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