【问题标题】:Getting Varnish To Work on Magento让 Varnish 在 Magento 上工作
【发布时间】:2011-06-29 02:42:12
【问题描述】:

首先请原谅我对 Varnish 完全缺乏了解。这是我第一次尝试使用 Varnish。

我在下面的例子:http://www.kalenyuk.com.ua/magento-performance-optimization-with-varnish-cache-47.html

但是,当我安装并运行它时,Varnish 似乎没有缓存。我确实得到了带有单个数字的 X-Varnish 标头和一个值为 1.1 varnish 的 Via 标头

(我的 ISP)告诉我这是因为 Magento 设置了以下 cookie:

Set-Cookie: frontend=6t2d2q73rv9s1kddu8ehh8hvl6; expires=Thu, 17-Feb-2011 14:29:19 GMT; path=/; domain=XX.X.XX.XX; httponly

他们说我要么必须更改 Magento 来处理这个问题,要么配置 Varnish 来处理这个问题。由于更改 Magento 是不可能的,我想知道是否有人可以给我一个线索,告诉我如何配置 Varnish 来处理这个 cookie?

【问题讨论】:

  • cookie 应该是什么样的?那个 cookie 有什么问题?
  • Varnish 不能很好地与 Cookie 配合使用(它永远不会缓存)。所以我必须要么删除 cookie(可疑),要么配置 Varnish 在它请求时不将 cookie 发送回 Apache。
  • 我将在 Magento Connect 页面添加一个支持电子邮件地址,以便您可以将您的问题发送到我们的票务系统。
  • 这类问题并不真正属于 Stack Overflow,因为它不是编程问题。你应该看看area51.stackexchange.com/proposals/25439/magento,看看如何找到一个合适的地方来提出这些问题

标签: php caching cookies magento varnish


【解决方案1】:

如何在 Varnish 中缓存 Magento(理论) - 这有 2 个组件

1) 静态资产(例如图像、CSS、JS)——这是一种简单的常见模式,涉及检测属于该类别的请求并设置缓存时间(或依赖于源服务器发送的缓存时间) ) Example of this in gist form

2) HTML 文档 - 这是一个好的 Magento 解决方案中复杂得多的部分。 在 Varnish 中缓存 HTML 文档以提高 Magento 性能至关重要。 HTML 文档生成是 Magento 服务器最昂贵(耗时)的事情。

缓存 HTML 文档的挑战来自个性化内容。

个性化内容和 HTML 文档

Magento 和所有其他电子商务网站通过会话管理特定用户的状态。会话是该特定用户在您网站上的状态的记录。 这包括以下内容: “Hello Bob” - 在页面顶部 “购物车中的 4 样东西” - 每个页面上购物车的状态

这些是不能在用户之间共享的项目,如果发生这种情况会导致严重问题(我们称之为“会话泄漏”)。

如果 HTML 页面包含有关个人身份和购物车中物品的个性化信息,我们如何缓存 HTML 页面?

有两种主要方法可以实现这一点: 在页面加载后通过附加请求加载页面的个性化元素 这里常见的实现方式是使用AJAX请求个性化的页面元素 利用一种技术将 HTML 文档的组件标记为可缓存和其他不可缓存(或不可在用户之间共享)。 Varnish 支持一种称为 ESI(Edge Side Includes)的技术,该技术允许对 HTML 文档的不同部分进行不同的缓存。

您的 Varnish 实施策略必须考虑用户个性化。

Varnish 的实现选项

Magento 1.X - 在 Magento 版本 1 中缓存 HTML 文档的最广泛使用的方法是名为 Magento Turpentine 的开源产品(由 Nexus 提供)。 这是一个已安装的插件(通过 Magento Connect),它会自动将 ESI 标签添加到您的 HTML 文档中,以便 Varnish 可以缓存这些资源。 Magento Turpentine install / guide

Magento 2.X - 最新版本的 Magento(目前处于测试阶段)支持 Varnish 作为其在生产中用于 HTML 缓存的推荐解决方案。这是个好消息,Varnish 是 Magento 推荐的选项,它可以开箱即用,以提高您的网站速度。

如何让 Varnish 和 Magento 正常工作

部署是一回事,一旦您实施了 Varnish Magento 解决方案并开始工作,接下来的步骤就是了解其性能如何。逐个请求获取有关缓存命中率和详细日志的指标可能是一项挑战,因为它涉及部署一系列额外的基础设施(或被卡在一次性手动收集日志)。

我们最近构建了这个基础架构,以在云中将 Varnish 作为服务运行(具有完整的日志/指标)-www.section.io-除此之外,这可能是您在 Varnish 和 Magento 项目中取得实际成功的最重要因素需要不断调整您的实现以管理诸如 url 中不同的查询字符串之类的事情(您好 google 分析“gclid”!),这可以显着降低您的缓存命中率

