Re: How to check if the client dropped the connection
aaime74 wrote: ... Hi. Kind of restarting from the beginning, I think that the first question to ask is whether whatever method which actually does the rendering of the maps, and which is heavy in terms of resources, is capable of being interrupted cleanly in the middle. Is it capable itself of checking regularly if it should continue doing the work ? Or else, if you shoot it down does it mop up after itself, or does it leave stuff to clean up all over the place ? From an overall design point of view, it seem to me that you have two very different types of processes going on : the first type is the management of the HTTP requests, connections, protocol, etc.., which is something that should be efficient, light-weight and quick, should detect (whenever possible) that the client has broken the connection and so on. That part should also serve the response to the client, when the full response is ready as a static object on disk e.g. The second part is the generation of that content, which by it's nature is slow and heavy, but has a very simple interface (create this content; stop right now; ..). Personally, I would tend to try to separate the two parts, and create a separate process to handle the content generation, a bit like a database back-end. It seems to me that it would then be easier to wrap this process in a simple management wrapper which can interrupt the content generation when receiving some signal from the first part, and cleanup properly, without tying up resources useful to the HTTP part in the meantime. Such a separation may also simplify aspects such as caching of previously generated content, or load-balancing several content generators. Maybe you should have a look at Apache MINA for the content-generation side ? (http://mina.apache.org/) The (whenever possible) above refers to the fact that a number of things outside of your control can come in the way of such detection : proxies, firewalls and the like. If the ultimate client breaks the connection, it is not guaranteed that Tomcat itself would notice this right away. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
awarnier wrote: aaime74 wrote: ... Hi. Kind of restarting from the beginning, I think that the first question to ask is whether whatever method which actually does the rendering of the maps, and which is heavy in terms of resources, is capable of being interrupted cleanly in the middle. Is it capable itself of checking regularly if it should continue doing the work ? Or else, if you shoot it down does it mop up after itself, or does it leave stuff to clean up all over the place ? I can cleanly stop the rendering process in almost any point of it. The issue is not stopping it, it's detecting the client connection was dropped. No matter what solution is adopted, one still depends on the ability to detect the client has dropped the connection, something that no one so far described how to check (I'm starting to wonder if there is a way at all). awarnier wrote: The (whenever possible) above refers to the fact that a number of things outside of your control can come in the way of such detection : proxies, firewalls and the like. If the ultimate client breaks the connection, it is not guaranteed that Tomcat itself would notice this right away. Ok, but let's say Tomcat is capable of that. How does one check from within the servlet that the connection has been dropped without writing out anything? What I've tried so far is trying to block on the input stream provided by the Http request and hoping it would throw an exception if the client drop the conntection, but that does not work, the input stream just return -1 to any read operation no matter if the client is still connected or not. Cheers Andrea -- View this message in context: http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25658980.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
Markus Meyer wrote: I'm not saying you should store the whole map all at once. My approach was to dynamically cache requests that the client may want to make in advance. An easy example would be if a client makes a request for the city center, you create the map for the city center plus the suburbs around it and store it somewhere, then return the city center. If the user then moves around a bit to see the suburbs, you already have the whole map cached and just need to return it, no need to do any further calculation. Sorry, I've lost you there. How is drawing a bigger image going to solve the problem, which in the end is both a CPU waste but also an OOM due to too many images being generated at the same time because of the user zooming in and out fast (most of them are actually not wanted anymore by the client which in the meantime will drop the connection). If anything your suggestion seems to make the client wait longer and the server OOM faster. Markus Meyer wrote: If you then also compress the image on the fly while you are reading it from disk (or from some memory cache), you will start writing to the output stream very soon (also detecting the dropped connection very soon) and the servlet will not need much RAM. Of course this does not work if you just use Java's built-in PNG encoder. Obviously, caching always comes with the price that you will have the occassional cache miss :-) That is, this does not work for every request but may decrease load and RAM usage a lot for typical use cases. WMS and tile systems are related, but they don't work the same way, I cited tiling because it's the thing people know the most given the Google maps popularity. A desktop WMS client won't use any pre-defined tile structure, each request will be different in terms of layer requested, zoom level, and area. The potential for caching is very, very low. The tile system are on the other side setup to make caching possible and efficient by imposing structure on the requests, but what I'm dealing with here is pure WMS. What I'm talking about here are the industry standard solutions for WMS map rendering. We can discuss this at lenght and we could come out with some interesting new way that was not tried before in the field. But in the meatime I would really appreciate if anybody could answer my first question: how does one detect the client connection has been dropped? Is there any way? Does anybody know? Markus Meyer wrote: In your OP you write: 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. This indicates that you (1) seem to not use any caching (drawing a map takes time - with caching the map would already have been drawn) and (2) you use BufferedImage which of course does not allow you to PNG-encode on the fly. Both problems would be solved with the above suggestion. The rendering subsystem actually takes a Graphics2D. If you can suggest ways to draw lines, points and polygons on a raster image that is not memory bound (like a buffered image) and has no sewing effects (like tiles, that do break labelling, long story, don't get me started on this) I'm all ears. Cheers Andrea -- View this message in context: http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25659184.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
On 29/09/2009 09:15, André Warnier wrote: aaime74 wrote: ... Hi. Kind of restarting from the beginning, I think that the first question to ask is whether whatever method which actually does the rendering of the maps, and which is heavy in terms of resources, is capable of being interrupted cleanly in the middle. Is it capable itself of checking regularly if it should continue doing the work ? Or else, if you shoot it down does it mop up after itself, or does it leave stuff to clean up all over the place ? From an overall design point of view, it seem to me that you have two very different types of processes going on : the first type is the management of the HTTP requests, connections, protocol, etc.., which is something that should be efficient, light-weight and quick, should detect (whenever possible) that the client has broken the connection and so on. That part should also serve the response to the client, when the full response is ready as a static object on disk e.g. Andre's approach is correct IMHO, it's a caching problem: decouple the generation bit from the delivery bit and ensure that the data you need to serve is always available at short notice, so the consequences of an interruption aren't so big. The second part is the generation of that content, which by it's nature is slow and heavy, but has a very simple interface (create this content; stop right now; ..). Consider pre-fetching the next possible grid squares into the cache - you may also consider tuning your caching algorithm to determine the rate direction of travel (of a given client) across the map, so you can avoid pre-fetching unnecessary units. I'd be thinking of a queue of requests and a multi-threaded (multi-server?) pool to service it. Slightly more leftfield: if you're effectively serving static images off a disk, you could consider directing (via a forward) requests straight to a public image directory and use APR/sendfile to serve them statically - which would be very fast, delivery-wise, and would eliminate the need for you to handle interruptions in your own code. (I think.) Lastly, if it's a heavy-weight process then at some point, when demand rises, you'll need a server(s) with lots of power and probably a big chunk of RAM. Don't try and design around this. p Personally, I would tend to try to separate the two parts, and create a separate process to handle the content generation, a bit like a database back-end. It seems to me that it would then be easier to wrap this process in a simple management wrapper which can interrupt the content generation when receiving some signal from the first part, and cleanup properly, without tying up resources useful to the HTTP part in the meantime. Such a separation may also simplify aspects such as caching of previously generated content, or load-balancing several content generators. Maybe you should have a look at Apache MINA for the content-generation side ? (http://mina.apache.org/) The (whenever possible) above refers to the fact that a number of things outside of your control can come in the way of such detection : proxies, firewalls and the like. If the ultimate client breaks the connection, it is not guaranteed that Tomcat itself would notice this right away. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
On 29/09/2009 09:34, aaime74 wrote: awarnier wrote: aaime74 wrote: ... Hi. Kind of restarting from the beginning, I think that the first question to ask is whether whatever method which actually does the rendering of the maps, and which is heavy in terms of resources, is capable of being interrupted cleanly in the middle. Is it capable itself of checking regularly if it should continue doing the work ? Or else, if you shoot it down does it mop up after itself, or does it leave stuff to clean up all over the place ? I can cleanly stop the rendering process in almost any point of it. The issue is not stopping it, it's detecting the client connection was dropped. No matter what solution is adopted, one still depends on the ability to detect the client has dropped the connection, something that no one so far described how to check (I'm starting to wonder if there is a way at all). awarnier wrote: The (whenever possible) above refers to the fact that a number of things outside of your control can come in the way of such detection : proxies, firewalls and the like. If the ultimate client breaks the connection, it is not guaranteed that Tomcat itself would notice this right away. Ok, but let's say Tomcat is capable of that. How does one check from within the servlet that the connection has been dropped without writing out anything? What I've tried so far is trying to block on the input stream provided by the Http request and hoping it would throw an exception if the client drop the conntection, but that does not work, the input stream just return -1 to any read operation no matter if the client is still connected or not. If you've processed request parameters, the inputstream is empty because it's already been consumed. As previously stated, you'd have to try and write something (a header?) to the outputstream to find out if it's available or not. hres.addHeader(X-Streamcheck-01, OK!); ... do some work ... hres.addHeader(X-Streamcheck-02, OK!); p Cheers Andrea - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
On 29/09/2009 09:47, aaime74 wrote: Markus Meyer wrote: I'm not saying you should store the whole map all at once. My approach was to dynamically cache requests that the client may want to make in advance. An easy example would be if a client makes a request for the city center, you create the map for the city center plus the suburbs around it and store it somewhere, then return the city center. If the user then moves around a bit to see the suburbs, you already have the whole map cached and just need to return it, no need to do any further calculation. Sorry, I've lost you there. How is drawing a bigger image going to solve the problem, which in the end is both a CPU waste but also an OOM due to too many images being generated at the same time because of the user zooming in and out fast (most of them are actually not wanted anymore by the client which in the meantime will drop the connection). ... because for future requests, the data already exists and the work is already done. The consequences of a dropped connection are therefore reduced because you're not doing the work for every single request, and any work you are doing isn't completely wasted. Take for example the situation where a user zooms in one direction, changes their mind goes back (say to check a point of origin), then *again* reverses direction to proceed as before. If you've cached the responses to the first motion then you don't need to do the work again when the third motion occurs - and the work done the first time isn't wasted. Queuing the requests for generating images would allow you to limit how much work was being done and reduce the chances of an OOM. It might simply be that you can't achieve what you want without lots of RAM and more processing power than you currently have. You may find that you must either queue the generator requests to manage the load on the server - at the price of making clients wait for data, or you that you must add more processing power RAM. (It sounds like your current setup can't cope with a single users' peak load.) Caching stuff mitigates some of the problems you have but it won't solve the overall problem (which is not that connections are dropped - it's that the work done is both wasted and too much for the server to handle). p If anything your suggestion seems to make the client wait longer and the server OOM faster. Markus Meyer wrote: If you then also compress the image on the fly while you are reading it from disk (or from some memory cache), you will start writing to the output stream very soon (also detecting the dropped connection very soon) and the servlet will not need much RAM. Of course this does not work if you just use Java's built-in PNG encoder. Obviously, caching always comes with the price that you will have the occassional cache miss :-) That is, this does not work for every request but may decrease load and RAM usage a lot for typical use cases. WMS and tile systems are related, but they don't work the same way, I cited tiling because it's the thing people know the most given the Google maps popularity. A desktop WMS client won't use any pre-defined tile structure, each request will be different in terms of layer requested, zoom level, and area. The potential for caching is very, very low. The tile system are on the other side setup to make caching possible and efficient by imposing structure on the requests, but what I'm dealing with here is pure WMS. What I'm talking about here are the industry standard solutions for WMS map rendering. We can discuss this at lenght and we could come out with some interesting new way that was not tried before in the field. But in the meatime I would really appreciate if anybody could answer my first question: how does one detect the client connection has been dropped? Is there any way? Does anybody know? Markus Meyer wrote: In your OP you write: 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. This indicates that you (1) seem to not use any caching (drawing a map takes time - with caching the map would already have been drawn) and (2) you use BufferedImage which of course does not allow you to PNG-encode on the fly. Both problems would be solved with the above suggestion. The rendering subsystem actually takes a Graphics2D. If you can suggest ways to draw lines, points and polygons on a raster image that is not memory bound (like a buffered image) and has no sewing effects (like tiles, that do break labelling, long story, don't get me started on this) I'm all ears. Cheers Andrea - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
2009/9/29 aaime74 andrea.a...@gmail.com But in the meatime I would really appreciate if anybody could answer my first question: how does one detect the client connection has been dropped? Is there any way? Does anybody know? First off, I assume you're serving these straight out of Tomcat to the client - there's no proxying or Apache httpd to complicate things. I think you already said that, but this thread's gone down so many twists that I've mislaid the information - my apologies. I don't believe that Tomcat provides any such detection mechanism out of the box. It certainly doesn't provide any termination mechanism - terminating a CGI script is easy as you know the code's held inside a nice neat bundle of a process, but aborting a Thread in Tomcat could leave a horrible legacy behind as it's all in the same address space. However, I think detection would be relatively simple to add. First off, let's assume that the OS's stack and Java's socket implementation work well enough together that isClosed() and isOutputConnected() on the socket actually give you meaningful information. If that's the case, all you need to do is to be able to get direct hold of the Socket that's writing the bytes and call appropriate methods on that. I would assume there's no way of doing this through the API, as it completely breaks layering. At this point, I'd be cracking open the Tomcat source and hacking in The Simplest Change That Could Possibly Work, just to see whether it does! In my case, that would involve some disgusting non-production hackery like putting a reference to the Socket onto thread-local storage once you know which thread will be handling the request, and making absolutely sure I took it out again as the request returned. Absolutely not what you want to do in a production system, but useful for a proof of concept. It's then possible to ask the Socket about its state directly in various places in the rendering pipeline, and abort the render if it's no longer required. I'd then do further work to refactor this so that there's some more appropriate (but Tomcat-specific) API, rather than the hackery described above. This does mean that you'd end up with a custom Tomcat, and hence your own code to maintain through upgrades. I suspect it's sufficiently isolated that such maintenance wouldn't be too big a problem, but you'd definitely be compiling from source. That's not a huge undertaking - I've done it on a couple of past projects. Happy to chat further if this looks like a useful approach. If you don't want to code it yourself, I suspect there are several people on-list with the skills and experience to construct such an addition. - Peter
Re: How to check if the client dropped the connection
2009/9/29 Pid p...@pidster.com ... because for future requests, the data already exists and the work is already done. The consequences of a dropped connection are therefore reduced because you're not doing the work for every single request, and any work you are doing isn't completely wasted. Pid, you're assuming some features of the application that may not be true, namely that a sufficiently high proportion of the images are re-used for this work to be useful. If the cache hit rate is low, that assumption may well be false. You're also assuming that the resulting artifact is sufficiently lightweight that it is appropriate to cache. That, in turn, depends on the relative cost of generating the image vs storing it. On modern machines with very fast processors, modest amounts of memory and dreadful bandwidth to disk*, I'd not be willing to take either side of that bet without examining the application's resource profile in considerable detail. - Peter * Amdahl's Rule of Thumb: A machine should be able to clear its memory in one second and write it to disk in 10 seconds. For a general-purpose server, I think the rule still holds.
Re: How to check if the client dropped the connection
aaime74 wrote: ... Ok, but let's say Tomcat is capable of that. How does one check from within the servlet that the connection has been dropped without writing out anything? I have been looking (starting at the HttpServletResponse object), trying to follow the trail to see if one at some point can get hold of some Connection object which would have some isConnected property. No luck so far, but I am really not a java expert. What I've tried so far is trying to block on the input stream provided by the Http request and hoping it would throw an exception if the client drop the conntection, but that does not work, the input stream just return -1 to any read operation no matter if the client is still connected or not. Yes, but that is because each TCP connection really consists of two separate parts or sides. For each actor (server and client), there is one part that is the incoming connection, and another separate part that is the outgoing connection (the sides being crossed-over in the middle for the server and the client). Each actor can close its own incoming or outgoing connection, independently, without warning to the other part. (E.g., suppose it just crashes). When that happens, the other side of that connection is left dangling : basically, it does not known that the other side is gone, until it tries to send something on that connection, and the TCP stack (deep down in the bowels of the underlying OS) returns an error, which then filters back up all the way to your java OutputStream object. In your case, what matters to you is the response output stream, not the input stream, which could have been (validly) closed by the client already, if it has no further use for it. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Andrea, On 9/29/2009 4:34 AM, aaime74 wrote: I can cleanly stop the rendering process in almost any point of it. The issue is not stopping it, it's detecting the client connection was dropped. No matter what solution is adopted, one still depends on the ability to detect the client has dropped the connection, something that no one so far described how to check (I'm starting to wonder if there is a way at all). I would do something like this, adopting Jason's strategy: private static final byte[] NOTHING = new byte[0]; public void doGet(...) { // or whatever OutputStream out = response.getOutputStream(); // look into java.util.concurrent.Executor and friends if // you've never seen them... great stuff MapDrawingTask /* implements Callable */ task = new MapDrawingTask(); FutureVoid task = executor.submit(task); while(!task.isDone() !task.isCancelled()) { try { Thread.currentThread().sleep(100); // or whatever timeout you want } catch (InterruptedException ie) { // Ignore } try { out.write(NOTHING); out.flush(); } catch (ClientAbortException cae) { task.cancel(true); // allow interruptions // the break isn't strictly necessary break; // or even return if you want to get out quick } } if(!task.isCancelled()) { // dump output to response } } You may want to catch more exceptions than just ClientAbortException there, you might need more error handling in general, and my quick-and-dirty thread-and-task management will probably need some improvement and cleanup, but you get the general idea: the HTTP thread blocks waiting for either the map-drawing task to complete, or for the client to hang up the phone. Hope that helps, - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkrCJxUACgkQ9CaO5/Lv0PDnqwCgn/WyPTUGwn6yHihzeak+HACW aOUAnR/EogE5wbVVKJUd8/aFLqXPVbYK =jXyD -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Markus, On 9/28/2009 6:03 PM, Markus Meyer wrote: Martin Gainty schrieb: could you explain just a bit more what is a tile? If you have a very large image, say 1 million x 1 million pixels or something like that, it is more efficient to split the image into tiles, that is small images of, say, 256 x 256 pixels. If a certain portion of the big image is requested, you can then load these tiles individually from disk and put them together to form the portion of the image that was requested. Oddly enough, this is much more efficient to do on the client side if, say, javascript is available. Google appears to do this with their maps: if you pan around your home on maps.google.com, you can see the individual tiles loading and being rendered on the screen to create a larger image. If you pan off the screen no loading has to occur until you cross one of the tile boundaries that has already been sent. It's like looking through a small window at a large painting: you are only seeing a small portion of the painting (the sum total of all previously-fetched tiles) because of the size of the window (the view port on the screen). The OP seems to be using tiles on the backend for convenience, but then using complex server-side methods to assemble the /exact/ image that the client requested. That requires things like image decoding followed by lots of memory allocation, and then a heavy re-compression before streaming the result back to the client. If the client has some measure of power, the server can take advantage of that by converting all complex requests into individual, simple requests. A request for a single 1000x1000 image could be converted into 16 requests for 256x256 static tile images, then re-assembled on the client. No image manipulation occurs on the server, which is a /huge/ win for your service. Unfortunately, it requires something like javascript to be present on the client. If your service cannot tolerate such a requirement, then you need to make arrangements for those clients who /don't/ have javascript available. - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkrCKdcACgkQ9CaO5/Lv0PCh3QCeIWWVAQ7+ynyC9IaxfAQJ6bb5 hzcAnAqgYsWDPbKki8Yjsn/Tiuvh4T+a =BzDn -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
How to check if the client dropped the connection
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=431SRS=EPSG%3A4326LAYERS=tiger-nyHEIGHT=550STYLES=FORMAT=image%2FpngSERVICE=WMSVERSION=1.1.1REQUEST=GetMapEXCEPTIONS=application%2Fvnd.ogc.se_inimageBBOX=-74.01697805908182,40.69808217724622,-73.99567744140603,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? If not, is there any Tomcat specific approach that might work instead? If there is no solution that can be applied at the general servlet api level, do you know of any Tomcat specific approach one could use? e.g., casting the HttpServletResponse to some Tomcat specific class and get some connection information status there? Cheers Andrea -- View this message in context: http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25641481.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
Hi Andrea. When the client disconnects, and your servlet tries to write to the output stream, Tomcat will throw a ClientAbortException (you may have already seen this): http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/connector/ClientAbortException.html Tomcat appears to only throw this exception when you either write some bytes to the output stream or when you flush the output stream, and the client already closed its end of the connection. It appears that you could periodically try flushing the output stream and see if doing so throws this exception. You can flush after writing any number of bytes, including zero bytes. The first time you call flush, it will send the HTTP response headers to the client, so you would need to first set the headers before flushing. That sounds difficult for you to do because you're writing an image, and one of the headers would be Content-Length, which you probably don't know until your image is generated. -- Jason Brittain On Mon, Sep 28, 2009 at 12:21 AM, aaime74 andrea.a...@gmail.com 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=431SRS=EPSG%3A4326LAYERS=tiger-nyHEIGHT=550STYLES=FORMAT=image%2FpngSERVICE=WMSVERSION=1.1.1REQUEST=GetMapEXCEPTIONS=application%2Fvnd.ogc.se_inimageBBOX=-74.01697805908182,40.69808217724622,-73.99567744140603,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? If not, is there any Tomcat specific approach that might work instead? If there is no solution that can be applied at the general servlet api level, do you know of any Tomcat specific approach one could use? e.g., casting the HttpServletResponse to some Tomcat specific class and get some connection information status there? Cheers Andrea -- View this message in context: http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25641481.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org -- Jason Brittain
Re: How to check if the client dropped the connection
Jason Brittain schrieb: The first time you call flush, it will send the HTTP response headers to the client, so you would need to first set the headers before flushing. That sounds difficult for you to do because you're writing an image, and one of the headers would be Content-Length, which you probably don't know until your image is generated. Actually, Content-Length is optional as per the HTTP-1.1 spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html However, my take on the OP is that a better optimization strategy in this case would be to just cache a larger image on the server rather than generating every image on-demand. That is, when the user is moving around in the image, the server, on the first request, would calculate the image for a much larger portion of the map than requested and stores it on disk in temporary storage (or in some cache area in RAM, if feasible, after all RAM is cheap these days and 64-bit machines can have lots of RAM). Storage of the images would not be done all at once but in tiles. When then user then moves around in the client, the requests just reads the tiles of the created image from disk, puts them together and clips the borders, then compresses the image and sends it to the client. It is possible that PNG even has some support for compressing parts of an image so the tiles itself could be already stored in compressed format, but it's been a while since I read the PNG spec last time. The same could be done for zooming by storing images in a pyramidal structure, like it is done in pattern recognition. While the user is moving, a background thread associated with the client could try to anticipate where the user is likely to be moving to and calculate the given tiles in advance. Actually, this sounds like an interesting project for several Ph.D. theses... Markus - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
jasonb wrote: Hi Andrea. When the client disconnects, and your servlet tries to write to the output stream, Tomcat will throw a ClientAbortException (you may have already seen this): http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/connector/ClientAbortException.html Tomcat appears to only throw this exception when you either write some bytes to the output stream or when you flush the output stream, and the client already closed its end of the connection. It appears that you could periodically try flushing the output stream and see if doing so throws this exception. You can flush after writing any number of bytes, including zero bytes. The first time you call flush, it will send the HTTP response headers to the client, so you would need to first set the headers before flushing. That sounds difficult for you to do because you're writing an image, and one of the headers would be Content-Length, which you probably don't know until your image is generated. We actually don't send the content length out, we used chunked transfer instead (that is, stream out the result of the png compression as made by JAI Image I/O) but unfortunately we cannot do that either, as the protocols mandates that any error occurring during rendering be returned as XML. So I actually know the final content type only when the image is fully rendered, which is when I start writing out bytes anyways. Cheers Andrea -- View this message in context: http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25651470.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
Markus Meyer wrote: Jason Brittain schrieb: The first time you call flush, it will send the HTTP response headers to the client, so you would need to first set the headers before flushing. That sounds difficult for you to do because you're writing an image, and one of the headers would be Content-Length, which you probably don't know until your image is generated. Actually, Content-Length is optional as per the HTTP-1.1 spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html However, my take on the OP is that a better optimization strategy in this case would be to just cache a larger image on the server rather than generating every image on-demand. That is, when the user is moving around in the image, the server, on the first request, would calculate the image for a much larger portion of the map than requested and stores it on disk in temporary storage (or in some cache area in RAM, if feasible, after all RAM is cheap these days and 64-bit machines can have lots of RAM). Storage of the images would not be done all at once but in tiles. When then user then moves around in the client, the requests just reads the tiles of the created image from disk, puts them together and clips the borders, then compresses the image and sends it to the client. It is possible that PNG even has some support for compressing parts of an image so the tiles itself could be already stored in compressed format, but it's been a while since I read the PNG spec last time. The same could be done for zooming by storing images in a pyramidal structure, like it is done in pattern recognition. While the user is moving, a background thread associated with the client could try to anticipate where the user is likely to be moving to and calculate the given tiles in advance. Actually, this sounds like an interesting project for several Ph.D. theses... Well, something like that has actually been done already, it's called tile caching, and works under the restrictive conditions that you can force the client to make requests in predetermined sizes and tiles. As for applying this to the general case, I invite you to have a look at how big the raster surface is and how much space is required to actually store on the disk a full map (only _one_ map, some GeoServer installs do serve 500-1000 different layers) here: http://geowebcache.org/trac/wiki/resources (the site is describing the tile cache companion to GeoServer, called GeoWebCache) So, it is somewhat doable, but only for a few backgrond layers that do not change that often (once a month may be ok if you don't need to zoom in too much). Cheers Andrea -- View this message in context: http://www.nabble.com/How-to-check-if-the-client-dropped-the-connection-tp25641481p25651562.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
aaime74 schrieb: Well, something like that has actually been done already, it's called tile caching, and works under the restrictive conditions that you can force the client to make requests in predetermined sizes and tiles. As for applying this to the general case, I invite you to have a look at how big the raster surface is and how much space is required to actually store on the disk a full map (only _one_ map, some GeoServer installs do serve 500-1000 different layers) here: I'm not saying you should store the whole map all at once. My approach was to dynamically cache requests that the client may want to make in advance. An easy example would be if a client makes a request for the city center, you create the map for the city center plus the suburbs around it and store it somewhere, then return the city center. If the user then moves around a bit to see the suburbs, you already have the whole map cached and just need to return it, no need to do any further calculation. If you then also compress the image on the fly while you are reading it from disk (or from some memory cache), you will start writing to the output stream very soon (also detecting the dropped connection very soon) and the servlet will not need much RAM. Of course this does not work if you just use Java's built-in PNG encoder. Obviously, caching always comes with the price that you will have the occassional cache miss :-) That is, this does not work for every request but may decrease load and RAM usage a lot for typical use cases. In your OP you write: 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. This indicates that you (1) seem to not use any caching (drawing a map takes time - with caching the map would already have been drawn) and (2) you use BufferedImage which of course does not allow you to PNG-encode on the fly. Both problems would be solved with the above suggestion. Markus - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
RE: How to check if the client dropped the connection
could you explain just a bit more what is a tile? Martin __ Verzicht und Vertraulichkeitanmerkung Diese Nachricht ist vertraulich. Sollten Sie nicht der vorgesehene Empfaenger sein, so bitten wir hoeflich um eine Mitteilung. Jede unbefugte Weiterleitung oder Fertigung einer Kopie ist unzulaessig. Diese Nachricht dient lediglich dem Austausch von Informationen und entfaltet keine rechtliche Bindungswirkung. Aufgrund der leichten Manipulierbarkeit von E-Mails koennen wir keine Haftung fuer den Inhalt uebernehmen. Date: Mon, 28 Sep 2009 21:27:15 +0200 From: me...@mesw.de To: users@tomcat.apache.org Subject: Re: How to check if the client dropped the connection Jason Brittain schrieb: The first time you call flush, it will send the HTTP response headers to the client, so you would need to first set the headers before flushing. That sounds difficult for you to do because you're writing an image, and one of the headers would be Content-Length, which you probably don't know until your image is generated. Actually, Content-Length is optional as per the HTTP-1.1 spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html However, my take on the OP is that a better optimization strategy in this case would be to just cache a larger image on the server rather than generating every image on-demand. That is, when the user is moving around in the image, the server, on the first request, would calculate the image for a much larger portion of the map than requested and stores it on disk in temporary storage (or in some cache area in RAM, if feasible, after all RAM is cheap these days and 64-bit machines can have lots of RAM). Storage of the images would not be done all at once but in tiles. When then user then moves around in the client, the requests just reads the tiles of the created image from disk, puts them together and clips the borders, then compresses the image and sends it to the client. It is possible that PNG even has some support for compressing parts of an image so the tiles itself could be already stored in compressed format, but it's been a while since I read the PNG spec last time. The same could be done for zooming by storing images in a pyramidal structure, like it is done in pattern recognition. While the user is moving, a background thread associated with the client could try to anticipate where the user is likely to be moving to and calculate the given tiles in advance. Actually, this sounds like an interesting project for several Ph.D. theses... Markus - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org _ Hotmail® has ever-growing storage! Don’t worry about storage limits. http://windowslive.com/Tutorial/Hotmail/Storage?ocid=TXT_TAGLM_WL_HM_Tutorial_Storage_062009
[OT] Re: How to check if the client dropped the connection
Martin Gainty wrote: could you explain just a bit more what is a tile? http://en.wikipedia.org/wiki/Tile It's the same idea, but for images. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How to check if the client dropped the connection
Martin Gainty schrieb: could you explain just a bit more what is a tile? If you have a very large image, say 1 million x 1 million pixels or something like that, it is more efficient to split the image into tiles, that is small images of, say, 256 x 256 pixels. If a certain portion of the big image is requested, you can then load these tiles individually from disk and put them together to form the portion of the image that was requested. Tiles which are inside the requested image portion can be used as is, tiles at the borders may not be contained fully in the requested image and must possibly be clipped. How tiles are used can be seen e.g. in Google Maps: when you have a slow internet connection, while scrolling you can actually see that the map consists of rectangular tiles which are loaded on demand. This is more or less the same concept as blocks when doing paging of virtual memory or pages when talking about processor caches. Even Audacity (audio editor) uses this concept to achieve fast editing of very large audio files. Markus - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org