Cache-control in WMS Requests

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Cache-control in WMS Requests

Paul Ramsey
All,

After doing a workshop with OpenLayers and Mapserver, one of the
things I noticed was that browsers tend to beat on Mapserver more than
they should, because they are not being told that they can cache the
tiles they have retrieved.  As soon as the tiles move out-of-scope,
they are gone, and moving back forces them to re-load.

For many applications, this behavior is way too hard on the server,
particularly since the browser has a perfectly good local cache
directory we could be taking advantage of.

I have (and it only took me 2 hours!) put together a five-line patch
to mapwms.c that allows an optional "http_max_age" parameter in the
WEB metadata, and will set it.  I provide this as an example for
discussion, not as a finished patch.  I need to add the HTTP 1.0
equivalent before it could be applied.

The main question that came up as I spelunked around looking for the
right place to insert this logic was "where!?".  I ended up settling
on the WMS GetMap, because that's where clients like OpenLayers will
tend to exercise it, but there are a number of places in the code
generating stuff that could be flagged with cache-control information.

mode=legend, mode=map, getlegendgraphic, etc etc.

P.

===================================================================
--- mapwms.c (revision 7459)
+++ mapwms.c (working copy)
@@ -2196,8 +2196,15 @@
     img = msDrawMap(map, MS_FALSE);
   if (img == NULL)
       return msWMSException(map, nVersion, NULL);
-

+  /* Set the HTTP Cache-control headers if they are defined
+     in the map object */
+  const char *http_max_age;
+  if( (http_max_age = msLookupHashTable(&(map->web.metadata),
"http_max_age")) )
+  {
+    msIO_printf("Cache-control: max-age=%s\n", http_max_age , 10, 10);
+  }
+
   msIO_printf("Content-type: %s%c%c",
               MS_IMAGE_MIME_TYPE(map->outputformat), 10,10);
   if (msSaveImage(map, img, NULL) != MS_SUCCESS)
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Bart van den Eijnden (OSGIS)-2
Hey Paul,

why not leave this up to the webserver? That's more flexible IMHO. E.g.
using Apache's mod_headers.

Best regards,
Bart

--
Bart van den Eijnden
OSGIS, Open Source GIS
http://www.osgis.nl


--------- Oorspronkelijk bericht --------
Van: Paul Ramsey <[hidden email]>
Naar: [hidden email] <[hidden email]>
Onderwerp: [mapserver-dev] Cache-control in WMS Requests
Datum: 17/03/08 21:04

> All,
>
> After doing a workshop with OpenLayers and Mapserver, one of the
> things I noticed was that browsers tend to beat on Mapserver more than
> they should, because they are not being told that they can cache the
> tiles they have retrieved.  As soon as the tiles move out-of-scope,
> they are gone, and moving back forces them to re-load.
>
> For many applications, this behavior is way too hard on the server,
> particularly since the browser has a perfectly good local cache
> directory we could be taking advantage of.
>
> I have (and it only took me 2 hours!) put together a five-line patch
> to mapwms.c that allows an optional &quot;http_max_age&quot; parameter in
the
> WEB metadata, and will set it.  I provide this as an example for
> discussion, not as a finished patch.  I need to add the HTTP 1.0
> equivalent before it could be applied.
>
> The main question that came up as I spelunked around looking for the
> right place to insert this logic was &quot;where!?&quot;.  I ended up
settling

> on the WMS GetMap, because that's where clients like OpenLayers will
> tend to exercise it, but there are a number of places in the code
> generating stuff that could be flagged with cache-control information.
>
> mode=legend, mode=map, getlegendgraphic, etc etc.
>
> P.
>
> ===================================================================
> --- mapwms.c (revision 7459)
> +++ mapwms.c (working copy)
> @@ -2196,8 +2196,15 @@
>      img = msDrawMap(map, MS_FALSE);
>    if (img == NULL)
>        return msWMSException(map, nVersion, NULL);
> -
>
> +  /* Set the HTTP Cache-control headers if they are defined
> +     in the map object */
> +  const char *http_max_age;
> +  if( (http_max_age = msLookupHashTable(&amp;(map-&gt;web.metadata),
> &quot;http_max_age&quot;)) )
> +  {
> +    msIO_printf(&quot;Cache-control: max-age=%sn&quot;, http_max_age ,
10, 10);

> +  }
> +
>    msIO_printf(&quot;Content-type: %s%c%c&quot;,
>                MS_IMAGE_MIME_TYPE(map-&gt;outputformat), 10,10);
>    if (msSaveImage(map, img, NULL) != MS_SUCCESS)
> _______________________________________________
> mapserver-dev mailing list
> [hidden email]
> http://lists.osgeo.org/mailman/listinfo/mapserver-dev
>
>



