简体   繁体   中英

Database Connections from Web Application without connection pool

I'm trying to wrap my head around a proper method of establishing JDBC connections to a database from a JSF web application. My normal approach to this problem is to create a Data Source within the application server and connect to it via its JNDI name inside my code. Essentially, all users would be sharing the same database user account during their entire session via the pool.

Unfortunately the requirements of a new project I'm working on prevents me from doing this. Each user who connects to the application must log in to the RDBMS using unique credentials. I have a sketch of how I'd implement the code associated with this, but I'm not 100% clear on the overall architecture. Do application servers (Tomcat, Glassfish, WebLogic) have functionality to support this?

Right now, the only way I can seem to accomplish this is by having each user session directly create a JDBC connection back to the database. While I believe this would work, it just doesn't feel right.

Am I missing something?

You are missing something - very much I assume: Reasonable system design. ;) The whole idea of managing users with their database credentials is good for exactly one use case imho - managing databases. For everything else, it imposes more problems than it does good... So let the shitstorm begin... ;)

BOT: There is a dilemma. You basically have to create a connection pool for each user, simply because otherwise you would have to create a connection to the database each time your datasource runs in a connection timeout. And a three way handshake plus authentication isn't exactly a cheap thing to do - latencies will kill your performance. While some drivers can be configured accordingly, this is a bad idea in general and most drivers aren't good at managing connections themselves because of what is called "separations of concerns". On the other hand, each connection "pool" needs only some 5 connections, since it is very unlikely that the same user will do many operations in parallel.

Note: The only driver I am aware of which manages connections and pools decently is MongoDB's driver.

Now here is the problem: You can't attach a connection pool to a session. Not without walking quite a few miles, and I doubt that it is possible altogether.

One idea to get around this is to create a connection pool for a user when he or she logs in and register it dynamically with JNDI. The problem is that this is not very scalable (assume you have a couple of hundreds of users). So you have to make sure that the pool is removed when a session terminates (either by logout or timeout). Plus, the code has to be maintained.

Another idea is to use Apache Shiro and write a custom Realm which simply tries to log in into the database to check the credentials, throwing an AuthenticationExcepion if this fails. The tradeoff here is that you'd have to initialize a connection each time, which has some latency. Your realm might even use an application wide connection pool and inspect the databases metadata for authentication and authorization data. Of course that would make it necessary to access the database as an privileged user - which is a horrible idea.

Bottom line: No matter which way you look at it, administering an applications authentication and authorization needs via the database may eliminate the authentication and authorization layer in the application, but in turn requires an additional layer of abstraction (you don't want to change your service's code in case some database mechanisms change, do you?), imposes scalability problems as we saw and ties your code very much to one database (except of course you don't want fine grained permissions and can live with "worked, didn't work" results).

I'm not sure what the overhead of an empty connection pool is, nor how many users are involved, but I would suggest keeping a global list of connection pools configured for a low max connections (2?) and an aggressive idle timeout all the way back to zero pool connections. Then when a user logs in, check if they already have a pool referenced by their username, create a new one if not and stick it in the pool, and use that one henceforward for that user's connections.

That way you get the benefits of a pool with the least overhead. Whether this is feasible probably depends on your user count.

I would certainly look to find the lowest overhead pool implementation that would be functional for you - there are several to choose from. c3p0 has worked great for myself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM