0

Building zk front end to handle multiple simultaneous long running data queries?

asked 2011-10-31 18:42:05 +0800

davout gravatar image davout
1435 3 18

I have design problem that I'm looking to solve with ZK.

There is a requirement to build a web app to support a portal style multi window display where each window is displays two panes: a query statement in the top pane, and the query results in a grid in the second pane. The queries are being sent to an underlying custom analytics engine. Each query window need to be modeless - think MDI. The data queries to the underlying custom analytics engine can be very long running - 2 minutes plus sometimes to return results.

To address this I want to provide the user with a MDI style interface where they can:
* Open a new query window
* Type in the query string and select 'go'. Under the hood the code will fire off the query to the remote custom analytics engine
* Open a second query window
* In the second query window type in a new query and select 'go'
* Repeat this for a third window and so on.
* Once a query window has received its results, the user is free to change the query statement and fire off a second different query.

Behind the scenes something has to receive a notification that a query has completed and that the related window grid needs to be updated with the results. There is no indication of when a query will be completed by the underlying custome analytics engine. If my app fires off queries from windows A, B C and D; the results could return in any order.

Any suggestions for how to deliver this in ZK?

delete flag offensive retag edit

28 Replies

Sort by ยป oldest newest

answered 2011-11-05 08:53:19 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

You have a good point there. The ZK-provided server push implementations are not very good.
PollingServerPush: High latency, high cpu load on server because all users are constantly polling the server
CometServerPush: Low latency, low CPU load on server, but comet threads are not asynchronous and will eat up the server thread pool if there are plenty of users

I've blogged shortly about these shortcomings here.

Ok, so why don't I recommend iframes then?

From the server side point of view, iframes have similar problems as CometServerPush has. You'll end up running background job in the servlet threads, which means that they will eat up the server thread pool. It's slightly more efficient with small amount of windows because there are only zkau threads (but some of those are blocked ones).

From the client side point of view, iframes have some disadvantages:
- CSS styling bugs (probably just IE). MDI style interface was a requirement so windows might be stacked on top of another. I'm not sure if ZK works around these styling bugs but if it doesn't, you'll end up with problems.
- I'm not 100% sure but I think that browser max connections limits are usually per host. For example in older IE versions the limit is 2 connections. That means that you cannot have more than 2 long running queries at the same time. Opening 3 windows and running a query in each of them would not work.

Summary:
Either way you are screwed on the server side. I think that CometServerPush is the best solution here because there is only one blocking thread per desktop. Running 100 queries simultaneously in one browser window would block only 1 server thread (it would of course block 100 background threads but that is unavoidable). Running 100 queries with the iframe solution would block 100 server threads (but no background threads).

The technically correct solution is to make the server push asynchronous, but ZK does not provide such functionality out of the box. In case you are interested, I'm working on a prototype implementation that can be found here.

CometServerPush:
1 blocking comet thread per desktop
non-blocking zkau threads
1 blocking background thread per query

Iframes:
1 blocking zkau thread per query
non-blocking zkau threads

(AsynchronousServerPush):
1 non-blocking comet thread per desktop
non-blocking zkau threads
1 blocking background thread per query

link publish delete flag offensive edit

answered 2011-11-05 13:13:35 +0800

davout gravatar image davout
1435 3 18

Any chance of publishing an article on this for us ZK users?

link publish delete flag offensive edit

answered 2011-11-05 20:09:59 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

Im very interested of reading more of this too.
Thanks for the explanation Joonas.

thanks
Stephan

link publish delete flag offensive edit

answered 2011-11-08 15:12:45 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

I started writing a series of blog posts about this. I'll let you guys know once I've published them :)

There's also a working sample app at https://github.com/Gekkio/zk-async-example

link publish delete flag offensive edit

answered 2011-11-09 09:32:08 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

Many thanks for that Joonas.

I have time to checkout on weekend.

thanks
Stephan

PS: I found an interesting article that discribes the blocking problem: http://www.theserverside.com/news/1363576/What-is-the-Asynchronous-Web-and-How-is-it-Revolutionary

link publish delete flag offensive edit

answered 2011-11-09 13:55:57 +0800

caclark gravatar image caclark
1753 2 5
http://clarktrips.intltwi...

updated 2011-11-09 13:58:31 +0800

