代码之家  ›  专栏  ›  技术社区  ›  Jiaaro

缓存后端在devserver上工作,但不是mod wsgi

  •  0
  • Jiaaro  · 技术社区  · 14 年前

    我正在使用自定义缓存后端来包装内置缓存后端,以便将当前站点ID添加到所有缓存密钥中(这对于具有单个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的单进程、单线程的特性?

    我已经为此苦苦挣扎了好几天了,任何帮助都会得到感激的。

    额外信息:

    • 网络派系共享托管(CentOS)
    • Apache 2
    • 巨蟒2.5
    • Django1.1.1
    • MODYWSGI 2.5
    • MySQL 5

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

    站点设置/缓存包装:

    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修饰器与一些中间件一起工作,以确定当前站点。它们在这里:

    装饰:

    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
    

    和中间件.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中)。

    编辑: 我发现了一个 list of the differences between devserver and apache 在Django的文档中,

    devserver将已安装的应用程序添加到 sys.path,apache没有。

    也许这和它有关?

    2 回复  |  直到 14 年前
        1
  •  1
  •   Crast    14 年前

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

    cache backend docs

    如果设置好了,但仍有问题,请尝试切换到虚拟缓存模块或本地内存模块(即使这不是一个好的生产设置),以查看这些模块是否工作,如果工作正常,则可能会在wsgi的python路径中缺少一个包,如 python-memcached

        2
  •  0
  •   Jiaaro    14 年前

    问题的根源是 sys.path 我必须确保mod wsgi设置与dev服务器具有相同的sys.path,并且不在不属于它们的地方保留任何额外的包副本(从某种程度上不通过版本控制应用于服务器的重构中)