From 16c57560bc4335fccf0a031ce7d156f929c97388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Tue, 21 Nov 2017 03:27:11 +0100 Subject: [PATCH] tileserver: cache tiles using memcached --- src/c3nav/tileserver/wsgi.py | 32 +++++++++++++++++++++++--------- src/requirements-tileserver.txt | 2 +- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/c3nav/tileserver/wsgi.py b/src/c3nav/tileserver/wsgi.py index f276b2c3..f2383ebd 100644 --- a/src/c3nav/tileserver/wsgi.py +++ b/src/c3nav/tileserver/wsgi.py @@ -6,6 +6,7 @@ import threading import time from io import BytesIO +import pylibmc import requests from c3nav.mapdata.utils.cache import CachePackage @@ -44,6 +45,8 @@ class TileServer: self.cache_package = None self.cache_package_etag = None + self.tile_cache = pylibmc.Client(["127.0.0.1"], binary=True, behaviors={"tcp_nodelay": True, "ketama": True}) + wait = 1 while True: success = self.load_cache_package() @@ -97,6 +100,12 @@ class TileServer: start_response('404 Not Found', [('Content-Type', 'text/plain')]) return [text] + def deliver_tile(self, start_response, etag, data): + start_response('200 OK', [('Content-Type', 'image/png'), + ('Cache-Control', 'no-cache'), + ('ETag', etag)]) + return [data] + def __call__(self, env, start_response): match = self.path_regex.match(env['PATH_INFO']) if match is None: @@ -142,19 +151,24 @@ class TileServer: # check browser cache if_none_match = env.get('HTTP_IF_NONE_MATCH') - if if_none_match: - tile_etag = build_tile_etag(level, zoom, x, y, base_cache_key, access_cache_key, self.tile_secret) - if if_none_match == tile_etag: - start_response('304 Not Modified', [('Content-Type', 'text/plain'), ('ETag', tile_etag)]) - return [b''] + tile_etag = build_tile_etag(level, zoom, x, y, base_cache_key, access_cache_key, self.tile_secret) + if if_none_match == tile_etag: + start_response('304 Not Modified', [('Content-Type', 'text/plain'), + ('ETag', tile_etag)]) + return [b''] + + cached_result = self.tile_cache.get(tile_etag) + if cached_result is not None: + return self.deliver_tile(start_response, tile_etag, cached_result) r = requests.get('%s/map/%d/%d/%d/%d/%s.png' % (self.upstream_base, level, zoom, x, y, access_cache_key), headers=self.auth_headers) - headers = [('Content-Type', r.headers['Content-Type'])] - if 'ETag' in r.headers: - headers.append(('ETag', r.headers['ETag'])) - start_response('%d %s' % (r.status_code, r.reason), headers) + if r.status_code == 200 and r.headers['Content-Type'] == 'image/png': + self.tile_cache[tile_etag] = r.content + return self.deliver_tile(start_response, tile_etag, r.content) + + start_response('%d %s' % (r.status_code, r.reason), [('Content-Type', r.headers['Content-Type'])]) return [r.content] diff --git a/src/requirements-tileserver.txt b/src/requirements-tileserver.txt index e0be1fe2..79399790 100644 --- a/src/requirements-tileserver.txt +++ b/src/requirements-tileserver.txt @@ -1,3 +1,3 @@ requests>=2.17,<2.18 numpy>=1.13,<1.14 - +pylibmc>=1.5,<1.6