根据请求的文件存在情况在 Varnish 后端之间进行选择的好方法

发布于 2024-12-13 02:10:50 字数 1056 浏览 2 评论 0原文

我在上面安装了 Apache2、nginx 和 Varnish。 Varnish 接收请求,确定它的后端(静态转到 nginx,动态转到 Apache),从后端获取响应并在需要时缓存它。

Apache 还可以生成缩略图。它使用一些特定的逻辑创建缩略图,这对于处理器来说是相当昂贵的。因此,Apache 将缩略图保存到磁盘,以便下次收到该缩略图的请求时 Varnish 可以将其直接重定向到 nginx。

这里有一个问题: Varnish 无法检查文件是否存在于文件系统中的某个位置,这就是为什么它不知道是否可以使用 nginx 后端或者 Apache 应该首先生成缩略图。

我目前采用的解决方法非常简单但丑陋:

  1. Varnish 接收缩略图请求;
  2. Varnish向nginx发送请求;
  3. 如果 nginx 找不到缩略图文件,它会回复 404 错误,并且 Varnish 将请求重定向到 Apache。

虽然这个算法看起来很简单,但实际上并非如此。 VCL 配置文件中需要进行以下实现:

  1. vcl_recv 中,始终假设缩略图存在,并且如果不是从某些特殊主机请求,则所有请求都必须重定向到 nginx;
  2. vcl_fetch 中捕获对象 HTTP 状态,如果它是 404 并且资源是缩略图,则将主机重写为特殊主机并重新启动进程:

VCL:

if( obj.status == 404 ) {
    if(req.url ~ "^thumb/") {
        set req.http.host = "thumb_generator.site.com";
        set req.url = regsub(req.url, "/thumb/(filename)", "thumb_gen.php?filename=\1");

        restart;
    }
}

也许有一些更好的方法来解决这个问题?我知道 Varnish 在 VCL 中支持 C,也许使用 C 代码检查文件是否存在更好?

I have the installation with Apache2, nginx and Varnish above them. Varnish receives the request, determines what backend is it for (static goes to nginx, dynamic goes to Apache), fetches the response from backend and caches it if needed.

Amongst other things Apache generates thumbnails. It creates thumbnails using some specific logic and it is quite expensive for processor. Thus Apache saves thumb to disk in order next time the request for this thumbnail will be received Varnish could redirect it directly to nginx.

And here is a problem: Varnish has no way to check if file exists somewhere in file system and that's why it don't know if nginx backend can be used or Apache should generate thumbnail first.

The workaround which I've currently adopted is quite simple but ugly:

  1. Varnish receives the request for thumbnail;
  2. Varnish sends request to nginx;
  3. If nginx can't find thumbnail file it replies with 404 error and Varnish redirects request to Apache.

While this algorithm seems to be simple in reality it is not. Following implementation is needed in VCL configuration file:

  1. In vcl_recv always assume that thumbnail exists and all request must be redirectedto nginx if it is not requested from some special host;
  2. In vcl_fetch catch object HTTP status and if it is 404 and resource is thumbnail than rewrite host to special one and restart the process:

VCL:

if( obj.status == 404 ) {
    if(req.url ~ "^thumb/") {
        set req.http.host = "thumb_generator.site.com";
        set req.url = regsub(req.url, "/thumb/(filename)", "thumb_gen.php?filename=\1");

        restart;
    }
}

Maybe there are some better ways to solve this problem? I know that Varnish supports C in VCL, maybe it is better to check file existence using C-code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甩你一脸翔 2024-12-20 02:10:50

好的,如果有人对解决方案感兴趣,我在 VCL 配置中找到了一个带有内联 C 的新解决方案。首先,我们必须添加一个函数来检查文件是否存在(在任何函数之外的文件顶部添加某个位置):

C{
#include  <stdio.h>
#include  <stdlib.h>

int exists (char *fname)
{
    FILE *file;
    if (file = fopen(fname, "r"))
    {
        fclose(file);
        return 1;
    }

    return 0;
}
}C

我知道有更好的方法来检查文件是否存在,但主要标头不可用在 VCL 中:/

然后在 vcl_recv 子例程中添加以下代码:

C{
    if( exists("/local/file/path") == 1 ) {
        VRT_l_req_backend(sp, VCL_conf.director[1]);
    } else {
        VRT_l_req_backend(sp, VCL_conf.director[2]);
    }
}C

就像一个魅力一样。

OK, if anyone is interested in solution I found a new one with inline C in VCL config. First of all we must add a function to check if file exists (add somewhere in the top of your file outside of any function):

C{
#include  <stdio.h>
#include  <stdlib.h>

int exists (char *fname)
{
    FILE *file;
    if (file = fopen(fname, "r"))
    {
        fclose(file);
        return 1;
    }

    return 0;
}
}C

I know that there are better ways to check if file exists, but major headers are not available inside VCL :/

Then in vcl_recv subroutine add following code:

C{
    if( exists("/local/file/path") == 1 ) {
        VRT_l_req_backend(sp, VCL_conf.director[1]);
    } else {
        VRT_l_req_backend(sp, VCL_conf.director[2]);
    }
}C

Works like a charm.

我只土不豪 2024-12-20 02:10:50

你正在使用 Varnish 来做一些它不适合的事情。它确实无法检查文件是否存在,因为它最初并不是为文件提供服务的。 Varnish 只是暂时将后端响应缓存在文件或内存存储中。

在这个设置中你真的需要清漆吗?让 nginx 检查文件是否存在或者将其转发到您的处理器不是更有意义吗?

You're using Varnish for something it wasn't made for. It indeed has no possibility to check if a file exists, because it was not made to serve files in the first place. Varnish just temporarily caches back-end responses in file or memory storage.

Do you really need varnish in this setup? Wouldn't it make a lot more sense to have nginx check if the file exists or else forward it to your processor?

青春有你 2024-12-20 02:10:50

为什么不使用 Nginx 的 try_files 指令在 404 上静默地将请求代理到 Apache?至少对我来说,这似乎更合乎逻辑。

Why not use Nginx's try_files directive to silently proxy the request to Apache on a 404? It would seem more logical, to me at least.

任性一次 2024-12-20 02:10:50

您可能会对 libvmod-utils 感兴趣。您将可以访问 WASD42 建议的内容,但直接使用 VMOD(更干净,并且应该应用最新的改进和建议)而不是内联 C。

Inline-C 很好,因为您可以做任何您需要的事情,但有时使用 VMOD 更干净,并且不会破坏您的 VCL 语言。

下面是 VCL 实现您的需求的示例:

import utils;

sub vcl_recv {
    if(req.url ~ "^/thumb/") {
        if (utils.exists("/srv/www/static/" + req.url)) {
            set req.backend = nginx;
        else {
            set bereq.url = regsub(req.url, "/thumb/(filename)", "thumb_gen.php?filename=\1");
            set req.backend = apache;
        }
    }
}

You probably will be interested in libvmod-utils. You will have access to what WASD42 suggested but directly with a VMOD (cleaner, and should have latest improvements & advices applied) instead of inline-C.

Inline-C is good because you can do whatever you need, but sometime having a VMOD is cleaner and will allow to not disrupt your VCL language.

Below an example of VCL implementing your needs :

import utils;

sub vcl_recv {
    if(req.url ~ "^/thumb/") {
        if (utils.exists("/srv/www/static/" + req.url)) {
            set req.backend = nginx;
        else {
            set bereq.url = regsub(req.url, "/thumb/(filename)", "thumb_gen.php?filename=\1");
            set req.backend = apache;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文