This is a branch of TileLite - it significantly changes the way that tiles are requested and data is stored. The main TileLite branch works as a traditional tile server - the user specifies a Mapnik XML file or Cascadenik file at startup and datasources are initialized at that point.
In contrast, this branch doesn't require a mapping server to intially contain any layer configuration, data, or mapfiles. Instead, the data and mapfile for each request is specified within the tile URL. Performance is ensured by caching, so that tile requests of this type are typically as fast as the other system, and further performance tweaks make this branch faster in certain cases. However, it is necessary to underline the fact that the schemes for requesting tiles for the two applications are different and incompatible.
From the client perspective, this branch of TileLite could be re-requesting data and mapfiles for each request. The caching system is written so that clients can make this assumption and the server will respond correctly to each request. In order to do this, there's a multi-layered caching system that reflects the performance hit of types of refetching. From the outside in, a tile request will hit the following caches:
- Tile cache Once tiles are rendered and served to the client, they're saved as files on the local filesystem. From this point, it's strongly recommended that another server serves from this cache, in the style of StaticGenerator. This way, Python is not invoked for extremely lightweight requests in which it needs to open a file and deliver it to the client, but a faster server can do this and only hit Python when it needs to render a tile.
- Map and Data static cache Rendering a map with Mapnik involves creating Mapnik objects that wrap datasources and mapfiles. This version of TileLite makes sure that the initialization time for these objects, which can be significant, is not a hit on performance for every tile request. As such, it maintains a FIFO cache of
Mapnik.Datasource
andMapnik.Map
objects. This cache is small - it only contains 10 objects of each type. The intent is not to thoroughly cache such objects, but to take care of situations in which multiple maps are being requested simultaneously. This cache stays small, as well, because it is in memory and TileLite doesn't aim to do memory management. - Map and Data file cache Map XML and Data files are cached locally by Mapnik. They are only removed when the cache is manually cleared by an authorized client - given the size of the files, it's unlikely that these files will fill a disk.
-
Tile request initially hits
TileHandler.get()
, which is decorated by@tornado.web.asynchronous
, which ensures that the connection is not automatically closed when the method returns. -
TileHandler.get()
returns None, but calls_map_cache.get()
with a callback toTileHandler.async_get()
. -
If the map is static-cached, and exists in
self.mapnik_maps
,TileHandler.async_get()
is immediately triggered with that map. -
Otherwise, a new
PreCache
object is initialized for this map file alone. The initial callback toTileHandler.async_get()
is thus passed down toPreCache.execute()
-
PreCache.execute()
callsPreCache.process_request()
for each shapefile, which uses Tornado's async download procedure. It runs itself in a timeout-loop while files are still downloading. -
When all download locks are cleared,
PreCache.execute()
is called again, and calls its callback, which is async_get, which finally renders the map with the givenmapnik_map
value.req -> TileHandler.get() -> _map_cache.get() -> TileHandler.async_get() -> PreCache.execute() -> ^ keeps open connection PreCache.process_request() -> TileHandler.async_get() -> render & self.finish() ^ timeout loop
http://toomanypets.com/{base64-encoded mapfile url}/{z}/{x}/{y}.png
http://toomanypets.com/{base64-encoded mapfile url}/{z}/{x}/{y}.json
http://toomanypets.com/{base64-encoded mapfile url}/{z}/{x}/{y}.grid.json
http://toomanypets.com/{base64-encoded mapfile url}/fields.json
This software is unsupported on Windows
-
Python 2.5 - 2.7 with cssutils, pil and pycurl.
-
Mapnik 2 is required to use the metawriter functionality in this branch.
svn checkout -r2301 http://svn.mapnik.org/trunk
-
svn checkout -r1044 http://mapnik-utils.googlecode.com/svn/trunk/serverside/cascadenik
For deployment, running a fast server like Nginx in front of TileLite to serve static files is highly recommended.
Using Mapnik 2 means using subversion trunk
and compiling it yourself. There are not binary installers available yet for Mapnik 2. After running scon.py configure
by sure that gdal
is listing as an INPUT_PLUGIN
(you may need to add it manually) in config.py. You'll want a line like:.
INPUT_PLUGINS = 'gdal,ogr,postgis,raster,shape'
Using MacPorts to build and install Tilelive's dependencies is possible, but there are a few things to watch out for.
- Be sure you compile Boost with the bindings for Python, ICU and Regex. You can use a command like
port install boost +python26+icu+regex
to do this. - MacPorts makes the Python
easy_install
utility available in the packagepy26-setuptools
, but sure to install that and specifyeasy_install-2.6
when using it to install software.
- Download or git clone TileLive
python setup.py install
- Run
liveserv.py
in your Terminal
Typically TileLive in production typically means running it in a more complex stack than simply liveserv
'ing. A setup looks like
- Nginx frontend, with a config similar to the one in sample_configuration. This will round-robin distribute requests across 4 TileLive backends
- TileLive backends, managed by supervisord or similar, running on a range of ports, like 8000-8003.
- Disk cache, in a mounted partition or
/tmp
It occasionally becomes necessary to clear different kinds of caches:
- Tile cache, if data/style is updated and tiles are cached. This can be cleared selectively by mapfile / domain. For instance, if you want to clear all tiles generated from a certain mapfile, find the mapfile part of their url, and
rm -rf /mnt/cache/tile/{that mapfile url}
- Mapfile cache, if mapfiles are updated
- Static caches
- Data cache, if downloaded data is invalid. However, it's more preferable to update the URL of now-resolving data, rather than resolve bad data.
TileLive has some expectations about provided mapfiles, given the great variety of mapfiles possible with Mapnik and its demands upon how data is handled.
In order to support data tiles (enabled whenever --tile_cache
is set), the mapfile must contain a valid MetaWriter entry
<MetaWriter
name="metawriter"
only-nonempty="false"
type="point"
file="[tile_dir]/[z]/[x]/[y].json" />
The only support value of type
is point
and the only supported value of file
is [tile_dir]/[z]/[x]/[y].json
as shown.
Mapfiles should specify a map in EPSG:900913 projection. Support of datasources in mapfiles is dependent upon the version of Cascadenik.
--buffer_size mapnik buffer size
--geojson allow output of GeoJSON
--inspect open inspection endpoints for data
--port run on the given port
--tile_cache enable development tile cache
--tilesize the size of generated tiles
The StyleWriter Drupal module provides integration with TileLite, both for generating mapfiles handling tiles. Any system capable of base64-encoding can be used with this tile layout scheme. This module, as well as Drupal itself, are by no means required for TileLive operation; it can be used with any client that provides mapfiles and uses a map display library compatible with the XYZ/OSM specification.
This branch of TileSeed includes a very simple, restricted seeding script. The
script has no external dependencies and uses four threads to make requests
faster when servers have multiple TileLite threads running as well. The script,
tileseed.py
is also made to integrate with the StyleWriter module.