2014-12-16 22 views
9

Ho un servlet Java e voglio utilizzare il pool di connessioni insieme a jdbc (Database: mysql).HikariCP troppe connessioni

Così qui è quello che sto facendo:

(Questa classe è pubblica finale di classe 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(); 
    } 
} 

e quando voglio chiamarlo:

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) { 
      } 
     } 
    } 

Ma quando faccio clic sulla mia app, dopo un po 'inizia a bloccarsi e ottengo questi errori:

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) 

Causato da: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications Link fallimento

ho impostato max_conncetions mysql a 1000. La query "SHOW PROCESSLIST" mi mostra un sacco di processi di sonno. Sono questi i pigri?

Sono davvero un po 'bloccato qui. Non so quale impostazione sta causando quel problema. Quindi la mia domanda è: cosa causa questo errore? Che cosa sto facendo di sbagliato? Qualsiasi aiuto apprezzato.

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

sì, questo è giusto. Tutto il processo di sonno è inattivo. Fai una cosa, prima di creare qualsiasi connessione devi controllare lo stato della connessione se c'è una connessione aperta, quindi chiuderla e quindi crearla. –

+0

Grazie per la tua risposta veloce. Beh no, non ci sono altri assegni. Come posso farlo ?;) –

+1

Ti suggerirò di diminuire il tempo di timeout nel tuo codice. 'dataSource3.setConnectionTimeout (1000);' –

risposta

17

paio di cose. Innanzitutto, quale versione di HikariCP, Java e del driver MySQL?

Secondo, 400 connessioni in una piscina? Way too many! Inizia da 10 a 20 in ciascun pool. Ti sorprenderà sapere che puoi gestire alcune migliaia di transazioni al secondo.

In terzo luogo, questa è la seconda domanda in the FAQ. Leggi la risposta e il link. È necessario impostare maxLifetime su qualcosa di più breve (di 1 minuto) rispetto al timeout nativo MySQL.

Infine, attivare la registrazione DEBUG, HikariCP non è rumoroso. Ogni 30 secondi, il thread di pulizia viene eseguito e registra le statistiche del pool.

+0

Questi sono i miei nuovi valori ora: 'dataSource2.setConnectionTimeout (34000); dataSource2.setIdleTimeout (28740000); dataSource2.setMaxLifetime (28740000); ' –

+0

Ok, funziona ora. Ho regolato tutte le impostazioni come hai detto tu. Ho anche trovato una piccola perdita (non ho chiuso la connessione - stupido ...) Ma una perdita è davvero così dannosa? Perché prima non usavo un pool di connessioni e la perdita non era così dannosa. Ah. E grazie ovviamente :) Ha reso la mia giornata. –

+5

Le connessioni chiuse senza pool non sono generalmente dannose, specialmente se si utilizza il commit automatico. L'oggetto Connection sarà garbage collector e alla fine il DB chiuderà il suo lato della connessione. * Con * un pool, le connessioni non chiuse provocheranno il blocco dell'applicazione, poiché il pool ha una dimensione massima e, quando le connessioni non vengono restituite, alla fine verranno svuotate di tutte le connessioni. Il prossimo chiamante di getConnection() verrà quindi sempre timeout. Questo è il motivo per cui quasi tutte le piscine supportano il rilevamento delle perdite. – brettw

Problemi correlati