PooledConnectionFactory有兩個(gè)屬性maxConnections,maximumActive。咋一看來(lái),用人類(lèi)的常識(shí)理解,maxConnection應(yīng)該表示最大可建的connection數(shù),maximumActive應(yīng)該表示最大活躍的connection數(shù),當(dāng)pool中的連接數(shù)大于最大活躍數(shù)時(shí),又超過(guò)idleTimeout會(huì)被回收線程回收到。
如果是這樣理解的,就大錯(cuò)特錯(cuò)了。PooledConnetionFactory的這兩個(gè)參數(shù)根本不是這個(gè)意思。
看一下PooledConnectionFactory的組成結(jié)構(gòu):
注:ConnectionPool其實(shí)存儲(chǔ)的就是一個(gè)ActivemqConnection,起的名字真是蛋疼。
更糟的是上面兩個(gè)屬性也不是我們想的一樣。maxConnections表示的是LinkedList中connection的數(shù)目。maximumActive表示的是SessionPool中session的最大數(shù)目。IdleTime是Connection的回收時(shí)間,回收時(shí)也不是多線程的,每次getConnection時(shí),都會(huì)檢測(cè)是否超時(shí),如果超時(shí),就是立即回收,此時(shí)立即重建,真蛋疼。SeesionPool是用Commons-pool實(shí)現(xiàn)的。
上圖的結(jié)構(gòu)表示的是一個(gè)PooledConnetion維護(hù)了一個(gè)Map,Map的Key可以是由username,password決定的, LinkedList維護(hù)了一個(gè)循環(huán)鏈表的ActivemqConnection。每次從LinkedList中的頭部取出一個(gè)AactivemqConnection,然后再添加到尾部,簡(jiǎn)單的輪詢式的負(fù)載均衡。而這些ActivemqConnection是可以被多線程重用的。Pool實(shí)現(xiàn)中也沒(méi)有connection是否inactive的檢測(cè)機(jī)制,因?yàn)锳ctivemqConnection有自己的heartbeat檢測(cè)機(jī)制。每次發(fā)送或接收時(shí)候先從ConnectionPool中取出一個(gè)connection,如果Connection都用光了,就會(huì)重用在鏈表頭部的Connection的SessionPool,所以一個(gè)Connection可能會(huì)被多個(gè)線程使用,但一個(gè)session只會(huì)對(duì)應(yīng)一個(gè)線程,保證上下文隔離性。多線程同享一個(gè)物理信道,這需要Activemq有自己的拆包機(jī)制,才不會(huì)混亂。而上面提到的負(fù)載均衡,也沒(méi)考慮到session的使用情況,可能我從頭部拿出的connection的session pool已經(jīng)被耗光,而尾部的connection session pool卻很空閑,這樣就要無(wú)辜的阻塞等待session。
這樣看來(lái)在我們?cè)O(shè)置PooledConnection時(shí),建議有條件的還是需要把maxConnections設(shè)置的大一些。它的默認(rèn)值是1。maximumActive可以設(shè)的相對(duì)小一些,它的默認(rèn)值是500,這值太大,擔(dān)心內(nèi)存溢出。IdleTime有條件的可以設(shè)置的大一些,增加connection的重用時(shí)間,默認(rèn)值是30秒。