Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing long polling in an asynchronous fashion

Is it possible to take an HTTPServletRequest away from its thread, dissolve this thread (i.e. bring it back to the pool), but keep the underlying connection with the browser working, until I get the results from a time-consuming operation (say, processing an image)? When the return data are processed, another method should be called asynchronously, and be given the request as well as the data as parameters.

Usually, long pooling functions in a pretty blocking fashion, where the current thread is not dissolved, which reduces the scalability of the server-side app, in terms of concurrent connections.

like image 711
user802232 Avatar asked Nov 10 '11 15:11

user802232


People also ask

Is long polling asynchronous?

There are three main types of asynchronous request and response sequences: push, poll, and long-poll.

How is long polling implemented?

The Client sends an HTTP request and then waits for a response. When an update is available, the server provides the Client a complete response. After getting a response, the Client typically sends a new long-poll request, either immediately or after a pause, to allow for an appropriate latency duration.

What is long polling and why would it be beneficial to use?

Long polling is the simplest way of having persistent connection with server, that doesn't use any specific protocol like WebSocket or Server Side Events. Being very easy to implement, it's also good enough in a lot of cases.

Is long polling synchronous?

This time let's learn the trick called “long-polling”. It helps in cheating on the API surface that our operations are synchronous.


2 Answers

Yes, you can do this with Servlet 3.0

Below is the sample to write the alert every 30 secs(not tested).

@WebServlet(async =“true”)
public class AsyncServlet extends HttpServlet {

Timer timer = new Timer("ClientNotifier");

public void doGet(HttpServletRequest req, HttpServletResponse res) {

    AsyncContext aCtx = request.startAsync(req, res);
    // Suspend request for 30 Secs
    timer.schedule(new TimerTask(aCtx) {

        public void run() {
            try{
                  //read unread alerts count
                 int unreadAlertCount = alertManager.getUnreadAlerts(username); 
                  // write unread alerts count
    response.write(unreadAlertCount); 
             }
             catch(Exception e){
                 aCtx.complete();
             }
        }
    }, 30000);
}
}

Below is the sample to write based on an event. The alertManager has to be implemented which notifies AlertNotificationHandler when client has to be alerted.

@WebServlet(async=“true”)
public class AsyncServlet extends HttpServlet {
 public void doGet(HttpServletRequest req, HttpServletResponse res) {
        final AsyncContext asyncCtx = request.startAsync(req, res);
        alertManager.register(new AlertNotificationHandler() {
                   public void onNewAlert() { // Notified on new alerts
                         try {
                               int unreadAlertCount =
                                      alertManager.getUnreadAlerts();
                               ServletResponse response = asyncCtx.getResponse();
                               writeResponse(response, unreadAlertCount);
                               // Write unread alerts count
                         } catch (Exception ex) {
                               asyncCtx.complete();
                               // Closes the response
                         }
                   }
        });
  }
}
like image 104
Ramesh PVK Avatar answered Nov 01 '22 02:11

Ramesh PVK


Yes, it's possible using Servlet spec ver. 3.0. Implementation I can recommend is Jetty server. See here.

like image 40
Victor Sorokin Avatar answered Nov 01 '22 01:11

Victor Sorokin