我從事的全部項目都用到了數據庫鏈接池,這樣作天然有它的理由。有時咱們可能忘記了使用設計模式或者某種特定技術的理由,這時就值得咱們反思爲何要使用它。每項技術或者每一個技術決策都有它的優點和不足,若是不瞭解其缺點,你須要知道你失去了什麼。 html
數據庫每一個讀寫操做須要一個鏈接。數據庫鏈接調用流以下圖: java
調用流程爲: git
應用數據層向DataSource請求數據庫鏈接 github
DataSource使用數據庫Driver打開數據庫鏈接 sql
建立數據庫鏈接,打開TCP socket 數據庫
應用讀/寫數據庫 設計模式
若是該鏈接再也不須要就關閉鏈接 安全
關閉socket 服務器
容易推斷出打開/關閉數據庫鏈接是開銷很大的操做。PostgreSQL爲每一個客戶端鏈接產生一個分離的OS進程,所以高頻率地打開/關閉數據庫鏈接會使數據庫管理系統壓力增大。 框架
重用數據庫鏈接最明顯的緣由是:
- 減小應用程序和數據庫管理系統建立/銷燬TCP鏈接的OS I/O開銷
- 減小JVM對象垃圾
咱們來比較一下不使用鏈接池方法與使用HikariCP,HikariCP多是目前最快的鏈接池框架。
該測試將打開和關閉1000個鏈接。
private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceConnectionTest.class); private static final int MAX_ITERATIONS = 1000; private Slf4jReporter logReporter; private Timer timer; protected abstract DataSource getDataSource(); @Before public void init() { MetricRegistry metricRegistry = new MetricRegistry(); this.logReporter = Slf4jReporter .forRegistry(metricRegistry) .outputTo(LOGGER) .build(); timer = metricRegistry.timer("connection"); } @Test public void testOpenCloseConnections() throws SQLException { for (int i = 0; i < MAX_ITERATIONS; i++) { Timer.Context context = timer.time(); getDataSource().getConnection().close(); context.stop(); } logReporter.report(); }
下面的圖表爲打開和關閉鏈接花費的時間,這個時間固然越短越好。
使用鏈接池比不使用鏈接池快600倍。咱們的企業系統包括幾十個應用,一個批處理器系統僅僅可以處理每小時大於200萬次數據庫鏈接,因此2個數量級的優化是值得考慮的。
理解使用數據庫鏈接池後運行如此好的緣由,要分析池鏈接管理的調用流程:
不管什麼時候請求一個鏈接,池數據源會從可用的鏈接池獲取新鏈接。僅當沒有可用的鏈接並且未達到最大的鏈接數時鏈接池將建立新的鏈接。鏈接池的close()方法把鏈接返回到鏈接池而不是真正地關閉它。
鏈接池是即將到來的鏈接請求的有界緩衝區。若是出現瞬間流量尖峯,鏈接池會平緩這一變化,而不是使全部可用數據庫資源趨於飽和。
等待步驟和超時機制是安全鉤子(safety hook),防止數據庫服務器過載。若是一個應用消耗太多數據庫流量,爲防止它將數據庫服務器壓垮(所以影響整個系統),鏈接池將減小它對數據庫的使用。
全部這些優點都是有代價的,鏈接池配置的額外複雜性增長(尤爲是大型企業級系統中)。因此沒有銀彈,你須要注意不少鏈接池配置好比:
- 最小鏈接數
- 最大鏈接數
- 最大空閒時間
- 獲取鏈接超時時間
- 超時重試鏈接次數
原文連接: javacodegeeks 翻譯: ImportNew.com - hejiani
譯文連接: http://www.importnew.com/11469.html