Re: Limiting concurrent requests by user
On 27 Feb 2012, at 22:18, Hassan Schroeder hassan.schroe...@gmail.com wrote: On Mon, Feb 27, 2012 at 12:04 PM, hernan hbe...@gmail.com wrote: - how to or where to place and access an object shared by all tomcat threads And I'd like to have a solution that can be extended to many tomcat instances (in different servers). Why not just keep counters in an in-memory store like e.g. Redis, MongoDB, Cassandra, etc. etc.? Or queue the work requests in a per user queue. This is better for long running jobs, better for user/resource management and could make your app more responsive. p -- Hassan Schroeder hassan.schroe...@gmail.com http://about.me/hassanschroeder twitter: @hassan - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Limiting concurrent requests by user
On 27 Feb 2012, at 22:26, Christopher Schultz ch...@christopherschultz.net wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hernán, On 2/27/12 3:04 PM, hernan wrote: I've a web service. In order to do a request, a user specifies a username and password via web service parameters along with web service parameters. The web service server, checks user and password and if it is correct, then process the request (else response access denied). The process may take some seconds or a few minutes to be completed. I'd like to limit the number of client requests per user. Does the username/password check take some seconds, or the operation that follows it? I'm asking because if you want to avoid the username/password check, then you'll have to assume that a username presented by a user is accurate -- that can open you up to denial-of-service attacks. Are you using sessions for users, or is everything stateless? I'm thinking to mantain some data structure in memory (shared by all tomcat threads, I don't know how to do that) or in some table in the database to count the number of requests per user. An in-memory structure would be far faster, but of course you have to keep it in memory. The best place for something like this is probably in the ServletContext (aka application), unless you are going to put it into something outside of the JVM (memcached, db, etc.). For each received request, if accepted, increments the counter, and when the process finishes (or if the process fails) decrements the counter. In order to do that, I think I need to have a singleton class and a synchronized method to check and modify the counter. Sincerely, I don't think it's a good idea, because I'll have a bottleneck using synchronized methods. In other hand, I don't know and I'd like: - how to or where to place and access an object shared by all tomcat threads - define a singleton class in tomcat You won't be doing anything with Tomcat per se: everything will be in your own webapp so you don't need to know how to do it in Tomcat. You also don't need a singleton: just a place to store the data. If you use the ServletContext, you can get to it from any servlet during the request. If you need to pass that data into some business logic controller, you can easily do that eve if it's just stored in the ServletContext. I wouldn't worry too much about synchronized access to such a structure, since the operations will be so short (perform a (hash?) lookup, perform an increment/decrement operation). You'll have to worry about your in-memory structure growing too large (huge username cache, for instance), so I would actually recommend scrapping the counter idea and instead using a simpler user in use flag -- something like a hash table with username keys and Boolean values: if a user is doing something, the hash table contains Boolean.TRUE for that username. If the user is not doing anything, then the username does not appear in the structure at all. Of course, that only works if you want to serialize all access on a per-user basis. If you instead want to limit things to, say, 5 simultaneous requests, then you'll have to use counters. Don't forget to release the user-lock in a finally block or you'll end up locking everyone out and/or running out of memory at some point (or both) :) And I'd like to have a solution that can be extended to many tomcat instances (in different servers). Do you want to have a cluster-wide lock-out mechanism so that a user may only make a single request to the cluster at a time, or do you want to just limit the user on a single machine? If you want to limit the user to one-request-per-cluster, then you'll definitely have to go outside the container for a decent solution. I would recommend looking into something like memcached for such a thing. Or a message broker. p I'm using: Tomcat 7.0.14 Upgrade. - -chris -BEGIN PGP SIGNATURE- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk9MAvcACgkQ9CaO5/Lv0PDfOQCfZAIAU4SeuqasbTvpP7t4dqL8 kDIAmgI3N1ZyMhwbNcwzkZTH83l/WbDN =UyLk -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Limiting concurrent requests by user
Hi, I'm looking for ideas/suggestions/patterns about limiting concurrent requests by user. May be you have tackled this kind of problem previously and I'd like to heard your opinions. I've a web service. In order to do a request, a user specifies a username and password via web service parameters along with web service parameters. The web service server, checks user and password and if it is correct, then process the request (else response access denied). The process may take some seconds or a few minutes to be completed. I'd like to limit the number of client requests per user. I'm thinking to mantain some data structure in memory (shared by all tomcat threads, I don't know how to do that) or in some table in the database to count the number of requests per user. For each received request, if accepted, increments the counter, and when the process finishes (or if the process fails) decrements the counter. In order to do that, I think I need to have a singleton class and a synchronized method to check and modify the counter. Sincerely, I don't think it's a good idea, because I'll have a bottleneck using synchronized methods. In other hand, I don't know and I'd like: - how to or where to place and access an object shared by all tomcat threads - define a singleton class in tomcat And I'd like to have a solution that can be extended to many tomcat instances (in different servers). I'm using: Tomcat 7.0.14 Metro 2.0 (jax-ws) MySQL + Hibernate Do you have any suggestion? Thanks in advance Hernán
Re: Limiting concurrent requests by user
On Mon, Feb 27, 2012 at 12:04 PM, hernan hbe...@gmail.com wrote: - how to or where to place and access an object shared by all tomcat threads And I'd like to have a solution that can be extended to many tomcat instances (in different servers). Why not just keep counters in an in-memory store like e.g. Redis, MongoDB, Cassandra, etc. etc.? -- Hassan Schroeder hassan.schroe...@gmail.com http://about.me/hassanschroeder twitter: @hassan - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Limiting concurrent requests by user
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hernán, On 2/27/12 3:04 PM, hernan wrote: I've a web service. In order to do a request, a user specifies a username and password via web service parameters along with web service parameters. The web service server, checks user and password and if it is correct, then process the request (else response access denied). The process may take some seconds or a few minutes to be completed. I'd like to limit the number of client requests per user. Does the username/password check take some seconds, or the operation that follows it? I'm asking because if you want to avoid the username/password check, then you'll have to assume that a username presented by a user is accurate -- that can open you up to denial-of-service attacks. Are you using sessions for users, or is everything stateless? I'm thinking to mantain some data structure in memory (shared by all tomcat threads, I don't know how to do that) or in some table in the database to count the number of requests per user. An in-memory structure would be far faster, but of course you have to keep it in memory. The best place for something like this is probably in the ServletContext (aka application), unless you are going to put it into something outside of the JVM (memcached, db, etc.). For each received request, if accepted, increments the counter, and when the process finishes (or if the process fails) decrements the counter. In order to do that, I think I need to have a singleton class and a synchronized method to check and modify the counter. Sincerely, I don't think it's a good idea, because I'll have a bottleneck using synchronized methods. In other hand, I don't know and I'd like: - how to or where to place and access an object shared by all tomcat threads - define a singleton class in tomcat You won't be doing anything with Tomcat per se: everything will be in your own webapp so you don't need to know how to do it in Tomcat. You also don't need a singleton: just a place to store the data. If you use the ServletContext, you can get to it from any servlet during the request. If you need to pass that data into some business logic controller, you can easily do that eve if it's just stored in the ServletContext. I wouldn't worry too much about synchronized access to such a structure, since the operations will be so short (perform a (hash?) lookup, perform an increment/decrement operation). You'll have to worry about your in-memory structure growing too large (huge username cache, for instance), so I would actually recommend scrapping the counter idea and instead using a simpler user in use flag -- something like a hash table with username keys and Boolean values: if a user is doing something, the hash table contains Boolean.TRUE for that username. If the user is not doing anything, then the username does not appear in the structure at all. Of course, that only works if you want to serialize all access on a per-user basis. If you instead want to limit things to, say, 5 simultaneous requests, then you'll have to use counters. Don't forget to release the user-lock in a finally block or you'll end up locking everyone out and/or running out of memory at some point (or both) :) And I'd like to have a solution that can be extended to many tomcat instances (in different servers). Do you want to have a cluster-wide lock-out mechanism so that a user may only make a single request to the cluster at a time, or do you want to just limit the user on a single machine? If you want to limit the user to one-request-per-cluster, then you'll definitely have to go outside the container for a decent solution. I would recommend looking into something like memcached for such a thing. I'm using: Tomcat 7.0.14 Upgrade. - -chris -BEGIN PGP SIGNATURE- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk9MAvcACgkQ9CaO5/Lv0PDfOQCfZAIAU4SeuqasbTvpP7t4dqL8 kDIAmgI3N1ZyMhwbNcwzkZTH83l/WbDN =UyLk -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Limiting concurrent requests by user
2012/2/27 hernan hbe...@gmail.com The process may take some seconds or a few minutes to be completed. I'd like to limit the number of client requests per user. Why not do you use Tomcat's valves mechanism ? You can implement a request filter on a Context scope Where store the counter of requests ? Memory looks the better option ... except if you application runs on a clustered enviroment. In this case, you can try a database