wood burning stoves 2.0*
The moose likes Struts and the fly likes Web application goes extremely slow with more than 5 users logged in Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Frameworks » Struts
Bookmark "Web application goes extremely slow with more than 5 users logged in" Watch "Web application goes extremely slow with more than 5 users logged in" New topic
Author

Web application goes extremely slow with more than 5 users logged in

shiva sarna
Greenhorn

Joined: Jul 23, 2006
Posts: 23
Hi,


In my struts application if more than 5 users login at a time it goes extremely slow.

I have checked my action classes and DAO and all my database connection are closed properly.

The login page takes lot of time to load though it is fast if only one or two users have logged in.

Please let me know if there is any other way to pool the database connection.


public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
log.warn("INSIDE AUTHENTICATE ACTION");

LoginForm currentLogin = (LoginForm) form;

String type = null;
int flag = 0;
int userId=0;
String target = "success";
TestTemplate testTemplate = null;

String uid = "";
String pwd = "";
String nonEncryptedPassword = "";

int count = 0;
DataSource dataSource = null;
Connection conn = null;

HttpSession session1 = request.getSession();
ActionErrors errors = new ActionErrors();

dataSource = getDataSource(request);

conn= dataSource.getConnection();

further code goes here
.
.
.
.
.
}

I pass the conn object to my DAO methods

count = UserData.validateUser(uid, pwd, conn);

and then after querying the database I close the statement and result set and int my action class close the connection as well.

if (conn != null) {
conn.close();
conn = null;
}

My question is:

In my web application I am calling a lot of action clases which constantly interact with my database and in all those action clases this is the way the connection is obtained and database queried.
Then why my application goes slow with more users.
Can you please suggest me some ways to improve my application performance.
My application should run fast with atleast 100 users logged in but it goes extremely slow just after five.

Thanks for your time and advice in advance.

regards

Shiva


SCJP 5.0
Rusty Smythe
Ranch Hand

Joined: Aug 09, 2006
Posts: 93

Every time you open and close your datasource, you are taking extra time.

You might run a profiler on your data store to see
1) How many connections are being created (is there a maximum limit that you're hitting?), and
2) How fast it takes to open a new connection.

Ideally, you would open your datasource once and leave it open for the life of the user's session; this is the general concept of data pooling.

Check out Hibernate; in my opinion, it is the easiest way to interact with a database once you learn it*.
shiva sarna
Greenhorn

Joined: Jul 23, 2006
Posts: 23
Hi Rusty,

I have a question. While I was searching on internet for this problem I came across JNDI connection pooling. Could you suggest how I can do this kind of poling in my application. Any type of documentation on this will be helpfull.

I used jmeter for performance testing and checked out the console for server response. My application works fine for 5 users but as soon as I try to log on 10 users users the server hangs.

thanks for your advice and help.

regards

shiva
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
The way you set up a JNDI Datasource is different for each application server. I'd suggest you search the documentation for the specific application server you're using. If you're using Tomcat 5, here is a good link.

Even though the method for creating the datasource differs by app server, the method of accessing the datasource in your application code is the same. Here is an example:


Merrill
Consultant, Sima Solutions
Ajay Xavier
Ranch Hand

Joined: Jan 03, 2005
Posts: 109
Hi Siva,

I belive specifying the datasource in struts-config.xml is not an efficient way. Try to put the database access details (like lookup, connection handling) in a utility class. Call a delegte class form your Action class which in turn uses the utility class for executing the operations against the database.

Regards,
Ajay.
shiva sarna
Greenhorn

Joined: Jul 23, 2006
Posts: 23
Thanks Merrill and Ajaya for your help. Where have I gone wrong. Why just specifying the datasource in struts config is not sufficient. The books that I referred suggested this method of connection pooling. When connections are pooled then why the performance is degrading.
Our server configuration is perfect,we have zeroed the problem on the database connection code.

Why JNDI connection pooling is better than specifying the datasource in struts config.

Can you please also suggest a document which gives me a proper reason explaning JNDI connection pooling is better than struts connection pooling.

It will be a great help to my team and then we can start making the changes in our application.

thanks again for your help and advice which is useful for me.

Regards

Shiva
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
The Struts datasource utility was never intended as a long-term production solution. This is one of the resons it is deprecated. It is no longer supported in Srtus 1.3.5, which is the latest version of Struts 1. If you search this forum, you will find dozens of posts with some sort of problem with Struts connection pooling. Trust me. You're better off not using it.

