2014-12-16 8 views
9

Ich habe ein Java Servlet und ich möchte Verbindungspooling zusammen mit jdbc (Datenbank: mysql) verwenden.HikariCP zu viele Verbindungen

Also hier ist, was ich tue:

(Diese Klasse public ist final class DBConnector)

private static final HikariDataSource dataSource = new HikariDataSource(); 
private static final HikariDataSource dataSource2 = new HikariDataSource(); 
private static final HikariDataSource dataSource3 = new HikariDataSource(); 

static { 
    dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/contentdb"); 
    dataSource.setUsername("root2"); 
    dataSource.setPassword("password"); 
    dataSource.setMaximumPoolSize(400); 
    dataSource.setMinimumIdle(5); 
    dataSource.setLeakDetectionThreshold(15000); 
    dataSource.setConnectionTestQuery("SELECT 1"); 
    dataSource.setConnectionTimeout(1000); 

    dataSource2.setDriverClassName("com.mysql.jdbc.Driver"); 
    dataSource2.setJdbcUrl("jdbc:mysql://localhost:3306/userdb"); 
    dataSource2.setUsername("root"); 
    dataSource2.setPassword("password"); 
    dataSource2.setMaximumPoolSize(300); 
    dataSource2.setMinimumIdle(5); 
    dataSource2.setLeakDetectionThreshold(15000); 
    dataSource2.setConnectionTestQuery("SELECT 1"); 
    dataSource2.setConnectionTimeout(1000); 

    dataSource3.setDriverClassName("com.mysql.jdbc.Driver"); 
    dataSource3.setJdbcUrl("jdbc:mysql://localhost:3306/analysedb"); 
    dataSource3.setUsername("root2"); 
    dataSource3.setPassword("password"); 
    dataSource3.setMaximumPoolSize(200); 
    dataSource3.setMinimumIdle(5); 
    dataSource3.setLeakDetectionThreshold(15000); 
    dataSource3.setConnectionTestQuery("SELECT 1"); 
    dataSource3.setConnectionTimeout(1000); 

} 

private DBConnector() { 
    // 
} 

public static Connection getConnection(int dataBase) throws SQLException { 
    if (dataBase == 0) { 
     return dataSource.getConnection(); 
    } else if (dataBase == 1) { 
     return dataSource2.getConnection(); 
    } else { 
     return dataSource3.getConnection(); 
    } 
} 

Und wenn ich es nennen wollen:

Connection con = null; 
    PreparedStatement query = null; 
    ResultSet result = null; 
    try { 
     con = DBConnector.getConnection(0); 
    }catch(SQLException ex){ 
    }finally{ 
     if (result != null) { 
      try { 
       result.close(); 
      } catch (SQLException logOrIgnore) { 
      } 
     } 
     if (query != null) { 
      try { 
       query.close(); 
      } catch (SQLException logOrIgnore) { 
      } 
     } 
     if (con != null) { 
      try { 
       con.close(); 
      } catch (SQLException logOrIgnore) { 
      } 
     } 
    } 

Aber wenn Ich klicke durch meine App, nach einer Weile beginnt es zu hängen und ich bekomme diese Fehler:

java.sql.SQLException: Timeout after 1001ms of waiting for a connection. 
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:208) 
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:108) 
at main.java.db.DBConnector.getConnection(DBConnector.java:60) 
at main.java.ressources.SingleItemData.getVotes(SingleItemData.java:1088) 
at main.java.item.methods.GET.content.GetStreamContent.getStreamContent(GetStreamContent.java:126) 
at main.java.RestService.doGet(RestService.java:254) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) 
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) 
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
at java.lang.Thread.run(Thread.java:724) 

Verursacht durch: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Kommunikationsverbindungsfehler

Ich habe mysql max_conncetions bis 1000. Die Abfrage „SHOW PROCESS“ zeigt mir eine Menge Schlaf Prozesse. Sind das die Müßiggänger?

Ich bin wirklich hier fest. Ich weiß nicht, welche Einstellung dieses Problem verursacht. Also meine Frage ist - was verursacht diesen Fehler? Was mache ich falsch? Jede Hilfe wird geschätzt.

EDIT: Setup-Mysql (localhost):

[mysqld] 

user=mysql 

port=3306 

socket  =/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock 

key_buffer=16M 

max_allowed_packet=1M 

table_open_cache=64 

sort_buffer_size=512K 

net_buffer_length=8K 

read_buffer_size=256K 

read_rnd_buffer_size=512K 

myisam_sort_buffer_size=8M 

max_connections = 1000 

wait_timeout = 28800 

interactive_timeout = 28800 

HikariCP: HikariCP-java6-2.2.5.jar

MySQL Connector: mysql-connector-java-5.1.25-bin.jar

+2

ja das ist richtig. Alle Schlafprozesse sind Leerlaufprozesse. Bevor Sie eine Verbindung herstellen, müssen Sie den Verbindungsstatus überprüfen, wenn eine Verbindung geöffnet ist. Schließen Sie sie und erstellen Sie sie neu. –

+0

Danke für Ihre schnelle Antwort. Nun, nein - es gibt keinen anderen Check. Wie kann ich das tun?;) –

+1

Ich werde vorschlagen, dass Sie bitte die Timeout-Zeit in Ihrem Code verringern. 'dataSource3.setConnectionTimeout (1000);' –

Antwort

17

Paar Dinge. Erstens, welche Version von HikariCP, Java und der MySQL-Treiber?

Zweitens, 400 Verbindungen in einem Pool? Way too many! Beginnen Sie mit 10 bis 20 in jedem Pool. Sie werden überrascht sein, dass Sie einige tausend Transaktionen pro Sekunde bewältigen können.

Drittens ist dies die zweite Frage in the FAQ. Lesen Sie die Antwort und den Link. Sie müssen maxLifetime auf etwas kürzer (um 1 Minute) als Ihr natives Timeout für MySQL setzen.

Zuletzt, aktivieren Sie DEBUG Protokollierung, HikariCP ist nicht laut. Alle 30 Sekunden wird der Housekeeping-Thread ausgeführt und protokolliert die Poolstatistiken.

+0

Das sind jetzt meine neuen Werte: 'dataSource2.setConnectionTimeout (34000); dataSource2.setIdleTimeout (28740000); dataSource2.setMaxLifetime (28740000); ' –

+0

Ok, es funktioniert jetzt. Ich habe alle Einstellungen wie gesagt angepasst. Ich fand auch ein kleines Leck (ich habe die Verbindung nicht geschlossen - dumm ...) Aber ist ein Leck wirklich so schädlich? Da zuvor habe ich keinen Verbindungspool verwendet und das Leck war nicht so schädlich. Ah. Und danke natürlich :) Habe meinen Tag gemacht. –

+5

Nicht geschlossene Verbindungen ohne Pool sind im Allgemeinen nicht schädlich, besonders wenn Sie Auto-Commit verwenden. Das Connection-Objekt wird als Garbage Collected erfasst und schließlich schließt die Datenbank die Seite der Verbindung. * Bei * einem Pool führen nicht geschlossene Verbindungen dazu, dass Ihre Anwendung einfriert, weil der Pool eine maximale Größe hat, und wenn Verbindungen nicht zurückgegeben werden, werden schließlich alle Verbindungen geleert. Der nächste Aufrufer von getConnection() wird daher immer Timeout. Deshalb unterstützen fast alle Pools die Lecksuche. – brettw

Verwandte Themen