|
|
||
Jean-Francois Arcand's Blog
«Fast web application redeployment using JMX |
Main
| Using Mustang's jmap/jhat to profile GlassFish »
Grizzly part III: Asynchronous Request Processing (ARP)Posted by jfarcand on February 01, 2006 at 03:13 PM | Comments (2)As described in part II, it is possible to extend the Grizzly Http Engine by writting Pipeline, Algorithm, Handler and AsyncHandler. By default, every HTTP connection are executed synchronously, e.g the request is parsed, the servlet executed and the response flushed to the browser. There is situation where this model doesn't work, e.g. when a business process is calling out to another one over a slow protocol, or if there is a work flow interruption, like the "manager approval email" case. Fortunately, it is possible in Grizzly to implement asynchronous request processing (ARP) using the AsyncHandler interface. But not only in Grizzly ;-) Next couple of paragraphs will discuss the set of interfaces available, describe the default implementation and conclude with a Servlet which execute only when a new message is available inside a Gmail account. The Servlet can be seen as HTTP Gmail notifier. But first, what's the goal or supporting ARP? Goal Available Interfaces AsyncHandler: This interface is the main entry point. When ARP is enabled, Grizzly will delegate the request processing execution to this interface. Instead of executing a Task, the Task execution will be delegated to the AsyncHandler implementation. This interface is mandatory. AsyncExecutor: This interface implementation will usually decide when a Task needs to be interrupted, under which conditions (using AsyncFilter), and when the Task needs to be resumed. A Task is interrupted when the conditions required for its execution aren't meet. An AsyncExecutor must have one or more AsyncFilter. If no AsyncFilter are defined, the SRP model will happens. This interface isn't mandatory, but recommended. AsyncFilter: Implementation of this interface will determine if the current request meet its execution conditions, e.g. does the request need to be executed or be interrupted. An AsyncFilter who decide to allow all requests to be executed without being interrupted will simulate the SRP mode. The Default implementation 1. The request execution is delegated to the DefaultAsyncHandler Note that DefaultAsyncExecutor.preExecute/interrupt/postExecute always delegate the execution to a set of ProcessorTask methods, thus requests are always executed the same way, independently of ARP or SRP. It is important to note that the default implementation isn't locking the thread when a Task is interrupted. The default Scheduler only have one thread to hold all SelectionKey associated with all interrupted requests. OK that's it for the theory. Let's work on a real application using GlassFish.
What we need is a Servlet that execute only when new emails are available in a Gmail account. Not only to Gmail, but to any POP3 account. In this case, the execution conditions would consist of connecting to the account, look for new emails. If new emails are available, then execute a Servlet that list all new emails (or display a flashing flag). Whatever the Servlet does, the goal here to to execute it only when its execution conditions are meet. The solution is simple. We just need to define an AsyncFilter who does: 1. Connect to our Gmail account Fortunately we can use JavaMail for (1), and Grizzly default ARP implementation for (2) and (3), and by adding a new AsyncFilter implementation. Then, we just have to: 1. Starts Grizzly using ARP mode. The implementation just consist of: + JavaMailAsyncFilter: this is the AsyncFilter than will determine if ARP or SRP is used. You can find the basic implementation here. Make sure you read the README.TXT which explain how to build and deploy in GlassFish. Since ARP is not a default feature, it is a little complicated to setup (feel free to post here for help). I've tested with my local POP3 provider and my Gmail account and it worked fine. When testing with Gmail, I selected Settings > Forwarding and POP. In the POP Download, I've picked "Enable POP only for mail that arrives now on". Thus my first request to the Servlet will not meet the execution conditions, and the Servlet will be interrupted until I send an email to myself. Of course the Gmail implementation is far from perfect, and can be greatly improved (improvement are more that welcome!). My goal here was to demonstrate how you can extend Grizzly and start supporting ARP. As always, contributions are welcome. That's it. Next time I will try to give some NIO tricks and tips (specially when it time to deal with OP_WRITE). P.S Thanks to Andrea Egloff for his useful feedback on the default ARP implementation. Bookmark blog post: CommentsComments are listed in date ascending order (oldest first) | Post Comment
| ||
|
|