I'm building a Java EE application that one of its requirements is to send messages for registered e-mails (around 1000 to 2000). The access to that application is limited and in any time there will be less than 2 user logged in.
For sending e-mails I'm using JavaMail, a #Stateless bean and #Asynchronous method.
My problem is that it takes too long to send the 1000+ e-mails, around 1.2 secs for each e-mail in my development server. What should I do to reduce time ? Can I span multiple Stateless beans? Or in that case creating around 10 to 15 threads, with so low user access isn't a too bad?
Your performance problem is probably due to creating a new connection to send each message, as described in the JavaMail FAQ. Your code needs to be able to cache and reuse the connection to the mail server. A better approach for sending the messages asynchronously might be to put the information necessary to construct the message in a JMS message and then use a (pool of) MDB to process the information, turn it into a mail message, and send it, while caching and reusing the Transport object that represents the connection to the server.
You need to configure the async thread pool size inside your container, default size is usually 15 parallel threads. There isn't one thread per bean instance but if the pool fills up there will be a queue and max 15 sending at a time.
Related
I have a scenario, An MSMQ queuing system...Records are queued on a timely basis...A WCF listener that listens to the queue, starts processing the records as soon as the records are queued up...does some process and sends email after that(There are 10 queues and 10 listeners out of which 3 listeners are responsible for email sending). The problem I am facing is the email sending part, where larger data is queued up then for some records I get the following error
Service not available, closing transmission channel. The server response was: 4.3.2 The maximum number of concurrent connections has exceeded a limit, closing transmission channel
The class that sends email is
public class A
{
//Method is static as it is a common method used by other processes running in parallel
public static void SendMail()
{
MailMessage mail = new MailMessage();
SmtpClient client = new SmtpClient();
///Email information goes here
client.Send(mail);
}
}
I guess even my method is static the smtp object is instantiated each time which causes the problem. Even if I increase the concurrent connections it is not solving the problem. I have a couple of workaround but required some more light on this.
Limit the no. of concurrent connections to let say 100. So even I have 1000 records queued up and the listeners starts processing them in parallel the smtp process will not use more than 100 connections at a time, wait for it to complete and then take up the next 100 and so on. But I am not sure how to do this.
Use parallel foreach loop or SmtpClient.SendAsync method, but here also my proficiency level is not much regarding these methods, so I am a little bit afraid(I need to make sure there is no major performance hit).
So just needed a stable and better approach to solve this.
I'm using Managed Executor Service to implement a process manager which will process tasks in the background upon receiving an JMS message event. Normally, there will be a small number of tasks running (maybe 10 max) but what if something happens and my application starts getting hundred of JMS message events. How do I handle such event?
My thought is to limit the number of threads if possible and save all the other messages to database and will be run when thread available. Thanks in advance.
My thought is to limit the number of threads if possible and save all the other messages to database and will be run when thread available.
The detailed answer to this question depends on which Java EE app server you choose to run on, since they all have slightly different configuration.
Any Java EE app server will allow you to configure the thread pool size of your Managed Executor Service (MES), this is the number of worker threads for your thread pool.
Say you have a 10 worker threads, and you get flooded with 100 requests all at once, the MES will keep a queue of requests that are backlogged, and the worker threads will take work off the queue whenever they finish work until the queue is empty.
Now, it's fine if work goes to the queue sometimes but if overall your work queue increases more quickly than your worker threads can take work off the queue, you will run into problems. The solution to this is to increase your thread pool size otherwise the backlog will get overrun and your server will run out of memory.
what if something happens and my application starts getting hundred of JMS message events. How do I handle such event?
If the load on your server will be so sporadic that tasks need to be saved to a database, it seems that the best approach would be to either:
increase thread pool size
have the server immediately reject incoming tasks when the task backlog queue is full
have clients do a blocking wait for the server task queue to be not full (I would only advise this option if client task submission is in no way connected to user experience)
I'm code reviewing a WCF service.
In the header of each message we inject data that the service is going to use later to build a connection string to a DB.
That's because the service is going to be used by a number of different sites, each with its own DB that the service has to query.
We use wcf extensibility. We have a custom MessageInspector that, after receiving the request, extracts the data from the message header, creates a context (that implements IExtension) and adds it to OperationContext.Current.Extensions.
Before sending the reply the custom context is removed from the Extencions collection.
This is a fairly common pattern, as discussed here:
Where to store data for current WCF call? Is ThreadStatic safe?
and here:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/319cac66-66e8-4dfe-9a82-dfd289c9df1f/wcf-doesnt-have-session-storage-so-where-should-one-store-call-specific-data?forum=wcf
This all works fine as long as the service receives a request, processes it, sends the reply and receives the next request.
But what if the service receives a request and before being able to reply it gets a second request? I built a small console application to test it. I send 2 messages from 2 different threads, I made the wcf service wait for 2 seconds, to ensure the second request comes in before the first one is completed and this is what I get:
Site Id : test1450 ; Session: uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70;id=2 : Thread Id: 6
Site Id : test1450 ; Session: uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70;id=3 : Thread Id: 22
It looks like wcf creates 2 sessions executing on 2 different threads, but Site Id is the same. It shouldn't. Judging from this it looks like OperationContext.Current.Extensions is a collection shared between threads.
Right now I'm inclined to think my test is wrong and I missed something.
Has anyone tried something similar and found out that OperationContext.Current is not thread safe?
OperationContext.Current like other similar properties such as HttpContext.Current have thread affine (or thread static) values. So they are thread safe in the sense that multiple threads can read them, but different threads will get different instances. They can be thought of as dictionaries between specific threads and instances.
So in this context they are not thread safe.
Requests are served by a thread pool so concurrent requests will have different thread ids. (up to a point where the thread pool is full, then requests will be put on hold)
I have a webservice using Hibernate as DAL - using MySql with InnoDB.
Since I want to make webservice calls really short (for better user experience in client side) I am using 2 threads with msg queue to do some work.
1 thread gets userId in the message, loads the user from the DB and gets it email address and send email to.
Second thread is used like this:
Webservice call.... doing some actions.
Adding ActivityLog into the DB.
Doing session.save( log ); session.commit();
Now we send message to the thread with the logId.
Message received - insert new entries into timeline table (userid, logId). Session is different session object than the main logic session object.
Should I have problems in this? in lazy loading? in the threads, since message is sent to the thread after commit()?
A Webservice -> Message queue architecture is pretty standard in case you don't need synchronous reply to the web service.
In the web service, store whatever you want into the database and the message queue will pick that up later.
A different session is not a problem, but if you have a single static Session for each of these threads, they may be subject to Session bloat: objects piling up in the Session cache.
More on this: http://suryagaddipati.wordpress.com/2008/02/15/hibernate-rich-clients-and-long-running-sessions/
In my application, I have a multiple file upload AJAX client. I noticed (using a stub file processing class) that Spring usually opens 6 threads at once, and the rest of the file upload requests are blocked until any of those 6 threads finishes its job. It is then assigned a new request, as in a thread pool.
I haven't done anything specific to reach this behavior. Is this something that Spring does by default behind the scenes?
While uploading, I haven't had any problems browsing the other parts of the application, with pretty much no significant overhead in performance.
I noticed however that one of my "behind the scenes" calls to the server (I poll for new notifications every 20 secs) gets blocked as well. On the server side, my app calls a Redis-based key-value store which should always return even if there are no new notifications. The requests to it start getting normally processed only after the uploads get finished. Any explanation for this kind of blocking?
Edit: I think it has to deal with a maximum of concurrent requests per session
I believe this type of treading belongs to the Servlet Container but not to Spring.