2010-08-19 9 views
7

Sto utilizzando Spring MVC per creare un sottile strato su un database SQL Server. Quando ho iniziato a testare, sembra che non gestisca lo stress molto bene :). Sto usando Apache Commons DBCP per gestire il pool di connessioni e l'origine dati.Qual è il modo corretto per gestire le connessioni JDBC con Spring e DBCP?

Quando ho tentato per la prima volta ~ 10-15 connessioni simultanee, si bloccava e dovevo riavviare il server (per Dev sto usando Tomcat, ma dovrò essere distribuito su Weblogic alla fine).

Queste sono le mie definizioni bean Spring:

<bean id="dataSource" destroy-method="close" 
     class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="[...]"/> 
    <property name="username" value="[...]" /> 
    <property name="password" value="[...]" /> 
</bean> 

<bean id="partnerDAO" class="com.hp.gpl.JdbcPartnerDAO"> 
    <constructor-arg ref="dataSource"/> 
</bean> 

<!-- + other beans --> 

e questo è come li uso:

// in the DAO 
public JdbcPartnerDAO(DataSource dataSource) { 
    jdbcTemplate = new JdbcTemplate(dataSource); 
} 

// in the controller 
@Autowired 
private PartnerDAO partnerDAO; 

// in the controller method 
Collection<Partner> partners = partnerDAO.getPartners(...); 

Dopo aver letto in giro un po ', ho trovato le proprietà maxWait, maxActive e maxIdle per il BasicDataSource (da GenericObjectPool). Ecco il problema Non sono sicuro di come dovrei impostarli, in termini di prestazioni. Da quello che so, Spring dovrebbe gestire le mie connessioni quindi non dovrei preoccuparmi di rilasciarle.

<bean id="dataSource" destroy-method="close" 
     class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="[...]"/> 
    <property name="username" value="[...]" /> 
    <property name="password" value="[...]" /> 
    <property name="maxWait" value="30" /> 
    <property name="maxIdle" value="-1" /> 
    <property name="maxActive" value="-1" /> 
</bean> 

In primo luogo, ho impostato maxWait, in modo che non sarebbe appendere e invece un'eccezione quando nessun collegamento era disponibile dalla piscina. Il messaggio di eccezione era:

Impossibile ottenere la connessione JDBC; l'eccezione annidata è org.apache.commons.dbcp.SQLNestedException: Impossibile ottenere una connessione, errore di piscina Timeout in attesa di oggetto inattivo

Ci sono alcune query a lungo in esecuzione, ma l'eccezione è stato gettato, indipendentemente dalla complessità query.

Quindi, ho impostato maxActive e maxIdle in modo che non generasse le eccezioni in primo luogo. I valori predefiniti sono 8 per maxActive e maxIdle (non capisco perché); se li metto a -1 non ci sono più eccezioni generate e tutto sembra funzionare.

Considerando che questa applicazione deve supportare un numero elevato di richieste simultanee, è ok lasciare le impostazioni su infinito? Spring gestirà davvero le mie connessioni, considerando gli errori che stavo ricevendo? Devo passare a C3P0 considerando che è un po 'morto?

+0

Se si ottengono eccezioni, la registrazione dello stacktrace consente di identificare facilmente il problema. Esistono query a lungo termine in cui vengono visualizzati i problemi? –

+0

Ho aggiornato il mio post con il messaggio di eccezione e alcune informazioni extra. –

risposta

6

Come già rilevato, il pool di connessioni dbcp predefinito è 8 connessioni, quindi se si desidera eseguire 9 query simultanee, una di esse verrà bloccata.Ti suggerisco di connetterti al tuo database ed eseguire exec sp_who2 che ti mostrerà cosa è connesso, attivo e se tutte le query sono bloccate. Puoi quindi confermare se il problema si trova nel db o nel tuo codice.

Finché si utilizza la famiglia di oggetti JdbcTemplate di Spring, le connessioni verranno gestite come previsto e, se si desidera utilizzare un DataSource non elaborato, assicurarsi di utilizzare DataSourceUtils per ottenere una connessione.

Un altro suggerimento: prima di Spring 3, non utilizzare mai JdbcTemplate, attenersi a SimpleJdbcTemplate, è ancora possibile accedere agli stessi metodi utilizzando SimpleJdbcTemplate.getJdbcOperations(), ma si dovrebbe trovare la scrittura di codice molto più bello utilizzando i farmaci generici e rimuovere la necessità per creare mai istanze JdbcTemplate/NamedParameterJdbcTemplate.

2

Cambiamo la prospettiva.

ma l'eccezione è stato gettato , indipendentemente dalla complessità di query

Potrebbe essere perché il tavolo o il record nella tabella, il quale si sta eseguendo la query contro è stato bloccato (da qualche altra operazione attiva) e quindi scade.

Provare a eseguire la stessa query dal client SQLServer e se impiega molto tempo, si può essere sicuri che sia la tabella o il blocco del record a causare questo.

+0

Vedo il tuo punto, ma il problema scompare completamente quando imposto i parametri 'maxActive' e' maxIdle' dell'origine dati su un valore elevato (o su infinito). Questo mi porta a pensare che il problema è da ConnectionPool, come afferma il messaggio di eccezione. –

8

Il parametro DBCP maxWait deve essere definito in millisecondi. 30 ms è un valore molto basso, si consiglia di aumentarlo a 30000 ms e riprovare.