users@glassfish.java.net

Re: How to check if the client dropped the connection

From: aaime74 <andrea.aime_at_gmail.com>
Date: Mon, 28 Sep 2009 11:31:28 -0700 (PDT)

Jeanfrancois Arcand-2 wrote:
>
> Salut,
>
> aaime74 wrote:
>> Hi,
>> I'm working on the development of an open source application, GeoServer,
>> implementing the Web Map Service specification.
>> The specification allows a client to request maps using simple GET
>> requests like:
>>
>> http://sigma.openplans.org:8080/geoserver/wms?WIDTH=431&SRS=EPSG%3A4326&LAYERS=tiger-n
>> \
>> y&HEIGHT=550&STYLES=&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEP
>> \
>> TIONS=application%2Fvnd.ogc.se_inimage&BBOX=-74.01697805908182,40.69808217724622,-73.9
>> \
>> 9567744140603,40.72526393994153
>>
>> and the client gets back a PNG with a map of the request area.
>> No asynchronism is allowed, the protocol is standardized
>> (http://portal.opengeospatial.org/files/?artifact_id=1058) and I have no
>> controls over the clients (there are tens of them around, both open
>> source
>> and proprietary) which are free to make as many request as they like, in
>> whatever order the like.
>>
>> By spec we're forced to use a plain request and response approach, but
>> we're experiencing a problem with clients making lots of request as the
>> user zooms/pans around: basically a request is made, but the user keeps
>> on moving, the client drops the older requests (closing the connection in
>> face of
>> the server) and makes others.
>> Unfortunately in the meantime the older requests are still running,
>> drawing
>> a map takes
>> time and a lot of memory, for example the above request, which is a
>> small one btw, allocates a BufferedImage of 700KB. The memory is
>> consumed up until the image is encoded out to the stream, which is also
>> the moment we finally figure out the client dropped the connection
>> (since writing to the servlet output stream fails).
>>
>> This is very sub-optimal. Servers like Apache, with cgi, do kill the cgi
>> process the moment the connection is dropped, significantly reducing the
>> server load both in terms of CPU and memory consumption.
>>
>> Is there any way to check if the client connection is still open using
>> only the standard servlet API?
>
> No, by default if you want to behavior you will need to implement
> something like:
>
> + spawn Thread(s)
> + Block on HttpServletRequest.getInputStream().read()
>
> The issue is you will ends up with one thread per connection blocked on
> the read().

Hum, I actually already tried something similar to that, just a little
differently.
Instead of spawning a processing thread, I spawned a connection checking
thread,
something like:

            connectionChecker = new Thread(new Runnable() {
                
                public void run() {
                    try {
                        while(true) {
                                int val =
httpRequest.getInputStream().read();
                                logger.severe("" + val);
                                Thread.sleep(50);
                        }
                    } catch(InterruptedException e) {
                        // the thread was interrupted because we served out
the response fully
                    } catch(Exception e) {
                        // thre thread was interruped because of something
else
                    }
                }
            });
            connectionChecker.start();

But in the end the code never blocked, read keeps on returning -1 (tried
both
in Jetty and Glassfish, same result). Is there any server configuration I
should
be trying out?


>
>> If not, is there any Glassfish specific approach that might work instead?
>
> You can uses the Grizzly Comet Framework for doing that (it's old link
> but it describe what it does)
>
> * http://is.gd/3KWKd
>
> I can feed you with more detailed examples, but as a starter, all you
> will need to do is to create a CometHandler
>
> * http://is.gd/3KX1k
>
> and register it for asynchronous events. When the remote client will
> close the connection. the CometHandler.onInterrupt() will be invoked,
> telling you the remote connection has been closed.
>
> If you need a solution that works on all Web Server, take a look at:
>
> * http://atmosphere.dev.java.net
>
> which also support the detection via AtmosphereHandler.

I will surely try this out, thanks a lot. Wondering if this could be
affected
by non blocking I/O the same way the simple approach above is?
Anyway, I will try this approach and let you know how it works.

> Hope that help.


It sure does :)

Cheers
Andrea
-- 
View this message in context: http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25649585p25650530.html
Sent from the java.net - glassfish users mailing list archive at Nabble.com.