美文网首页python
Django缓存中间件解析。

Django缓存中间件解析。

作者: LumiaXu | 来源:发表于2017-12-30 01:06 被阅读14次

    前言

    如果使用缓存中间件(在settings里面加上设置)那么中间件将会基于URL对Django的页面进行缓存。启用缓存中间件的规范方法是设置“UpdateCacheMiddleware”作为你的第一件中间件,而且“FetchFromCacheMiddleware”作为最后的中间件。
    就像下面一样:

    MIDDLEWARE = [
            'django.middleware.cache.UpdateCacheMiddleware',
            ...
            'django.middleware.cache.FetchFromCacheMiddleware'
            ]
    

    这是违反直觉的,而违反直觉的原因在于:“UpdateCacheMiddleware” 需要运行最后的响应阶段,处理中间件自下而上; “FetchFromCacheMiddleware” 需要在请求阶段最后运行,自上而下处理中间件。

    在缓存中间件中,还有一类简单的中间件:“CacheMiddleware”可以用于一些简单的站点。但是,如果有任何其他中间件需要影响缓存密钥,那么您就可以需要 “UpdateCacheMiddleware” 和 “FetchFromCacheMiddleware”两个中间件,而不是仅用CacheMiddleware一个中间件。这种情况在有“LocaleMiddleware”出现的情况下是尤为经常。

    缓存中间件的工作任务:

    • 只有状态码为200的GET或HEAD请求被高速缓存。
    • 每个页面存储的秒数由响应(Response)的“缓存控制(Cache-Control)”头部中的“max-age”部分设置的。如果“max-age”部分没有的话,那么此项设置落到CACHE_MIDDLEWARE_SECONDS变量上。
    • 这个中间件期望HEAD请求与相应的GET请求完全相同的响应头。【见工作任务1。
    • 发生异常故障时时,从process_request那返回原始请求的浅层拷贝。【告诉了我们这个东西是直接短路process_request, 直接生成HTTPResponse对象,然后这个HTTPResponse对象就是从原始的返回请求那边传过来的浅拷贝】
    • 页面将根据请求头中的内容缓存响应的“Vary”title。
    • 该中间件还在响应对象上设置ETag,Last-Modified,Expires和Cache-Control头部。

    缓存的代码解析:

    中间件

    • UpdateCacheMiddleware
    • FetchFromCacheMiddleware
    • CacheMiddleware(继承上面两个)

    UpdateCacheMiddleware

        def process_response(self, request, response):
            """Sets the cache, if needed."""
            if not self._should_update_cache(request, response):
                # We don't need to update the cache, just return.
                return response
    
            if response.streaming or response.status_code != 200:
                return response
    
            # Don't cache responses that set a user-specific (and maybe security
            # sensitive) cookie in response to a cookie-less request.
            if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
                return response
    
            # Try to get the timeout from the "max-age" section of the "Cache-
            # Control" header before reverting to using the default cache_timeout
            # length.
            timeout = get_max_age(response)
            if timeout is None:
                timeout = self.cache_timeout
            elif timeout == 0:
                # max-age was set to 0, don't bother caching.
                return response
            patch_response_headers(response, timeout)
            if timeout:
                cache_key = learn_cache_key(request, response, timeout, self.key_prefix, cache=self.cache)
                if hasattr(response, 'render') and callable(response.render):
                    response.add_post_render_callback(
                        lambda r: self.cache.set(cache_key, r, timeout)
                    )
                else:
                    self.cache.set(cache_key, response, timeout)
            return response
    

    Hook点:process_response
    内容:

    • 检查是否需要更新缓存:
      • 方法,过期,cookie等
    • 如果需要更新缓存,则
      • 先获取cookie_key。
      • 如果要渲染:把httpresponse对象中的缓存加入渲染好的模板。
      • 如果不要渲染:就直接吧HttpResponse对象加入缓存中。
      • 返回HttpRespone对象。

    FetchFromCacheMiddleware

    def process_request(self, request):
            """
            Checks whether the page is already cached and returns the cached
            version if available.
            """
            if request.method not in ('GET', 'HEAD'):
                request._cache_update_cache = False
                return None  # Don't bother checking the cache.
    
            # try and get the cached GET response
            cache_key = get_cache_key(request, self.key_prefix, 'GET', cache=self.cache)
            if cache_key is None:
                request._cache_update_cache = True
                return None  # No cache information available, need to rebuild.
            response = self.cache.get(cache_key)
            # if it wasn't found and we are looking for a HEAD, try looking just for that
            if response is None and request.method == 'HEAD':
                cache_key = get_cache_key(request, self.key_prefix, 'HEAD', cache=self.cache)
                response = self.cache.get(cache_key)
    
            if response is None:
                request._cache_update_cache = True
                return None  # No cache information available, need to rebuild.
    
            # hit, return cached response
            request._cache_update_cache = False
            return response
    

    源码解析:

    • Hook点在process_request阶段。
    • 请求刚处理进来,针对工作任务中的2要求验证HEAD和GET方法。
    • 通过请求,找到cache_key从而能通过cache_key找到cache的内容。
    • 按照【缓存中间件的工作任务】中的要求2,进行response的构建
    • 这里直接构建一个response属于一个返回短路。

    相关文章

      网友评论

        本文标题:Django缓存中间件解析。

        本文链接:https://www.haomeiwen.com/subject/gmfggxtx.html