Utilizzo corretto del pool di connessioni

1

Sono confuso su come interagire correttamente con il mio database Postgres attraverso la tipica esperienza utente sulla mia app web. Sto cercando un chiarimento sul metodo più efficiente di comunicazione con il database, senza sovrascrittura (spamming).

Attualmente utilizzo org.apache.commons.dbcp.BasicDataSource per connettermi al mio database ogni volta che è necessario, e chiudo sempre la connessione al termine. Ha perfettamente senso per me quando sto facendo una query di una volta.

Ma se la query può essere eseguita più volte a discrezione dell'utente?

Qui ci sono 2 occorrenze specifiche nella mia app:

  • Se un utente immette le proprie credenziali e fa clic su "Accedi" nella pagina di accesso, il database viene interrogato per convalidare le credenziali. Cosa succede se l'utente fa clic sul pulsante 100 volte? Ciò significa che potrebbero potenzialmente inviare spam al pulsante, causando l'invio di più query al mio database. Potremmo imporre un limite manuale (come 5 clic al minuto) ma dove tracciamo la linea?
  • Una volta effettuato l'accesso, il loro profilo utente deve essere compilato e possono "Salvare" le modifiche dopo l'attivazione di qualsiasi modifica di campo. Quindi sarebbe molto facile inviare spam maliziosamente il pulsante Salva dopo che un nuovo carattere è stato digitato.

Capisco che una nuova connessione non venga creata ogni volta che viene chiamato getConnection() , ma non capisco se la meccanica interna di BasicDataSource gestisca questo potenziale spamming.

Una volta che l'utente fa clic su "Salva", è importante che le modifiche siano accessibili a tutti gli altri utenti. Ad esempio, l'utente A potrebbe fare clic su "Rendi visibili ad altri utenti" e quindi fare clic su "Salva". L'utente B dovrebbe ora essere in grado di trovare l'utente A nella nostra app.

Mi consiglia di utilizzare Connection Pool, Hibernate, Redis, cache2K o qualche altro strumento / framework? O è sufficiente interrogare il database ogni volta che il pool lo ottimizzerà sul back-end?

Grazie mille. Sto usando Java 8 + Vaadin 8.

    
posta Mathomatic 12.12.2018 - 17:09
fonte

3 risposte

1

If a user types in their credentials and then clicks "Login" on the login page, the database is queried to validate the credentials. What if the user clicks the button 100 times?

Ci sono diversi modi per affrontarlo. Mi chiedo però se è qualcosa di cui dovresti davvero preoccuparti. 100 richieste non sono molto nello schema delle cose. Ignorando le connessioni per un momento, se si esegue la stessa query 100 volte di seguito, in genere è molto meno lavoro per il DB rispetto all'esecuzione di 100 query per dati diversi a causa della memorizzazione nella cache di ottimizzazioni di pagine, percorsi e così via.

Once logged in, their user profile must be filled and they can 'Save' the changes after any field changes are triggered. So it would be very easy to maliciously spam the save button after a new character is typed

I risparmi sono un po 'più costosi, ma ancora una volta, questo sarà davvero importante? Sarei più preoccupato per possibili incoerenze di stato rispetto allo stress sul DB. A meno che tu non stia eseguendo il DB su un'infrastruttura veramente limitata, dubito che noterai un utente che sta facendo questo.

Per entrambi, un processo automatico che sommerge il sistema con molte migliaia di richieste al secondo, potrebbe essere qualcosa di cui dovresti preoccuparti. Un utente che schiaccia un mouse si muove in estrema lentezza per i sistemi che eseguono miliardi di istruzioni al secondo.

Do you recommend I use Connection Pool, Hibernate, Redis, cache2K or some other tool/framework? Or is it sufficient to query the database each and every time since pool will optimize it on the back-end?

Sono un po 'confuso dalla tua menzione del pool di connessioni qui poiché sembra implicare altrove nella tua domanda che stai già utilizzando un pool. Questa sarebbe l'unica ragione per cui non creerai una nuova connessione su ogni richiesta anche se chiudi la connessione dopo ogni richiesta.

