S'abonner au Flux RSS

Mot-clé - tilecache

Fil des billets - Fil des commentaires

jeudi, novembre 17 2011

Remplir ses caches sur plusieurs niveaux de façon smart

J'utilise tilecache pour générer des tuiles à la volée sur des rendus plus ou moins complexe, et pour réduire un peu la charge du serveur de rendu j'ai mis en place des caches (avec varnish) au devant de celui-ci. L'architecture de cache repose sur 2 niveaux, un cache en frontal direct non public, et 3 caches devant celui-ci qui sont appelés pas les clients OpenLayers (ou autres) et ouvert sur le net. L'intérêt des 3 caches est de bénéficier de l'astuce bien connu des a.tile.., b.tile.., c.tile bien connu des utilisateurs d'OpenStreetMap. Avec tilecache est fournit tilecache_seed qui permet de remplir les cache mais celui-ci ne remplissait pas entièrement mon besoin. En effet il me faut remplir les 3 caches publics, avec l'ensemble des layers rendus et ceci sans mettre à genoux le serveur de rendu. Idéalement l'opération se ferait en une passe sans avoir à ancer plusieurs commandes à la suite. Pour cela j'ai écrit un script perl qui rassemble toutes ces fonctionnalités plus quelques autres.

Le script permet de spécifier autant de serveur à remplir que souhaité, un ensemble de cache à générer, une bbox sur la zone voulue, et un couple de zoom min et max. Lors du lancement le script va extraire un premier serveur du groupe de serveurs indiqués, il va ensuite boucler pour générer tous les layers sur ce serveur sur la première tuile du zoom min, de cette façon le cache en frontal de la machine de rendu va se remplir. Ensuite il va appeler les mêmes tuiles sur les autres serveurs, à cet instant nous avons donc dans tous les caches, tous les layers dans l'espace d'une tuile. Le script va ensuite boucler de même pour toutes les autres tuiles en descendant dans les niveau de zoom après avoir complété le précédent.

Des problèmes fréquemement rencontrés avec des processus comme les remplissage de cache, la saturation du backend, la rupture d'un élément obligent à tout reprendre ou stopper le processus. J'ai essayé d'être le plus smart possible et de faire en sorte que le script aille le plus loin possible en générant le moins d'erreur, les mécanismes mis en oeuvre sont décrits ci-dessous :

  • suppression automatique d'un serveur défaillant, en cours de remplissage un des serveurs caches fait défaut, au bout de 10 réponses consécutives en erreur le serveur est ignoré et le remplissage continu sur les autres normalement
  • réduction de la sollicitation du backend, en cours de remplissage si le serveur source surcharge, à chaquer erreur 503 reçues le remplissage ralentit, le temps d'attente entre tuiles est augmenté afin de réduire la charge endurée. De même au bout d'un nombre de requête sans erreur le temps d'attente est réduit pour éviter un de traitement trop long. Si le temps d'attente dépasse un seuil le processus prend fin.
  • une option simulate permet de se rendre compte avant de le faire que l'on va faire plus de 3 millions de requêtes HTTP, des fois cela peut-être long :-)

Bien évidemment le script peut-être utlisé au plus simple avec un layer et un seul serveur de cache en direct, si vous n'aimez pas tilecache_seed.

Le script est nommé fill-cache.pl (original) et publié sur Gitorious dans le projet osmtools

Comme tout script/programme celui-ci n'est évidemement pas finit et peut être amélioré, alors comme il est libre, profitez-en, contribuez ! Si vous ne codez pas et avez l'idée de génie, un petit commentaire sur ce billet pourrait voir vos voeux se réaliser.

lundi, mai 23 2011

Rendu de tuile dynamique sous Debian Squeeze

Nous allons mettre en oeuvre une méthode génération de tuile à la volée en utilisant l'outil TileCache sur une distribution Debian Squeeze. Le principe de TileCache exposé ici et de servir par Apache un cgi qui va générer une tuile en utilisant le moteur de rendu mapnik et la stocker sur le disque pour ne pas avoir à la regénérer à chaque appel. La procédure part d'une installation minimale de la dernière version stable de Debian à savoir Squeeze.

Première étape, installer quelques outils de travail qui ne sont pas liés au sujet qui ici nous importe mais dont nous aurons besoin. Cette action se fait avec l'utilisateur root évidemement, chaque futur changement d'utilisateur unix sera clairement explicité.

apt-get install subversion wget unzip bzip2 apache2

Sans trop détailler cette partie nous allons installer une base de données spatiale.

apt-get install postgresql postgis postgresql-8.4-postgis osm2pgsql

Si votre environnement par défaut n'utilise pas une locale en UTF-8 vous aurez à recréer votre cluster postgres, pour cela détruisez l'actuel (toutes données seront perdues) et recréé le par défaut en UTF-8. Les trois commandes suivantes supprime le cluster actuel, créé le nouveau et le démarre.

pg_dropcluster --stop 8.4 main
pg_createcluster 8.4 main --locale fr_FR.UTF-8
pg_ctlcluster 8.4 main start

Pour les manipulations purement postgresql on travaille toujours avec l'utilisateur unix postgres, On passe donc sous cet utilisateur

su - postgres

On vérifie que le cluster est par défaut en utf-8 avec la commande :

psql -l

La colone encoding doit indique 'UTF8'

On créée un utilisateur sans privilèges particulier qui sera utilisé plus loin dans la configuration de mapnik.

createuser -S -D -R -P render

on considère dans la suite du billet que vous affectez ici le mot de passe 'render' à cet utilisateur ; dans la vrai vie personne n'ose faire une chose pareille évidemment :-)

Création de la base de données nommée render, que l'on affecte à l'utilisateur "render"

createdb -O render render

Les trois commandes suivantes servent à spatialiser la base. Cela permet de stocker et manipuler les objets géométriques directement avec des primitives postgres.

createlang plpgsql render
psql -q -d render -f /usr/share/postgresql/8.4/contrib/postgis-1.5/postgis.sql
psql -q -d render -f /usr/share/postgresql/8.4/contrib/postgis-1.5/spatial_ref_sys.sql

Les 3 commandes précédentes doivent être siliencieuses en cas de succès.

On rend la propriété des objets créés à notre utilisateur "render" (les commandes ont été lancées avec le user "postgres")

psql -d render -c 'ALTER TABLE geometry_columns OWNER TO render'
psql -d render -c 'ALTER TABLE spatial_ref_sys OWNER TO render'
psql -d render -c 'ALTER VIEW geography_columns OWNER TO render'

Il nous reste à effectuer l'installation du moteur de rendu mapnik et à charger le fichier de données dans la base de données Désormais nous allons travailler avec un utilisateur dédié au rendering

Retour en root pour installer la paquets nécessaires

apt-get install python-mapnik mapnik-utils

et création d'un utilisateur lambda

adduser render

On passe sous cet utilisateur render pour la suite.

su - render

Installation de mapnik depuis le dépôt svn officiel d'openstreetmap dans le répertoire /home/render/mapnik

svn co http://svn.openstreetmap.org/applications/rendering/mapnik

Toutes les informations nécessaires au rendu ne sont pas stockées dans la base de données, une partie est utilisée depuis des fichiers de formes appelés Shapefiles. On trouvera par exemple dans ceux-ci le contour des continents, qui contrairement aux autres données dans OSM bougent bien peu. Avant de pouvoir faire nos rendus nous allons donc les récupérer grâce à un script bash qui télécharge les fichiers nécessaires et les décompresse dans le répertoire courant :

cd mapnik && bash get-coastlines.sh

Là vous pouvez aller prendre un café, un sandwich ou une entrecôte suivant le débit de votre liaison internet. Le total des fichiers réléchargés dépasse les 450Mo.

A cette étape nous nous rappochons d'OpenStreetMap et allons récupérer les données pour les charger dans notre base. Nous récupérons le fichier pour la région Basse-Normandie, à vous d'adapter pour coller à votre besoin. Les deux sources de fichiers d'export les plus utilisés aujourd'hui sont Geofabrik et Cloudmade, arbitrairement nous utiliserons Cloudmade.

wget http://downloads.cloudmade.com/europe/western_europe/france/basse-normandie/basse-normandie.osm.bz2

Le chargement des données dans la base se fait avec le logiciel osm2pgsql, celui-ci utilise en entrée un fichier de données (comme celui fraichement téléchargé) et un fichier de style qui permet de filtrer les clés sur les objets en fonction de ce que l'on veut afficher sur notre carte. Le packaging de debian évoluant moins rapidement que les tags dans OSM nous allons légèrement adapter le fichier de style ajoutant la clé 'addr:housename' au fichier de style pour que notre démonstration fonctionne.

cp /usr/share/osm2pgsql/default.style .
echo 'node,way addr:housename text linear' >> default.style

Longue étape, le chargement des données se fait avec la commande :

osm2pgsql -s -S default.style -d render basse-normandie.osm.bz2

là encore pour pouvez aller vous ressourcer en alcaloïde méthylxanthine ,

Avec les sources de mapnik est distibué le style utilisé pour le rendu sur le site openstreetmap.org autant l'utiliser. Étant assez complexe il est découpé en plusieurs fichiers xml qu'il faut réassembler en spécifiant la connexion à postgresql qui sera utilisée pour le rendu. Cela se fait en utilisant le script pyhton generate_xml.py de la façon suivante :

./generate_xml.py --host=localhost --port=5432 --user=render --password=render --dbname=render osm.xml > osm-local.xml

Le fichier osm-local.xml sera celui utilisé au final par mapnik, il fait tout de même 9682 lignes, on voit bien l'intérêt du découpage.

J'en profite pour féliciter ceux qui sont arrivés jusque ici et les rassurent aussi, on voit le bout.

Si on fait le point, nous avons nos données de stockées dans la base et le moteur de rendu est installé et configuré, ne nous reste donc plus qu'à passer au sujet principal de ce billet, à savoir TileCache :

Installation se fait au travers du paquet eponyme

apt-get install tilecache

La configuration s'effectue dans le fichier dans /etc/tilecache.cfg auquel nous ajouterons juste une section finale composée de :

[osm]
type=Mapnik
mapfile=/home/render/mapnik/osm-local.xml
spherical_mercator=true
tms_type=google

Cette simple configuration conclue l'installation et il ne nous reste qu'à tester l'ensemble

Par défaut TileCache va stocker les tuiles générées dans /tmp/tilecache à vous d'adapter au besoin. Dans un prochain billet on verra le cache des tuiles directement dans Memcached.

Ma machine de test s'appelle geti que vous remplacerez dans l'url suivante par le nom de votre machine

L'appel de cette url devrait vous afficher la ville de Cherbourg

http://geti/cgi-bin/tilecache.cgi/1.0.0/osm/12/2029/1395.png

Vous reconnaitrez facilement la forme de l'url que vous pourrez utiliser avec Leaflet par exemple.

Pour tester plus en avant votre installation vous pouvez récupérer un fichier simple de test disponible sur mon serveur, adaptez le nom de la machine dans le code et placez le fichier à la racine de votre site web, vous disposerez d'une carte navigable avec des tuiles générées à la volée !

wget http://carto.quiedeville.org/leaflet/article-test.html

Bugs, problèmes, mécompréhension, les commentaires sont ouverts.