Using Asynchronous Servlets to Deal with Hung Threads
Pages: 1, 2, 3

An example of using the Abstract Asynchronous Servlet

Imagine an application that outputs the stock exchange quotations. We suppose that stock values are obtained using a JCA interface, which, in turn, accesses a banking system. The customer needs feedback within a few seconds. However, if thousands of people are connected within the same time period, it's likely that the response will be delayed, and, in the worst scenario, this will lead to a HTTP connection timeout.

But the damage can go even further: If customers notice that the site is not responsive, they will go on clicking the refresh button, flooding the application server with new requests.

It's time to put a brake on this. Well, the bad news is that if the backend resource is stuck, we cannot actually satisfy the customer's request. However, if we cache the latest stock ticker along with the time it was gathered, we could produce this information inside our timeout callback, pointing out the time at which this data was collected. In our example, we set the timeout to 2500 milliseconds. If the response is not produced by that time, doTimeout() will kick in. Figure 3 shows our architecture.

doTimeout callback

Figure 3. The doTimeout() callback is triggered when the servlet is not notified in time

Let's look at the servlet in more detail:

public class AsyncServlet extends AbstractAsyncServlet {



   // Need JDK 1.5

   Hashtable  <String,Long> hashStocks = new Hashtable<String,Long>();

   Date dateLastUpdate = new Date();



   public void init() {

    
                        
// The default request timeout period in milliseconds.

        super.setTimeout(2500);

         
                        
// The default interval period in milliseconds at which 

        // requests will be checked for timeouts.

        super.setScavangeInterval(1);

    
                        
// Populate hashtable with Stock initial value

        hashStocks = readStocksValue();

   }



  public boolean doRequest(final RequestResponseKey rrk)

        throws ServletException, IOException {

  

     HttpServletRequest req = rrk.getRequest();

     HttpServletResponse res = rrk.getResponse();

  

      
                        
// Read Stock quotation from Back end

     hashStocks = readStocksValue();

  

     TimerManagerFactory.getTimerManagerFactory().getDefaultTimerManager()

                .schedule(new TimerListener() {

  

        public void timerExpired(weblogic.timers.Timer arg0) {

            try {      

                 
                        
  // This will trigger delivery of the response.

                   AbstractAsyncServlet
                        
.notify(rrk, null);

             } catch (Exception e) {

                e.printStackTrace();

             }      

        }      

      }, 1000);

  

     return true;  

  }



  public void doResponse(RequestResponseKey rrk, Object context)

                        throws ServletException, IOException {



        HttpServletRequest req = rrk.getRequest();

        HttpServletResponse res = rrk.getResponse();



         
                        
// Display fresh quotations

        displayStockQuotations(res);

  }



  public void doTimeout(RequestResponseKey rrk) throws ServletException,

                IOException {

        HttpServletRequest req = rrk.getRequest();

        HttpServletResponse res = rrk.getResponse();

  

         
                        
// Hung thread. Recover quotations from the cache

        displayStockQuotations(res);

  }

  

  private Hashtable<String,Long> readStocksValue() {  

        Hashtable<String,Long> hash = new Hashtable<String,Long>();

  

        hash.put("XOM", new Long(75));

        hash.put("GE", new Long(1005));

        hash.put("JPM", new Long(1008));

        dateLastUpdate = new Date();

  

        return hash;

  }

  

  private void displayStockQuotations(HttpServletResponse res) {

        PrintWriter pw = null;

        try {

           pw = res.getWriter();

        } catch (IOException e) {  

           e.printStackTrace();

        }

        pw.println("Quotations at :" +dateLastUpdate);

        Enumeration<Long> enumStocks = hashStocks.elements();

        while (enumStocks.hasMoreElements()) {

           pw.println(enumStocks.nextElement());

           pw.flush();

        }

        pw.close();

   }

}

                      

The main benefit of this approach is that we provide an answer without keeping the execute thread queue too busy. This will contribute to a more scalable application and improve the customer experience.

This approach has been kept intentionally simplistic; after all, the real purpose of this article is to illustrate a feature with a trivial example.

In a real stock system we could add a bit of complexity by customizing the answer based on the type of customer. For example, stock brokers or users who have subscribed a contract with our stock system might have longer timeouts, or no timeout at all. For all other users, it could be acceptable to deliver quotations that are some seconds stale.

Javascript Hacking

The advent of Ajax applications has deeply changed the style of Web applications. Applications built using Ajax produce richer and more dynamic Web sites, like Google Maps, MySpace, Gmail, and the Netflix site. The sites do a lot of work behind the scenes so they are less about users filling out one form after another, and more about the application automatically giving the user the information he or she needs.

Unfortunately, common Ajax best practices have not been developed, which leaves plenty of room to get things wrong.

The problem is that Web 2.0 sites are vulnerable in a way that Web 1.0 sites aren't: Every keystroke or mouse click can be transformed into an execute thread that is consumed. So, given the nature of Ajax applications, this could lead to a nasty mechanism that can exhaust WebLogic Server with many short-lived HTTP requests. No surprise that several pieces of malware already exploit this problem, with just a couple of lines of code. In the trenches of sys admins, they have even coined the term Javascript hacking for this kind of attack.

Pages: 1, 2, 3

Next Page ยป