V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
RiESA
V2EX  ›  问与答

一个 Varnish 服务如何对运行在一个 nginx 上的不同网站分开缓存?

  •  
  •   RiESA · 2020-02-14 00:04:03 +08:00 · 1161 次点击
    这是一个创建于 1736 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,第一次使用配置 Varnish,发现把两个网站都接入 Varnish 之后,缓存会混淆,极有可能是我配置的问题

    nginx 运行在 80 端口 Varnish 运行在 8080 端口,并且监听 nginx 所在的 80 端口,并且目前两个网站都是 80 端口

    配置文件我只写了一个 backend

    default.vcl

    vcl 4.0;

    backend default {

    .host = "127.0.0.1";
    
    .port = "80";
    

    }

    ...............后略

    我个人思考了一下,是不是我想问题太简单粗暴了,我以为 nginx 已经配置好的情况下,通过 Varnish,会根据 nginx 的配置把不同的站点分开对待,没想到缓存在一起了

    当然也和我没配置写对有关,是不是应该把其中的一个网站的端口改成别的,例如 81,然后加多一个 backend ?例如

    vcl 4.0;

    backend default {

    .host = "127.0.0.1";
    
    .port = "80";
    

    } backend default2 {

    .host = "127.0.0.1";
    
    .port = "81";
    

    }

    但是我又不太确定这样是否正确,单单把端口分开可以解决这种情况吗?还是需要其他的配置让 Varnish 区分开两个网站的缓存,希望有经验的大佬解答一下,第一次接触这个两眼一抹黑

    12 条回复    2020-02-15 14:27:15 +08:00
    RiESA
        1
    RiESA  
    OP
       2020-02-14 08:29:58 +08:00 via Android
    打捞一下自己 orz
    Taosky
        2
    Taosky  
       2020-02-14 09:28:01 +08:00
    这个 Varnish 是放在 nginx 前面做缓存加速? 看不懂帮顶。
    sleepm
        3
    sleepm  
       2020-02-14 09:36:27 +08:00 via Android
    就是需要多个 backend
    先是 nginx 转发给 varnish
    然后 varnish 根据规则再转发给后面不同端口的 backend

    可以参考
    https://xn--vkuk.org/blog/%e6%8a%98%e8%85%benginx-varnish-apache2-https%e6%95%b4%e7%ab%99%e5%b0%8f%e8%ae%b0/
    现在想想最后面不同的端口也可以由 nginx 提供
    现在不用 varnish 了。。就是因为缓存太变态了。。搞个啥都得重启清下缓存,要不怀疑人生,哈哈
    RiESA
        4
    RiESA  
    OP
       2020-02-14 11:35:57 +08:00 via Android
    @sleepm 好的谢谢,我研究一下
    RiESA
        5
    RiESA  
    OP
       2020-02-14 11:38:51 +08:00 via Android
    @sleepm 我是直接 访问>varnish>nginx 这样的结构,前面并没有多一层 nginx,这样的话单纯区分两个站的端口可以解决缓存混淆问题吗?
    sleepm
        6
    sleepm  
       2020-02-14 11:47:06 +08:00 via Android
    主要是 varnish 的规则
    我把 nginx 放前面就是为了 https,那会 varnish 还不支持 https
    RiESA
        7
    RiESA  
    OP
       2020-02-14 12:32:22 +08:00 via Android
    @sleepm 好的,谢谢
    RiESA
        8
    RiESA  
    OP
       2020-02-15 10:43:27 +08:00
    @sleepm 我又来请教您了,我昨晚尝试配置了一下多站点,但是出现了一个很奇怪的问题,站点 A,也就是第一个 backend 完全正常,第二个 backend,站点 B 会出现 404 的情况,但是又不是完全 404 强刷一下页面可以出来,但是没点几下又 404 这种,
    目前的访问流程是:CDN>varnish>nginx,不排除是我设置写的有问题,不知道能不能帮我看看,谢谢
    RiESA
        9
    RiESA  
    OP
       2020-02-15 10:46:20 +08:00
    vcl 4.0;
    # set default backend if no server cluster specified
    backend default {
    .host = "127.0.0.1";
    .port = "80";
    }
    backend test {
    .host = "127.0.0.1";
    .port = "81";
    }


    # access control list for "purge": open to only localhost and other local nodes
    acl purge {
    "127.0.0.1";
    }

    # vcl_recv is called whenever a request is received
    sub vcl_recv {
    # Serve objects up to 2 minutes past their expiry if the backend
    # is slow to respond.
    # set req.grace = 120s;
    if(req.http.host ~ "a.com"){
    set req.http.host = "a.com";
    set req.backend_hint = default;
    }
    if(req.http.host ~ "b.com"){
    set req.http.host = "b.com";
    set req.backend_hint = blog;
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    set req.backend_hint= default;

    # This uses the ACL action called "purge". Basically if a request to
    # PURGE the cache comes from anywhere other than localhost, ignore it.
    if (req.method == "PURGE") {
    if (!client.ip ~ purge) {
    return (synth(405, "Not allowed."));
    } else {
    return (purge);
    }
    }

    # Pass any requests that Varnish does not understand straight to the backend.
    if (req.method != "GET" && req.method != "HEAD" &&
    req.method != "PUT" && req.method != "POST" &&
    req.method != "TRACE" && req.method != "OPTIONS" &&
    req.method != "DELETE") {
    return (pipe);
    } /* Non-RFC2616 or CONNECT which is weird. */

    # Pass anything other than GET and HEAD directly.
    if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
    } /* We only deal with GET and HEAD by default */

    # Pass requests from logged-in users directly.
    # Only detect cookies with "session" and "Token" in file name, otherwise nothing get cached.
    if (req.http.Authorization || req.http.Cookie ~ "session" || req.http.Cookie ~ "Token") {
    return (pass);
    } /* Not cacheable by default */

    # normalize Accept-Encoding to reduce vary
    if (req.http.Accept-Encoding) {
    if (req.http.User-Agent ~ "MSIE 6") {
    unset req.http.Accept-Encoding;
    } elsif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elsif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    unset req.http.Accept-Encoding;
    }
    }

    return (hash);
    }


    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";

    # This is otherwise not necessary if you do not do any request rewriting.

    set req.http.connection = "close";
    }

    # Called if the cache has a copy of the page.
    sub vcl_hit {
    if (!obj.ttl > 0s) {
    return (pass);
    }

    # Force lookup if the request is a no-cache request from the client.
    if (req.http.Cache-Control ~ "no-cache") {
    return (miss);
    }
    }

    # Called after a document has been successfully retrieved from the backend.
    sub vcl_backend_response {
    # set minimum timeouts to auto-discard stored objects
    set beresp.grace = 120s;

    if (beresp.ttl < 48h) {
    set beresp.ttl = 48h;
    }

    if (!beresp.ttl > 0s) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    if (beresp.http.Set-Cookie) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # if (beresp.http.Cache-Control ~ "(private|no-cache|no-store)") {
    # set beresp.uncacheable = true;
    # return (deliver);
    # }

    if (beresp.http.Authorization && !beresp.http.Cache-Control ~ "public") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    return (deliver);
    }
    RiESA
        10
    RiESA  
    OP
       2020-02-15 10:47:56 +08:00
    更正一下,目前是下面这个才对,上面那个忘记改一个地方了
    RiESA
        11
    RiESA  
    OP
       2020-02-15 10:49:25 +08:00
    vcl 4.0;
    # set default backend if no server cluster specified
    backend default {
    .host = "127.0.0.1";
    .port = "80";
    }
    backend test {
    .host = "127.0.0.1";
    .port = "81";
    }


    # access control list for "purge": open to only localhost and other local nodes
    acl purge {
    "127.0.0.1";
    }

    # vcl_recv is called whenever a request is received
    sub vcl_recv {
    # Serve objects up to 2 minutes past their expiry if the backend
    # is slow to respond.
    # set req.grace = 120s;
    if(req.http.host ~ "a.cn"){
    set req.http.host = "a.cn";
    set req.backend_hint = default;
    }
    if(req.http.host ~ "b.cn"){
    set req.http.host = "b.cn";
    set req.backend_hint = test;
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    set req.backend_hint= default;

    # This uses the ACL action called "purge". Basically if a request to
    # PURGE the cache comes from anywhere other than localhost, ignore it.
    if (req.method == "PURGE") {
    if (!client.ip ~ purge) {
    return (synth(405, "Not allowed."));
    } else {
    return (purge);
    }
    }

    # Pass any requests that Varnish does not understand straight to the backend.
    if (req.method != "GET" && req.method != "HEAD" &&
    req.method != "PUT" && req.method != "POST" &&
    req.method != "TRACE" && req.method != "OPTIONS" &&
    req.method != "DELETE") {
    return (pipe);
    } /* Non-RFC2616 or CONNECT which is weird. */

    # Pass anything other than GET and HEAD directly.
    if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
    } /* We only deal with GET and HEAD by default */

    # Pass requests from logged-in users directly.
    # Only detect cookies with "session" and "Token" in file name, otherwise nothing get cached.
    if (req.http.Authorization || req.http.Cookie ~ "session" || req.http.Cookie ~ "Token") {
    return (pass);
    } /* Not cacheable by default */

    # normalize Accept-Encoding to reduce vary
    if (req.http.Accept-Encoding) {
    if (req.http.User-Agent ~ "MSIE 6") {
    unset req.http.Accept-Encoding;
    } elsif (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
    } elsif (req.http.Accept-Encoding ~ "deflate") {
    set req.http.Accept-Encoding = "deflate";
    } else {
    unset req.http.Accept-Encoding;
    }
    }

    return (hash);
    }


    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";

    # This is otherwise not necessary if you do not do any request rewriting.

    set req.http.connection = "close";
    }

    # Called if the cache has a copy of the page.
    sub vcl_hit {
    if (!obj.ttl > 0s) {
    return (pass);
    }

    # Force lookup if the request is a no-cache request from the client.
    if (req.http.Cache-Control ~ "no-cache") {
    return (miss);
    }
    }

    # Called after a document has been successfully retrieved from the backend.
    sub vcl_backend_response {
    # set minimum timeouts to auto-discard stored objects
    set beresp.grace = 120s;

    if (beresp.ttl < 48h) {
    set beresp.ttl = 48h;
    }

    if (!beresp.ttl > 0s) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    if (beresp.http.Set-Cookie) {
    set beresp.uncacheable = true;
    return (deliver);
    }

    # if (beresp.http.Cache-Control ~ "(private|no-cache|no-store)") {
    # set beresp.uncacheable = true;
    # return (deliver);
    # }

    if (beresp.http.Authorization && !beresp.http.Cache-Control ~ "public") {
    set beresp.uncacheable = true;
    return (deliver);
    }

    return (deliver);
    }
    sleepm
        12
    sleepm  
       2020-02-15 14:27:15 +08:00
    规则没问题,那估计就是你的 cdn 设置的回源有问题
    看看回源设置,不行的话撤了 cdn 试试,如果撤了没问题,那就是 cdn 的设置了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1859 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:38 · PVG 00:38 · LAX 08:38 · JFK 11:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.