原文:
對於上一次的map連線池實現,其效率與執行緒安全是沒有問題的。但是在實際的使用中,當併發量很大的時候,其依然會出現問題。
仔細檢視get**,不難發現在獲取連線時,由於沒有設定連線上限,我們預設總會獲取到連線(無論是從連線池獲取還是新建連線)。本人使用的是rpc連線,做壓力測試時,連線池大小為100,但每秒的併發請求數為10000,連線的使用時間為1s。導致大部分的連線無法從連線池獲取,只能採用新建的方式。而這些新建之後的連線也無法真正的放回連線池,必須關閉,所以就會有大量的連線不停的建立和關閉。首先,這是和連線池的設計初衷相左的。其次,大量的連線就會占用大量不同的埠,由於關閉並不是瞬時的,會存在乙個time_wait時間差。一般linux系統為60秒。這就導致在實際的高併發下埠號立即被占用完畢而無法再建立新的連線而服務無法正常完成,這也是我遇到的問題。通過以下命令,我們可以看到有大量的time_wait埠。
netstat -n | awk '/^tcp/ end '
我們已經明確了由於沒有設定連線上限而導致新建大量連線的問題,所以我們必須設定乙個連線上限,而連線數量的多少應該根據伺服器的狀態和實際的使用場景來配置。
const(
poolconntctions = 100
maxconnections = 10000
waittimeout = 2* time.second
)type conn inte***ce
type pool struct
func (p *pool)get(target string)(conn,error)else
return bp.get()
}type boundpool struct
func newboundpool(p *pool)*boundpool
}func (bp *boundpool)get()(conn,error)
return c,nil
} }select
}func (bp *boundpool)new()(conn,error)
這裡沒有給出全部**,為了更加清晰的連線池結構和避免多次map的鎖操作。我將pool分為了兩部分,第一部分的map對映和第二部分實際的連線池。當然給外部的介面還是pool。
看一下boundpool的get實現,我們要麼從連線池獲取,要麼連線數量允許,我們新建連線。而當兩者都不可滿足時,我們仍然不能返回錯誤,因為當併發量很大時,大多數情況都會如此。所以我們引入了第二次select方式的獲取,我們等待一定的時間,在這段時間裡如果我們仍然不能獲取到可用的連線,那麼只能說明我們的配置引數,或者伺服器的狀態不能滿足巨大的請求量。對了,別忘了在關閉連線和新建連線時對當前連線數做相應的加減操作。並且我們可以在服務啟動時初始化一定數量連線,看起來很簡單,其實實現起來仍然有一些可以值得注意的地方。
其實關於獲取連線等待一定時間,在我最初寫連線池時就有如此的考慮,但那時候我陷入了乙個思維怪圈,首先,我不知道連線池大小設定多少合適。其次,我無法權衡從通道獲取,等待超時和新建連線這三者的關係。那個時候我總想著用乙個select 完成這三者操作,但很明顯,這樣是不符合邏輯的,也不可能實現。我居然沒想到重寫整理一下思路,用兩個select來完成這個動作。真的笨啊。。
mysql連線池 順序 Mysql 連線池
通常,如果我們的服務涉及到mysql的操作,當乙個新的請求進來的時候,可以先連線mysql,使用完之後再斷開連線即可。但這樣做有個弊端,當請求量巨大時,會在瞬間有大量的資料庫連線與斷開操作,這是非常影響 mysql 效能的做法。此時,我們就需要使用mysql連線池。在 python 服務中使用 my...
連線池與使用Tomcat的連線池
what is connection pool?看圖 1 存放connection物件的容器 2 減少連線資料庫的開銷 3 程式請求連線時,在connection pool中取連線 4 連線使用完後,放回connection pool,不釋放 5 connection pool對連線進行管理 計數 ...
mysql連線池的概念 連線池概念
1 連線池是乙個程序 多個連線是在乙個程序裡面儲存 管理的。這個程序儲存所有的連線,當我們開啟連線,如果有未用連線可用,則返回該連線。如果池中的連線都用完了,則建立乙個新的連線儲存到連線池。而但我們關閉連線的時候,連線池裡面並不關閉連線,而是返回連線池中並標記為可重用的狀態,等待重新連線直到等待超時...