I know that I've joined this discussion late, but I have a question.
First, gekkio, you've done a nice piece of work.
Second, I'm wondering if you or someone else can compare and contrast it to an implementation that uses only the ZK event mechanism. If your WindowComposer had these methods:

    public void onClick$runButton() {
        // Let's disable the button so the user cannot start another task while a previous one is processing
        runButton.setDisabled(true);
        runButton.setLabel("Running...");

        Events.echoEvent( "onProcessRequest", self, null ) ;
        Clients.showBusy( "Processing...", self ) ;  // optional if you want to occupy UI while task is running
    }

    /**
    * This event listener method will be called to perform the long running work
    *
    * @param event
    */
    public void onProcessRequest(Event event) {
        List<Integer> results = null ;

        //  do whatever the long running task is...
        results = doWhatever() ;

        // Re-enable the button
        runButton.setDisabled(false);
        runButton.setLabel("Run task");

        // Let's visualize results in the grid
        results.setModel(new ListModelList(results));

        Clients.clearBusy( self ) ;  // optional if you want to occupy UI while task is running
    }

What are the ramifications of this approach compared to your AsyncTask + ThreadPool approach?

link publish delete flag offensive edit

answered 2011-11-10 05:14:40 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

Cary, that's a good question.
The most obvious ramification is that doing long running work in servlet threads blocks all other event processing in the same desktop (= browser window). This happens because ZK serializes client-to-server requests (when I say "serializes", I don't mean java.io.Serializable, I mean that requests are processed serially, never in parallel). So basically this is what happens:

1. Client->Server: runButton.onClick is sent
2. Server->Client: server response commands client to do runButton modifications (label=Running..., disabled=true) and echo back with onProcessRequest
3. Client->Server: onProcessRequest is sent
4. long running process while server handles onProcessRequest. During this time no other Client->Server requests can happen (e.g no onClicks of other buttons)
5. Server->Client: server response commands client to show results and re-enable runButton
6. (Client->Server): Any server-side events you have caused in the browser window (button clicks, etc) during the long running process are sent at this point.

So, to elaborate further, using echoEvent and processing directly in the servlet thread is not ok for a MDI-style interface where you have multiple windows doing long running tasks. You'd be able to only open one window and it would effectively block the whole UI while processing.

I've done some updates to the example project. There's now an alert button that can be used to test when new server-side events are processed. I also refactored the code a bit so it can be modified more easily to test other solutions.

You can now test your solution yourself with these modifications to WindowComposer:

    public void onClick$runButton() {
        visualizeProcessingStart();
        Events.echoEvent("onProcessRequest", self, null);
    }

    public void onProcessRequest() {
        List<Integer> resultData = ExampleTask.generateNumbers(amount.intValue());
        visualizeProcessingEnd(resultData);
    }

You can see the effect I described earlier by doing those modifications, starting one process and clicking the alert button. You'll see that the button is unresponsive and the alert pops up only when the processing is finished.

link publish delete flag offensive edit

answered 2011-11-10 05:24:22 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

Thanks Stephan, that's a good article!

By using the terminology from the article, the server push implementations can be classified like this:

PollingServerPush: HTTP Polling, normal servlets
CometServerPush: HTTP Long Polling, normal servlets
AtmosphereServerPush: HTTP Long Polling, asynchronous servlets

(AtmosphereServerPush is my implementation that uses the Atmosphere framework for truly asynchronous processing)

link publish delete flag offensive edit

answered 2011-11-10 06:13:23 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

A quick update on the example project:

In the async branch there's now a version of the project with AtmosphereServerPush.
You can now easily test and see the major difference between CometServerPush vs AtmosphereServerPush (thread starvation).
1. Uncomment the relevant section in pom.xml (= limits Jetty to 3 threads)
2. Run the project
3. Open more than one browser window/tab and start processing in them
See the project README for instructions.

CometServerPush quickly eats the 3 threads and you'll see that the UI becomes completely unresponsive. AtmosphereServerPush does not care and will work even if you open 100 browser windows.

Once I finish my blog posts, I'll explain this better :)

link publish delete flag offensive edit

answered 2011-11-10 06:58:38 +0800

davout gravatar image davout
1435 3 18

I think there is real business value for ZK in having some tangible examples of the different server push options made available in the framework and in the demo apps.

With the recently announced death of Flash and similar technologies like Silverlight not long for this world, I suspect that any GUI framework that can show that it has the async server push area covered is going to have a huge advantage.

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2011-10-31 18:42:05 +0800

Seen: 1,261 times

Last updated: Jan 28 '12

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More