rawsontetley.org

Using memcached to store web.py sessions

After experiencing problems with long IO/wait times on the sheltermanager.com website, I tracked the problem down to using the web.py DBStore with my user sessions.

Despite it being such a small table, postgresql performed terribly at reading it back and inserting new sessions. Whilst I could have tried to tune it further (eg: by making a new tablespace on a RAM disk to contain it), I decided to investigate memcached since this is just the sort of thing it’s best at.

All you need software-wise is the memcache daemon itself and the python client library. If you’re using Debian, install the appropriate packages:

apt-get install memcached python-memcache

Here’s the web.py session sample with a minimal memcache store:

import web
import memcache

class MemCacheStore(web.session.Store):
    mc = None
    def __init__(self):
        self.mc = memcache.Client(['127.0.0.1:11211'], debug=0)
    def __contains__(self, key):
        return self.mc.get(key) != None
    def __getitem__(self, key):
        return self.mc.get(key)
    def __setitem__(self, key, value):
        self.mc.set(key, value, time = web.config.session_parameters["timeout"])
    def __delitem__(self, key):
        self.mc.delete(key)
    def cleanup(self, timeout):
        pass # Not needed as we assigned the timeout to memcache

web.config.debug = False
urls = (
    "/count", "count",
    "/reset", "reset"
)

app = web.application(urls, locals())
session = web.session.Session(app, MemCacheStore(), initializer={'count': 0})

class count:
    def GET(self):
        session.count += 1
        return str(session.count)

class reset:
    def GET(self):
        session.kill()
        return ""

if __name__ == "__main__":
    app.run()