【讨论】:

    【解决方案2】:

    如果您使用 Varnish 3.0,您可能需要更改您的 .vcl 配置。这是我在 magento 和 varnish 3 中使用的:

        # This is a basic VCL configuration file for varnish.  See the vcl(7)
    # man page for details on VCL syntax and semantics.
    # 
    # Default backend definition.  Set this to point to your content
    # server.
    # 
     backend default {
        .host = "127.0.0.1";
        .port = "8080";
     }
    
    acl trusted {
        "127.0.0.1";
        "127.0.1.1";
        # Add other ips that are allowed to purge cache
    }
    
    # 
    # http://www.varnish-cache.org/docs/2.1/tutorial/vcl.html#vcl-recv
    # @param req    Request object
    sub vcl_recv {
        if (req.http.x-forwarded-for) {
            set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
        }
        else {
            set req.http.X-Forwarded-For = client.ip;
        }
    
        if (req.request == "PURGE") {
            # Allow requests from trusted IPs to purge the cache
            if (!client.ip ~ trusted) {
               error 405 "Not allowed.";
            }
            ban("req.url ~ " + req.url);
            error 200 "Ok"; #We don't go to backend 
            #return(lookup); # @see vcl_hit
        }
    
        if (req.request != "GET" &&
           req.request != "HEAD" &&
           req.request != "PUT" &&
           req.request != "POST" &&
           req.request != "TRACE" &&
           req.request != "OPTIONS" &&
           req.request != "DELETE") {
             /* Non-RFC2616 or CONNECT which is weird. */
             return (pipe);
        }
    
         # Cache only GET or HEAD requests
         if (req.request != "GET" && req.request != "HEAD") {
             /* We only deal with GET and HEAD by default */
             return (pass);
         }
    
        # parse accept encoding rulesets to normalize
        if (req.http.Accept-Encoding) {
            if (req.http.Accept-Encoding ~ "gzip") {
                set req.http.Accept-Encoding = "gzip";
            } elsif (req.http.Accept-Encoding ~ "deflate") {
                set req.http.Accept-Encoding = "deflate";
            } else {
                # unkown algorithm
                remove req.http.Accept-Encoding;
            }
        }
    
         # Rules for static files
         if (req.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css|gz|rar|txt|bzip|pdf)(\?.*|)$") {
            set req.http.staticmarker = "1";
            unset req.http.Cookie;
    
            return (lookup);
        }
    
        # Don't cache pages for Magento Admin
        # FIXME: change this rule if you use custom url in admin
        if (req.url ~ "^/(index.php/)?admin") {
            return(pass);
        }
    
        # Don't cache checkout/customer pages, product compare
      #  if (req.url ~ "^/(index.php/)?(checkout|customer|catalog/product_compare|wishlist)") {
      #      return(pass);
      #  }
        # Don't cache checkout/customer pages, product compare
        if (req.url ~ "/(checkout|customer|catalog/product_compare|wishlist)/") {
            return(pass);
        }
    
    
        # Don't cache till session end
        if (req.http.cookie ~ "nocache_stable") {
            return(pass);
        }
    
        # Unique identifier witch tell Varnish use cache or not
        if (req.http.cookie ~ "nocache") {
            return(pass);
        }
    
        # Remove cookie 
        unset req.http.Cookie;
        set req.http.magicmarker = "1"; #Instruct varnish to remove cache headers received from backend
        return(lookup);
     }
    
    
    sub vcl_pipe {
    #     # Note that only the first request to the backend will have
    #     # X-Forwarded-For set.  If you use X-Forwarded-For and want to
    #     # have it set for all requests, make sure to have:
    #     # set req.http.connection = "close";
    #     # here.  It is not set by default as it might break some broken web
    #     # applications, like IIS with NTLM authentication.
         return (pipe);
    }
    
    #sub vcl_pass {
    #     return (pass);
    #}
    
    #sub vcl_hash {
    #     set req.hash += req.url;
    #     if (req.http.host) {
    #         set req.hash += req.http.host;
    #     } else {
    #         set req.hash += server.ip;
    #     }
    #     return (hash);
    # }
    
    
    # Called after a cache lookup if the req. document was found in the cache.
    sub vcl_hit {
        if (req.request == "PURGE") {
            ban_url(req.url);
            error 200 "Purged";
        }
    
        #
        # ATTENTION!! I had to comment this to make it work on vernish 3.0!!!!
        # error message:
        # Symbol not found: 'obj.cacheable' (expected type BOOL):
        #
        # I'm not sure about it, please check!!!
        #
        #if (!obj.cacheable) {
        #    return (pass);
        #}
    
    
        return (deliver);
    }
    
    # Called after a cache lookup and odc was not found in cache.
    sub vcl_miss {
        if (req.request == "PURGE"){
            error 200 "Not in cache";
        }
        return (fetch);
    }
    
    # Called after document was retreived from backend
    # @var req      Request object.
    # @var beresp   Backend response (contains HTTP headers from backend)
    sub vcl_fetch {
        set req.grace = 30s;
    
        # Current response should not be cached
        if(beresp.http.Set-Cookie ~ "nocache=1") {
            return (deliver);
        }
    
        # Flag set when we want to delete cache headers received from backend
        if (req.http.magicmarker){
            unset beresp.http.magicmarker;
            unset beresp.http.Cache-Control;
            unset beresp.http.Expires;
            unset beresp.http.Pragma;
            unset beresp.http.Cache;
            unset beresp.http.Server;
            unset beresp.http.Set-Cookie;
            unset beresp.http.Age;
    
            # default ttl for pages
            set beresp.ttl = 1d;
        }
        if (req.http.staticmarker) {
            set beresp.ttl = 30d; # static file cache expires in 30 days
            unset beresp.http.staticmarker;
            unset beresp.http.ETag; # Removes Etag in case we have multiple frontends
        }
    
        return (deliver);
    }
    
    # Called after a cached document is delivered to the client.
    sub vcl_deliver {
        if (obj.hits > 0) {
            set resp.http.X-Cache = "HIT ("+obj.hits+")";
        } else {
            set resp.http.X-Cache = "MISS";
            #    set resp.http.X-Cache-Hash = obj.http.hash;
        }
        return (deliver);
    }
    # 
    # sub vcl_error {
    #     set obj.http.Content-Type = "text/html; charset=utf-8";
    #     synthetic {"
    # <?xml version="1.0" encoding="utf-8"?>
    # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    #  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    # <html>
    #   <head>
    #     <title>"} obj.status " " obj.response {"</title>
    #   </head>
    #   <body>
    #     <h1>Error "} obj.status " " obj.response {"</h1>
    #     <p>"} obj.response {"</p>
    #     <h3>Guru Meditation:</h3>
    #     <p>XID: "} req.xid {"</p>
    #     <hr>
    #     <address>
    #        <a href="http://www.varnish-cache.org/">Varnish cache server</a>
    #     </address>
    #   </body>
    # </html>
    # "};
    #     return (deliver);
    # }
    

    【讨论】:

      【解决方案3】:

      我认为这解释了我们如何在 magento 中使用清漆

      如果您使用 aoe_static 模块和我为 varnish 3 定制的 vcl,它会清除缓存页面响应中的 cookie。它应该在 vcl fetch 中执行此操作。然后可以从加载动态内容的较小的 ajax 响应中设置 cookie。这会维护您的会话、购物车等。此 ajax 响应可以在 vcl 恢复中“管道”化。

      我在执行此操作时没有遇到任何问题,但没有在生产站点上尝试过。

      动态块必须通过布局 xml 替换为占位符。如果您喜欢这些替代品,则可能是清漆边缘包含或自定义 ajax 实现。

      当从 aoe_static(或您喜欢的任何类型的 ajax 方法)加载动态内容时,请记住您仍然可以使用 magentos 布局系统,例如为您的 ajax 调用创建一个句柄,其中包含要呈现的嵌套块。

      如果您使用 aoe_static 模块,您会注意到调用了 loadLayout,但请记住传递给该 loadLayout 的句柄。它与您所在页面的布局请求不同,但它确实为您提供了默认句柄。

      另一个问题是库存水平。当产品没有足够的库存添加到购物车时,它仍会显示在产品列表中,并作为可配置和分组产品的选项。

      您可能可以使用观察器 - cataloginventory_stock_item_save_after - 检查库存水平(我没有检查过这个)。然后可以根据产品的 url 清除缓存。获取产品将出现的类别网址并同时清除这些网址非常容易。

      如果您想从观察者那里看到一个简单的实现,phoenix 模块有方法可以执行这些类型的清除。

      但是如何处理分层的导航 url 比较棘手。您需要预先存储应用程序使用基本类别列表 url 作为键提供的查询字符串参数,然后在观察者中读取并清除这些 url。这种查询字符串参数的存储在发送之前使用响应很容易,使用正则表达式检查请求对象并使用逗号分隔记录查询字符串。

      我认为当前的模块都没有处理分层导航的库存水平是错误的?

      我认为开源社区需要一个好的完成的清漆模块,因为所有其他模块都缺乏。就我个人而言,我计划仅将付费整页缓存与负载平衡服务器一起使用,并且可能使用清漆来捕获图像和 css 请求。除非有人想联合起来进行适当的 varnish 实施,或者如果可以将工作添加到更好地解决所有这些问题的开源实施中,我很乐意为您的网站提供帮助。

      查看此问题以了解有关您将面临此问题的问题的更多详细信息 - magento open source full page cache

      【讨论】:

      • 你应该使用正确的写作,句子的开头大写
      • 我确实应该这样做。如果有人想了解有关我提到的任何事情的实施的更多细节,请询问,我很乐意提供帮助(也许我什至会发现错误)。但我输入了很多,停止输入大写字母是不行的。对不起。但是感谢您的帮助,我一开始并没有注意到您已修复它大声笑
      【解决方案4】:

      http://moprea.ro/2011/may/6/magento-performance-optimization-varnish-cache-3/ 描述了使用 varnish 启用全页缓存的 Magento 扩展。此扩展依赖于在 github 上发布的 Varnish 配置。

      这些是已经实现的功能:

      1. 可行的清漆配置
      2. 使用 Varnish(一种超快速缓存 HTTP 反向代理)启用整页缓存。
      3. Varnish 服务器可在 Admin 中配置,位于 System / Configuration / General - Varnish Options 下
      4. 在保存产品、类别和 CMS 页面时自动清除(仅)缓存页面。
      5. 在 Magento Admin 中的 System / Cache Management 下添加新的缓存类型,并提供停用缓存和刷新缓存的可能性。
      6. 在保存类别导航并且需要刷新清漆缓存以便更新所有页面的菜单时通知管理员用户。
      7. 为购物车中有产品或已登录等的用户自动关闭清漆缓存)
      8. 提供默认清漆配置,以便模块可用。 截图:https://github.com/madalinoprea/magneto-varnish/wiki

      【讨论】:

        【解决方案5】:

        我假设这是 Magento 发送给所有用户的会话 cookie - Varnish + Redmine 也有类似的问题。

        Varnish 不缓存您的页面的原因是,默认情况下,它只缓存确定安全的内容 - 使用 cookie 的用户通常会在给定页面加载时看到不同的内容,例如,如果他们已登录,那么可能他们的用户名位于每个页面的顶部,因此无法缓存页面†。

        然而,许多框架也将会话 cookie 提供给未登录的用户。恐怕我根本不了解 Magento,所以我无法预测忽略此 cookie 的后果 - 在 Redmine 上,忽略 cookie 意味着用户无法登录,并且所有表单都停止工作(因为他们不再拥有 CSRF令牌)。

        如果可以的话,从 Magento 方面解决这个问题可能会更好 - Varnish 将监听上游的标头以确定可以缓存的内容等。

        如果你不能,那么你可以通过 Varnish 的配置来缓解它。您需要确保 Set-Cookie 标头不是从任何缓存命中发送的,并且您还需要在请求该 cookie 无效的页面上删除客户端的 cookie。这意味着您将需要例外情况,例如登录屏幕或任何需要您登录的页面(除非 Magento 在您登录后设置单独的 cookie,这会使事情变得容易得多)。

        Varnish 文档(我强烈推荐作为资源)有几页关于提高命中率的内容,包括专门针对 dropping cookies on some pages and not others 的一页。

        † 有一个例外,如果您使用的是edge side includes

        【讨论】:

          【解决方案6】:

          我们开发了一个名为 PageCache 的模块,由 Varnish 提供支持,它通过提供经过良好测试的 Varnish 配置文件 (VCL) 和一个紧密集成的 Magento 模块,该模块具有大量选项来控制 Magento 的 Varnish 权限,从而使 Magento 和 Varnish 能够流畅地一起运行后端。在 Magento Connect 上查看:

          http://www.magentocommerce.com/magento-connect/Phoenix/extension/6322/varnish_cache

          【讨论】:

          • 我对这个模块很感兴趣。 Magento Connect 页面上的链接仅链接到自身。我可以在哪里联系您讨论该模块?
          【解决方案7】:

          http://moprea.ro/2011/feb/16/magento-performance-optimization-varnish-cache-2/

          不确定是否有帮助,但我偶然发现了这一点。

          我之前实际上已经尝试过让清漆起作用,但我失败了。我建议您在尝试 varnish 之前先获得 APC + Memcached + tmpfs 会话/缓存。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-08-23
            • 2017-07-11
            • 1970-01-01
            • 2021-01-29
            • 2015-08-19
            • 2021-03-19
            • 1970-01-01
            • 2018-02-12
            相关资源
            最近更新 更多