Quando si chiama close sull'origine dati utilizzando il pool, generalmente si utilizza la connessione che si stava utilizzando e la si restituisce al pool. Ciò impedisce la riconnessione su ogni richiesta. Questo è importante perché per le query più sensibilmente scritte, il tempo necessario per stabilire una connessione è molto più costoso rispetto all'esecuzione della query e richiederà molto più tempo. Se non stai facendo il pool, l'utente che fa clic con il mouse molto velocemente potrebbe causare problemi.

Per quanto riguarda il caching e le altre cose che hai menzionato, sembra eccessivo per ciò di cui stai parlando. La prima cosa che aggiungerei è una semplice cache in memoria. Se ciò non è sufficiente, aggiungi una cache distribuita. Ma non farei nulla di questo se non sapessi in modo specifico quali problemi risolvono per te. Altrimenti probabilmente stai solo creando nuovi problemi da affrontare.

    
risposta data 17.12.2018 - 22:34
fonte
1

Non lavoro molto in Java e non ho familiarità con gli strumenti disponibili, ma nella maggior parte delle piattaforme moderne (che include Java), il livello / oggetto di accesso ai dati avrà un pool di connessioni, che gestisce ciò per te.

Durante la scrittura del codice, l'approccio generale è infatti quello di aprire quando è necessario, eseguire query / eseguire, quindi chiudere. Tuttavia, questi comandi vengono passati al gestore delle connessioni in un modo o nell'altro, che è generalmente responsabile della decisione dei dettagli sul fatto che veramente chiuda o meno quella connessione. Il gestore del pool potrebbe tenere aperta la connessione e mantenerla fino a quando non viene fatta un'altra richiesta, riutilizzando quindi la connessione aperta ed evitando il sovraccarico di riaprirla. Questo è un dettaglio di astrazione di cui generalmente non devi preoccuparti (anche se, come sempre, è bello sapere come funziona l'astrazione, e perché, perché ci possono essere casi in cui vuoi bypassare l'astrazione, ma è raro nel caso di pool di connessioni, comunque per la maggior parte delle applicazioni).

E infine, per le preoccupazioni di "spamming" nel database, questo di solito è anche un non-problema. I database spesso gestiscono migliaia di richieste al secondo. Tutto ciò che un utente può lanciare manualmente è probabile che venga agitato senza alcun problema. Un concetto correlato sarebbe un attacco DoS / DDoS: in cui qualcuno scrive codice che cercherà di inondare il tuo sistema di richieste e quindi di impedire ad altri di utilizzarlo. Tuttavia, questa è una bestia molto diversa e tende a influenzare il server di hosting web molto prima di quanto possa causare problemi al database.

Tutto sommato, è bello essere preoccupati per queste cose, ma l'esperienza alla fine ti porterà alla consapevolezza che ci sono molte più cose pertinenti a cui preoccuparsi:)

    
risposta data 17.12.2018 - 23:09
fonte
1

But what if the query can be performed multiple times at the discretion of the user?

Puoi iniziare rilanciando la funzione di invio sul tuo client, non permettergli di inviare nuovamente un'altra richiesta fino a quando non trascorre un determinato intervallo di tempo o almeno di disattivare il pulsante fino a quando non ricevi una risposta (o un timeout). Quindi fai lo stesso sul lato server.

Once a user clicks 'Save' it's important that the changes are accessible to all other users. For example, User A could click 'Make Visible to Other Users' and then click 'Save'. User B should now be able to find User A in our app.

Qualsiasi modifica diventerà evidente una volta eseguita la query e eseguito un commit

Do you recommend I use Connection Pool

Normalmente si utilizzerà un pool di connessioni in una situazione in cui ci si aspetterebbe che più transazioni si verifichino contemporaneamente (la transazione è un'operazione di blocco) e non si desidera che tutti siano in attesa su quell'un oggetto di connessione (inedia).

    
risposta data 17.12.2018 - 16:32
fonte

Leggi altre domande sui tag