缓存后端适用于devserver但不适用于mod_wsgi

时间:2010-02-17 06:05:18

标签: python django caching memcached

我正在使用自定义缓存后端来包装内置缓存后端,以便我可以将当​​前site_id添加到所有cache_keys(这对于使用单个memcached实例的多站点功能非常有用)

不幸的是它在django内置的devserver上工作得很好,但是当我尝试使用mod_wsgi在实时服务器上运行它时会出现一个令人讨厌的错误

以下是我的错误日志中的回溯:

[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1] mod_wsgi (pid=22933): Exception occurred processing WSGI script '/home/jiaaro/webapps/op_wsgi/myProject/deploy/myProject.wsgi'.
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1] Traceback (most recent call last):
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]   File "/home/jiaaro/webapps/op_wsgi/lib/python2.5/django/core/handlers/wsgi.py", line 230, in __call__
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]     self.load_middleware()
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]   File "/home/jiaaro/webapps/op_wsgi/lib/python2.5/django/core/handlers/base.py", line 40, in load_middleware
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]     mod = import_module(mw_module)
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]   File "/home/jiaaro/webapps/op_wsgi/lib/python2.5/django/utils/importlib.py", line 35, in import_module
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]     __import__(name)
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]   File "/home/jiaaro/webapps/op_wsgi/myProject/apps/site_settings/__init__.py", line 6, in <module>
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]     import cache_wrapper
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]   File "/home/jiaaro/webapps/op_wsgi/myProject/apps/site_settings/cache_wrapper.py", line 4, in <module>
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]     from django.core.cache.backends.base import BaseCache
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]   File "/home/jiaaro/webapps/op_wsgi/lib/python2.5/django/core/cache/__init__.py", line 73, in <module>
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]     cache = get_cache(settings.CACHE_BACKEND)
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]   File "/home/jiaaro/webapps/op_wsgi/lib/python2.5/django/core/cache/__init__.py", line 68, in get_cache
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1]     return getattr(module, 'CacheClass')(host, params)
[Wed Feb 17 00:39:34 2010] [error] [client 127.0.0.1] AttributeError: 'module' object has no attribute 'CacheClass'

如果我在同一台机器(实时服务器)上运行devserver,它可以正常工作......我可以毫无困难地执行此操作:

$ cd /home/jiaaro/webapps/op_wsgi/myProject
$ python2.5 manage.py runserver

并在单独的ssh会话中......

$ wget 127.0.0.1:8000

使用memcached和实时数据库正确提供页面。有什么不同的mod_wsgi导入我应该知道的模块的方式吗?

也许关于devserver的单进程,单线程特性?

我几天来一直在努力奋斗,任何帮助都会受到赞赏

额外信息:

  • Webfaction共享主机(centos)
  • Apache 2
  • Python 2.5
  • Django 1.1.1
  • mod_wsgi 2.5
  • MySql 5.0

更多详情:    - 我已经设置了缓存后端(它正在工作,因为你可以看到它在回溯中导入正确的模块)    - 模块中有一个名为“CacheClass”的类:

site_settings / cache_wrapper.py:

from django.conf import settings
CACHE_BACKEND = getattr(settings, 'CUSTOM_CACHE_BACKEND')

from django.core.cache.backends.base import BaseCache

class CacheClass(BaseCache):
    from decorators import accept_site

    def __init__(self, *args):
        from django.core.cache import get_cache
        self.WRAPPED_CACHE = get_cache(CACHE_BACKEND)

    @accept_site
    def add(self, site, key, *args):
        return self.WRAPPED_CACHE.add(self._key(site, key),*args)

    @accept_site
    def get(self, site, key, *args):
        return self.WRAPPED_CACHE.get(self._key(site, key),*args)

    ... (all the rest of the wrapped methods)

    def _key(self, site, key):
        from exceptions import NoCurrentSite
        if not site:
            raise NoCurrentSite
        return "%s|%s" % (site.id, key)

accept_site装饰器与一些中间件一起工作以找出当前站点。他们在这里:

decorators.py:

def accept_site(fn):
    def decorator(self, *args, **kwargs):
        site = kwargs.get('site', None)
        try: 
            del kwargs['site']
        except KeyError: 
            pass

        from .middleware import get_current_site
        site = site or get_current_site()

        if not site:
            raise NoCurrentSite("The current site is not available via thread locals, please specify a site with the 'site' keyword argument")

        return fn(self, site, *args, **kwargs)

    return decorator

和middleware.py

try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

from django.conf import settings
from django.contrib.sites.models import Site

DEFAULT_SITE_ID = 1

_thread_locals = local()
def get_current_site():
    return getattr(_thread_locals, 'site', None)

def set_current_site(site):
    setattr(_thread_locals, 'site', site)

class SiteSettings(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""
    def process_request(self, request):
        if settings.DEBUG:
            site_id = request.GET.get('site_id', DEFAULT_SITE_ID)
        else:
            site_id = DEFAULT_SITE_ID

        current_site_domain = request.META["HTTP_HOST"]
        try:
            current_site = Site.objects.get(domain__iexact=current_site_domain())
        except:
            current_site = Site.objects.get(id=site_id)
        set_current_site(current_site)

所有这些都使用devserver,使用与wsgi服务器相同的设置并使用相同的python路径配置(据我所见)

此时我希望我已经在某个地方创建了一个导入循环(尽管只有在devserver中才会出现这种情况)

编辑:我在django文档中找到了list of the differences between devserver and apache,其中说明了

  

Devserver将已安装的应用添加到   sys.path,Apache没有。

也许这与它有关?

2 个答案:

答案 0 :(得分:1)

您是否在settings.py中设置了CACHE_BACKEND?当DEBUG = True时,这不是问题,因为我相信安装了一个虚拟后端,但是在生产中,即使你正在编写自己的后端,也需要设置这个值,presumedley。

cache backend docs

如果已设置并且您仍然遇到问题,请尝试切换到虚拟缓存模块或本地内存(即使这不是一个好的生产设置),看看这些是否有效,如果有,那么你可能在您的WSGI的python路径中缺少一个包,如python-memcached

答案 1 :(得分:0)

问题的根源是sys.path我必须确保mod_wsgi设置与开发服务器具有相同的sys.path,并且没有额外的软件包副本留在他们不属于的地方(从某种方式通过版本控制未应用于服务器的重构)