Commercial application servers spend thousands of dollars and hundreds of person-hours in creating good, efficient connection pooling mechanisms for their products. It is just common sense that these are going to be better and more efficient since they were built specifically for use with that application server.

Connection pooling through JNDI is and has been for a long time the best practice for relational database connections in J2EE applications. See chapter 31 of the Sun J2EE Tutorial.
[ December 17, 2006: Message edited by: Merrill Higginson ]
shiva sarna
Greenhorn

Joined: Jul 23, 2006
Posts: 23
Thanks Merril for your help and advice.

Infact my team has asked me to say thanks to you on their behalf, we all were
cracking our heads over this.

take care

Regards

Shiva
shiva sarna
Greenhorn

Joined: Jul 23, 2006
Posts: 23
Hi Merrill,

Where the server hanged after 5 users now I am able to run the test for 100 users and it is working fine.

But now the problem is that we have more than 1300 Action classes with us and to change the way connections are called will be a huge task.

I just changed the code for 3 action classes and tested for a module.

So is there a way where I can directly use JNDI without making any changes to all the action classes.

thanks in advance for your time and advice.

regards

shiva
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
It's never a good idea to put database connection code in your Action class. This type of code is better off delegated to another class. The best suggestion I can make would be to create a JDBC Helper class that handles getting the reference to the DataSource and creating the connection. Bear in mind that looking up the datasource in JNDI is a relatively expensive operation. Once you have the reference, it's a good idea to cache it in a singleton or through some other means so you don't have to keep looking it up.

If you currently have logic in each of your action classes that connects to the Struts database, I don't see any alternative to changing them all now. Just design it so that if any future changes have to be made, they can be made in a central place.
shiva sarna
Greenhorn

Joined: Jul 23, 2006
Posts: 23
Hi Merrill,

When you say JDBC helper class, is it possible to get the reference to the database once and then keep it in session for a user.

Is there any example on net where they have explained how to create a JDBC helper class and get a reference from it.

One more question. Yesterday when I was checking the database connections, I saw that the old connections are not released for example if 5 users login 5 connections will be created. If after logging of these 5 users, I log them back in I see on my ser 10 database connections. I understand this is because of the pool size but then after some time the pool gets exhausted.

So how can I determine the maximum connections in the pool.

Because the client can have anywhere between 100 to 5000 users.

thanks for your help.

regards

shiva
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Originally posted by shiva sarna:
When you say JDBC helper class, is it possible to get the reference to the database once and then keep it in session for a user.

If by "reference to the database" you mean a reference to the DataSource object, the answer is yes. If you mean a JDBC Connection object, the answer is no. Anything stored in the session must be serializable, and a JDBC connection is not serializable.

Even so, an HTTPSession is not the ideal place to put the DataSource. It's the same for all users, so if you're going to cache it, you might as well cache it in one place for all, such as in a Singleton, or in the ServletContext object.
Originally posted by shiva sarna:
Is there any example on net where they have explained how to create a JDBC helper class and get a reference from it.

This type of class follows a common pattern known as a "service locator". This link explains how to create one.
Originally posted by shiva sarna:

One more question. Yesterday when I was checking the database connections, I saw that the old connections are not released for example if 5 users login 5 connections will be created. If after logging of these 5 users, I log them back in I see on my ser 10 database connections. I understand this is because of the pool size but then after some time the pool gets exhausted.


The fact that the pool is growing to this extent is an indication that you are not closing the connections properly. You should call the close() method on the connection after each transactional unit of work. It is best to include the close in a finally clause so that it takes place regardless of whether an exception is thrown or not.

Regarding your question about what sizes to use: You first need to talk to your DBA and find out how many simultaneous connections the Database itself will allow. The number in your connection pool should always be comfortable below this number. Other than that, the best advice I can give is to take your best guess and set them to some value, do some load testing, change the settings, load test again, and measure improvments or degradations caused by the change in settings.
shiva sarna
Greenhorn

Joined: Jul 23, 2006
Posts: 23
Hi Merrill,

You were right. Connection was not closed in one of the methods.

The module is working fine, pool size is not increasing and performance is fast.

The problem that we face now is how to make changes to all our action classes.

I really can't think of anything as of now. Even if I write a helper class I will have to refer it in all the classes where I have called the datasource.

You have been of great help.

Thank you.

regards

shiva
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Web application goes extremely slow with more than 5 users logged in