_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Christopher Schmidt-2
On Tue, Mar 18, 2008 at 07:52:44AM +0100, Bart van den Eijnden (OSGIS) wrote:
> Hey Paul,
>
> why not leave this up to the webserver? That's more flexible IMHO. E.g.
> using Apache's mod_headers.

Well, the easiest answer to this is "MapServer knows more about its
requests than Apache does". You can't do caching rules based on query
strings in apache (at least, not easily) so you can't, for example,
cache getmap requests without also caching getcapabilities -- so if
you're routinely changing the number of layers in a dataset, but never
changing the content of those layers, then MapServer can't provide an
accurate caching header.

Then, there's the fact that not everyone uses servers where it's easy to
set caching headers (I've heard a number of complaints that this is hard
under IIS, for example.)

All in all, I think that dumb caching at the level of the webserver is a
great first step, but it's one of the things that a deeper understanding
of the data that you're serving can affect greatly, and that's
information that the webserver doesn't have.

Regards,
--
Christopher Schmidt
MetaCarta
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Paul Ramsey
For reasons of "user ease" having things like this configured in one
place is handy ("how do I improve my Openlayers performance?" "add
this one line"). I'm going to test this morning though, and see how
much difference this one header makes to browsers in terms of actual
caching behavior (they might ignore the header because the URL is
"cgi-shaped", etc, etc).  Unfortunately the rest of the headers that
affect caching (last modified, etag, etc) are probably off the table,
since they can't be tracked properly in a dynamic environment.

P.

On 3/18/08, Christopher Schmidt <[hidden email]> wrote:

> On Tue, Mar 18, 2008 at 07:52:44AM +0100, Bart van den Eijnden (OSGIS) wrote:
>  > Hey Paul,
>  >
>  > why not leave this up to the webserver? That's more flexible IMHO. E.g.
>  > using Apache's mod_headers.
>
>
> Well, the easiest answer to this is "MapServer knows more about its
>  requests than Apache does". You can't do caching rules based on query
>  strings in apache (at least, not easily) so you can't, for example,
>  cache getmap requests without also caching getcapabilities -- so if
>  you're routinely changing the number of layers in a dataset, but never
>  changing the content of those layers, then MapServer can't provide an
>  accurate caching header.
>
>  Then, there's the fact that not everyone uses servers where it's easy to
>  set caching headers (I've heard a number of complaints that this is hard
>  under IIS, for example.)
>
>  All in all, I think that dumb caching at the level of the webserver is a
>  great first step, but it's one of the things that a deeper understanding
>  of the data that you're serving can affect greatly, and that's
>  information that the webserver doesn't have.
>
>  Regards,
>
> --
>  Christopher Schmidt
>  MetaCarta
>
> _______________________________________________
>  mapserver-dev mailing list
>  [hidden email]
>  http://lists.osgeo.org/mailman/listinfo/mapserver-dev
>
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Christopher Schmidt-2
On Tue, Mar 18, 2008 at 10:43:50AM -0700, Paul Ramsey wrote:
> For reasons of "user ease" having things like this configured in one
> place is handy ("how do I improve my Openlayers performance?" "add
> this one line"). I'm going to test this morning though, and see how
> much difference this one header makes to browsers in terms of actual
> caching behavior

It should be significant, based on my experience.

> (they might ignore the header because the URL is "cgi-shaped", etc,
> etc).

I've never had that problem.

> Unfortunately the rest of the headers that affect caching (last
> modified, etag, etc) are probably off the table, since they can't be
> tracked properly in a dynamic environment.

I'm not sure I agree with this. Perhaps by default you would want such
tracking 'off', but certainly one could have a setting which says "use
the last modified time of the mapfile for these things", and use the
etag/last-modified for that. (Admittedly, it requires more work.)

Regards,
--
Christopher Schmidt
MetaCarta
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Paul Ramsey
On 3/18/08, Christopher Schmidt <[hidden email]> wrote:

>  > Unfortunately the rest of the headers that affect caching (last
>  > modified, etag, etc) are probably off the table, since they can't be
>  > tracked properly in a dynamic environment.
>
> I'm not sure I agree with this. Perhaps by default you would want such
>  tracking 'off', but certainly one could have a setting which says "use
>  the last modified time of the mapfile for these things", and use the
>  etag/last-modified for that. (Admittedly, it requires more work.)

I was thinking that using the last-modified dates/etags on the source
files would be a clever trick, but it wouldn't work for
database-backed layers, and service backed layers, so it would a
somewhat complex bit of trickery.  Layer-level max_age is tempting,
but also adds complexity with unknown returns.  So, step one,
map-level max_age, and see if anyone uses/likes it.
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Sean Gillies
In reply to this post by Christopher Schmidt-2
Christopher Schmidt wrote:

> On Tue, Mar 18, 2008 at 10:43:50AM -0700, Paul Ramsey wrote:
>> For reasons of "user ease" having things like this configured in one
>> place is handy ("how do I improve my Openlayers performance?" "add
>> this one line"). I'm going to test this morning though, and see how
>> much difference this one header makes to browsers in terms of actual
>> caching behavior
>
> It should be significant, based on my experience.
>
>> (they might ignore the header because the URL is "cgi-shaped", etc,
>> etc).
>
> I've never had that problem.
>
>> Unfortunately the rest of the headers that affect caching (last
>> modified, etag, etc) are probably off the table, since they can't be
>> tracked properly in a dynamic environment.
>
> I'm not sure I agree with this. Perhaps by default you would want such
> tracking 'off', but certainly one could have a setting which says "use
> the last modified time of the mapfile for these things", and use the
> etag/last-modified for that. (Admittedly, it requires more work.)
>
> Regards,

Doesn't WMS have something "better" than ETag or Last-Modified? Update
sequence?

Sean



_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

RE: Cache-control in WMS Requests

Kralidis,Tom [Ontario]
 

> -----Original Message-----
> From: [hidden email]
> [mailto:[hidden email]] On Behalf Of
> Sean Gillies
> Sent: 18 March, 2008 2:01 PM
> To: [hidden email]
> Subject: Re: [mapserver-dev] Cache-control in WMS Requests
>
> Christopher Schmidt wrote:
> > On Tue, Mar 18, 2008 at 10:43:50AM -0700, Paul Ramsey wrote:
> >> For reasons of "user ease" having things like this
> configured in one
> >> place is handy ("how do I improve my Openlayers performance?" "add
> >> this one line"). I'm going to test this morning though,
> and see how
> >> much difference this one header makes to browsers in terms
> of actual
> >> caching behavior
> >
> > It should be significant, based on my experience.
> >
> >> (they might ignore the header because the URL is
> "cgi-shaped", etc,
> >> etc).
> >
> > I've never had that problem.
> >
> >> Unfortunately the rest of the headers that affect caching (last
> >> modified, etag, etc) are probably off the table, since
> they can't be
> >> tracked properly in a dynamic environment.
> >
> > I'm not sure I agree with this. Perhaps by default you
> would want such
> > tracking 'off', but certainly one could have a setting
> which says "use
> > the last modified time of the mapfile for these things",
> and use the
> > etag/last-modified for that. (Admittedly, it requires more work.)
> >
> > Regards,
>
> Doesn't WMS have something "better" than ETag or
> Last-Modified? Update sequence?
>

WMS does, yes.  And MapServer now supports it for all WxS Server
support.  See http://trac.osgeo.org/mapserver/ticket/2384 and additional
commentary at
http://www.kralidis.ca/blog/2008/02/12/mapserver-and-wxs-updatesequence/
for more details.

..Tom


> Sean
>
>
>
> _______________________________________________
> mapserver-dev mailing list
> [hidden email]
> http://lists.osgeo.org/mailman/listinfo/mapserver-dev
>
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Paul Ramsey
Right, that's for Capabilities files, which I'm not touching. I'm just
mucking with GetMap right now, since that's the only API tiled clients
seem to be hitting mapserver with at the moment.

My tests on Safari and Firefox show that the HTTP header really does
make a difference, the browsers hold on to their tiles, so you can
zoom in and out without re-hitting the server for maps you have
already requested.

I'll see if I can figure out how to do the HTTP 1.0 "Expires" header
and then submit a patch.

P.

On 3/18/08, Kralidis,Tom [Burlington] <[hidden email]> wrote:

>
>
>  > -----Original Message-----
>  > From: [hidden email]
>  > [mailto:[hidden email]] On Behalf Of
>  > Sean Gillies
>  > Sent: 18 March, 2008 2:01 PM
>  > To: [hidden email]
>  > Subject: Re: [mapserver-dev] Cache-control in WMS Requests
>  >
>  > Christopher Schmidt wrote:
>  > > On Tue, Mar 18, 2008 at 10:43:50AM -0700, Paul Ramsey wrote:
>  > >> For reasons of "user ease" having things like this
>  > configured in one
>  > >> place is handy ("how do I improve my Openlayers performance?" "add
>  > >> this one line"). I'm going to test this morning though,
>  > and see how
>  > >> much difference this one header makes to browsers in terms
>  > of actual
>  > >> caching behavior
>  > >
>  > > It should be significant, based on my experience.
>  > >
>  > >> (they might ignore the header because the URL is
>  > "cgi-shaped", etc,
>  > >> etc).
>  > >
>  > > I've never had that problem.
>  > >
>  > >> Unfortunately the rest of the headers that affect caching (last
>  > >> modified, etag, etc) are probably off the table, since
>  > they can't be
>  > >> tracked properly in a dynamic environment.
>  > >
>  > > I'm not sure I agree with this. Perhaps by default you
>  > would want such
>  > > tracking 'off', but certainly one could have a setting
>  > which says "use
>  > > the last modified time of the mapfile for these things",
>  > and use the
>  > > etag/last-modified for that. (Admittedly, it requires more work.)
>  > >
>  > > Regards,
>  >
>  > Doesn't WMS have something "better" than ETag or
>  > Last-Modified? Update sequence?
>  >
>
>
> WMS does, yes.  And MapServer now supports it for all WxS Server
>  support.  See http://trac.osgeo.org/mapserver/ticket/2384 and additional
>  commentary at
>  http://www.kralidis.ca/blog/2008/02/12/mapserver-and-wxs-updatesequence/
>  for more details.
>
>
>  ..Tom
>
>
>
>  > Sean
>  >
>  >
>  >
>  > _______________________________________________
>  > mapserver-dev mailing list
>  > [hidden email]
>  > http://lists.osgeo.org/mailman/listinfo/mapserver-dev
>  >
>  _______________________________________________
>  mapserver-dev mailing list
>  [hidden email]
>  http://lists.osgeo.org/mailman/listinfo/mapserver-dev
>
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Paul Ramsey
Also on IE7.

BTW, Firefox 3 loads the tiles in an attractive spiral from the center
out, probably the order desired by the clever openlayers developers,
but oft ignored by other browsers.

P.

On 3/18/08, Paul Ramsey <[hidden email]> wrote:
>  My tests on Safari and Firefox show that the HTTP header really does
>  make a difference, the browsers hold on to their tiles, so you can
>  zoom in and out without re-hitting the server for maps you have
>  already requested.
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Christopher Schmidt-2
On Tue, Mar 18, 2008 at 11:59:58AM -0700, Paul Ramsey wrote:
> Also on IE7.
>
> BTW, Firefox 3 loads the tiles in an attractive spiral from the center
> out, probably the order desired by the clever openlayers developers,
> but oft ignored by other browsers.

Really? I've definitely seen Spirals in FF2, Safari, and IE... though to
be honest, I see it much less these days, since I'm always using the
multi-hosts DNS trick to accelerate loading (which leads to loads being
parallelized, and thus you get lots of chunks of the 'spiral' at the
same time).

Regards,
--
Christopher Schmidt
MetaCarta
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Paul Ramsey
First time I really noticed it, and one of the annoyances of IE6 was
always that it appeared to load the off-screen stuff first :)
Everything is hard to quantify... I noticed after writing the post
that Safari appeared to cache the images REGARDLESS of the
cache-control header.  And then FF seemed to start ignoring the header
and requesting tiles every time, then it flipped back and started
caching...

I think the moral of the story is to do the right thing (express your
desired behavior) then cross your fingers and hope. Better than
nothing.

On the HTTP 1.0 versus 1.1 debate, I found this post interesting. I
think the behavior as it stands is probably good enough.

http://www.mnot.net/blog/2007/05/15/expires_max-age

P.

On 3/18/08, Christopher Schmidt <[hidden email]> wrote:

> On Tue, Mar 18, 2008 at 11:59:58AM -0700, Paul Ramsey wrote:
>  > Also on IE7.
>  >
>  > BTW, Firefox 3 loads the tiles in an attractive spiral from the center
>  > out, probably the order desired by the clever openlayers developers,
>  > but oft ignored by other browsers.
>
>
> Really? I've definitely seen Spirals in FF2, Safari, and IE... though to
>  be honest, I see it much less these days, since I'm always using the
>  multi-hosts DNS trick to accelerate loading (which leads to loads being
>  parallelized, and thus you get lots of chunks of the 'spiral' at the
>  same time).
>
>  Regards,
>
> --
>  Christopher Schmidt
>  MetaCarta
>
> _______________________________________________
>  mapserver-dev mailing list
>  [hidden email]
>  http://lists.osgeo.org/mailman/listinfo/mapserver-dev
>
_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Jeff McKenna-2
Related to this: yesterday's cache control changes in mapwms.c are
causing me build errors with MSVC:

mapwms.c(2202) : error C2143: syntax error : missing ';' before 'const'
mapwms.c(2203) : error C2065: 'http_max_age' : undeclared identifier
mapwms.c(2203) : warning C4047: '=' : 'int' differs in levels of
indirection fro
m 'const char *'


-jeff


_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Yewondwossen Assefa
Just committed a change in mapwms.c to fix te build error.

Later,


Jeff McKenna wrote:

> Related to this: yesterday's cache control changes in mapwms.c are
> causing me build errors with MSVC:
>
> mapwms.c(2202) : error C2143: syntax error : missing ';' before 'const'
> mapwms.c(2203) : error C2065: 'http_max_age' : undeclared identifier
> mapwms.c(2203) : warning C4047: '=' : 'int' differs in levels of
> indirection fro
> m 'const char *'
>
>
> -jeff
>
>
> _______________________________________________
> mapserver-dev mailing list
> [hidden email]
> http://lists.osgeo.org/mailman/listinfo/mapserver-dev
>
>


--
----------------------------------------------------------------
Assefa Yewondwossen
Software Analyst

Email: [hidden email]
http://www.dmsolutions.ca/

Phone: (613) 565-5056 (ext 14)
Fax:   (613) 565-0925
----------------------------------------------------------------

_______________________________________________
mapserver-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapserver-dev
Reply | Threaded
Open this post in threaded view
|

Re: Cache-control in WMS Requests

Tom Jordan
Are there any Linux or Windows binaries of MapServer with this patch that I could download?
Perhaps a beta or nightly build?

On a related note, this patch allows a particular user to effectively utilitize his client-side cache. Is there a way to cache these tiles on the server-side also, so the same tile would not have to be regenerated for each client?

Thanks,
Tom

> <quote author="Yewondwossen Assefa-2">
> Just committed a change in mapwms.c to fix te build error.
>
> Later,
>
>
> Jeff McKenna wrote:
> > Related to this: yesterday's cache control changes in mapwms.c are
> > causing me build errors with MSVC:
> >
> > mapwms.c(2202) : error C2143: syntax error : missing ';' before 'const'
> > mapwms.c(2203) : error C2065: 'http_max_age' : undeclared identifier
> > mapwms.c(2203) : warning C4047: '=' : 'int' differs in levels of
> > indirection fro
> > m 'const char *'
> >
> >
> > -jeff