android wtf_WTF连接池
android wtf
讓我們談談連接池。
我聲稱:
大多數流行的連接池的默認設置都很差!
對您來說,這意味著:
去查看您的連接池設置。
如果您依賴默認設置,則可能會遇到問題。 您可能有內存泄漏和應用程序無響應(即使負載根本不高)。
下面,我將顯示一些最重要的設置以及我的建議,這些設置應如何配置。
什么是連接池?
一個普通的Web應用程序需要從數據庫寫入或讀取數據,它是這樣的:
(順便說一下,在舊的良好CGI應用程序中,這是唯一可能的方法)
在許多情況下,此方法非常好。 而且您可能不需要更多。 但這對于高性能系統有一些缺點 :
- 步驟1可能需要一些時間。 大概幾十或幾百毫秒(當然要取決于它)。
- 很容易忘記第3步(關閉連接),這會導致連接泄漏 (導致內存泄漏和其他問題)。
新英雄
這就是誕生另一種方法的原因:應用程序可能會預先打開一堆連接并一直保持打開狀態。 一堆打開的連接稱為連接池 。 然后任何操作如下所示:
看起來很酷。 但是,新的力量總是意味著新的問題。
…以及新問題
使用連接池時,我們需要(至少)解決以下問題 :
- 我們應該保持多少連接?
- 應該保留多長時間?
- 如果它們看起來壞了怎么辦?
- 如果應用程序需要的連接數超過當前池的數量,該怎么辦?
- 如果有人忘記將連接恢復到池怎么辦?
為了回答這些問題,連接池有很多設置。 而且它們的默認值大多不好。 感興趣嗎? 讓我展示。
基本設置
我將考慮Java世界中2個最流行的連接池:
- C3P0( https://www.mchange.com/projects/c3p0/ )
- HikariCP( https://github.com/brettwooldridge/HikariCP )
原因的基本參數是:
- 最小大小(隨時應打開的最小連接數)
- 初始大小(啟動時打開了多少個連接應用程序)
- 最大大小(池中的最大連接數)
順便說一下,這些是唯一具有合理默認值的設置。 他們來了:
| c3p0 | 光ikaCP | |
| 最小尺寸 | 3 | 10 |
| 初始尺寸 | 3 | 10 |
| 最大尺寸 | 15 | 10 |
讓我們繼續進行更多有問題的設置。
關鍵設置
結帳超時
應用程序可以等待多長時間,直到它從池中獲得連接。
- c3p0設置:checkoutTimeout
- HikariCP設置:connectionTimeout
默認值:
| c3p0 | 光ikaCP | 我建議 | |
| checkoutTimeout | ∞ | 30秒 | 1毫秒 |
這兩個默認值都只是災難。
正如我提到的,在大多數情況下,從池中獲得連接非常快。 除非池中沒有打開的連接。 然后,池需要獲取一個新的連接(通常需要不到一秒鐘的時間)。 但是,如果達到maxSize,則池無法打開新的連接,而只是等到有人將其連接返回到池中。 但是,如果應用程序發生連接泄漏(阻止連接返回的錯誤),則池將永遠無法恢復連接!
那會發生什么呢?
對于c3p0,我們最終將所有線程凍結為以下狀態:
"qtp1905485420-495 13e09-3211" #495 prio=5 os_prio=0 tid=0x00007f20e078d800 nid=0x10d7 in Object.wait() [0x00007f204bc79000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable()- locked <0x00000000c3295ef8> (a com.mchange.v2.resourcepool.BasicResourcePool)at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource()…at org.hibernate.jpa.internal.QueryImpl.getResultList()at domain.funds.FundsRepository.get()…似乎HikariCP的默認“ 30秒”要好一些。 不,它在高性能應用程序中并沒有真正幫助。 在這30秒內,可能會收到許多新請求,并且所有請求都被凍結。 顯然,應用程序將很快收到OutOfMemory錯誤。 任何等待只會將應用程序的終止延遲幾秒鐘。
這就是為什么我建議將checkoutTimeout設置為最小可能值:1ms。 不幸的是,我們不能將其設置為0,因為0意味著無盡的等待&#55357;&#56898; 我們越早失敗,我們給工作線程完成工作的機會就越大。 而且我們可以清楚地通知用戶該應用程序當前已超載,他應該稍后再試。
在結帳時測試連接
有時池中的連接可能會死。 數據庫可以主動關閉它們,或者系統管理員可以斷開網絡電纜。 這就是池應該監視連接活動性的原因。
最簡單的設置是c3p0中的“ testConnectionOnCheckout”(我在HikariCP中沒有找到類似的設置,它似乎始終處于啟用狀態)。
默認值:
| c3p0 | 光ikaCP | 我建議 | |
| testConnectionOnCheckout | 假 | 真正? | 真正 |
當然,默認情況下應該啟用它 !
否則,您將在日志中最終遇到許多此類異常:
org.hibernate.TransactionException: Unable to rollback against JDBC Connection at o.h.r.j.i.AbstractLogicalConnectionImplementor.rollback() at o.h.r.t.b.j.i.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.rollback(JdbcResourceLocalTransactionCoordinatorImpl.java:294)PS如果要獲得更好的性能,可以考慮在后臺而不是在結帳時測試連接:
- testConnectionOnCheckout = false
- testConnectionOnCheckin = true
- idleConnectionTestPeriod = 10
首選測試查詢
但是池應該如何準確地測試連接?
問題在于它取決于數據庫。
默認情況下,兩個池都通過執行以下測試來測試連接
- “ connection.isValid()”(對于JDBC4),或者
- “ connection.getMetaData()。getTables()”(對于JDBC3)
這可能很慢,因為“ getTables()”每次都檢索有關所有表的元信息。 推薦值類似于
- “ SELECT 1”(對于MySql),或者
- “從雙重選擇1”(對于Oracle)等
通過執行此簡單而快速的查詢,池可以檢查連接是否仍處于活動狀態。
最大空閑時間
未使用的連接可以在池中保留多長時間
- c3p0設置:maxIdleTime
- HikariCP設置:idleTimeout
默認值:
| c3p0 | 光ikaCP | 我建議 | |
| maxIdleTimeout | ∞ | 10分鐘 | 1..10分鐘 |
可能沒什么大不了的,但是每個打開的連接
- 在數據庫中保存一些資源
- 防止其他系統獲得到同一數據庫的連接(每個數據庫都有最大可能連接數的限制)
因此,關閉未使用的(空閑)連接是個好主意。 我建議將此值設置為無限期。 大概幾分鐘是合理的。
最小泳池大小
應始終具有多少個連接池(即使未使用)。
- c3p0設置:minPoolSize
- HikariCP設置:minimumIdle
默認值:
| c3p0 | 光ikaCP | 我建議 | |
| maxIdleTimeout | 3 | 最大游泳池 | 0…N |
出于同樣的原因,關閉未使用的連接可能是一個好主意。 在大多數情況下,我會將此值設置為0或1。 如果某些用戶意外決定在午夜登錄到您的應用程序,那么他將只等待幾毫秒。 沒什么大不了的。
最大連接年齡
連接在池中可以存在多長時間(無論它是空閑還是已使用)
- c3p0設置:maxConnectionAge
- HikariCP設置:maxLifetime
默認值:
| c3p0 | 光ikaCP | 我建議 | |
| maxIdleTimeout | ∞ | 30分鐘 | 比方說30分鐘 |
以防萬一,不時關閉連接可能是一個好主意。 可能有助于避免某些內存泄漏。
來自HikariCP文檔的報價:
“我們強烈建議設置此值,它應該比任何數據庫或基礎架構施加的連接時間限制短幾秒鐘。”
未返回的連接超時
典型的問題之一是連接泄漏。 一些錯誤的代碼從池中獲取了一個連接,但沒有返回它。 如何發現這個問題?
幸運的是,在這種情況下,我們有一個很好的設置:
- c3p0設置:unreturnedConnectionTimeout
- HikariCP設置:leakDetectionThreshold
默認值:
| c3p0 | 光ikaCP | 我建議 | |
| maxIdleTimeout | 殘障人士 | 殘障人士 | 5分鐘? |
如果任何錯誤代碼接受了連接但在5分鐘內未返回連接,則池將強制返回連接并發出如下警告:
[C3P0PooledConnectionPoolManager Logging the stack trace by which the overdue resource was checked-out. java.lang.Exception: DEBUG STACK TRACE: Overdue resource check-out stack trace. at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource() at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1885) at domain.application.ApplicationReportSender.sendWeeklyReport(ApplicationReportSender.java:63)這將幫助您找出有罪代碼在哪里。
結論
我概述了一些連接池設置。 還有更多。 根據我的經驗,我給出了一些合理的建議。 但是您的應用程序可能具有不同的負載。 您的用戶可能會有不同的行為。 我的建議對您來說似乎很愚蠢。
沒問題。 不要相信我 但也請不要相信默認值。
去檢查你的游泳池設置!
翻譯自: https://www.javacodegeeks.com/2018/12/wtf-connection-pools.html
android wtf
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的android wtf_WTF连接池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 反引号包裹反引号_五个金色反引号
- 下一篇: 橘子英语怎么读 橘子的英语是什么