`

varnish实现设备检测

    博客分类:
  • web
 
阅读更多

原文出处:https://www.varnish-cache.org/docs/3.0/tutorial/devicedetection.html

 

设备检测室根据用户请求的User-Agent来判断返回正确的内容。

 

这样的例子包括对于手机用户这样小屏幕并且高延迟网络发送压缩的文件,或者提供客户端能辨认的流媒体编码格式。

 

有几种策略来处理这样的用户请求:1)redirect到其他的URL. 2) 对于特殊的用户使用不同的后台;3)改变后台的请求以保证后台发送处理过的内容。

 

To make the examples easier to understand, it is assumed in this text that all the req.http.X-UA-Device header is present and unique per client class that content is to be served to.

Setting this header can be as simple as:

sub vcl_recv {
    if (req.http.User-Agent ~ "(?i)iphone" {
        set req.http.X-UA-Device = "mobile-iphone";
    }
}

There are different commercial and free offerings in doing grouping and identifiying clients in further detail than this. For a basic and community based regular expression set, see https://github.com/varnish/varnish-devicedetect/ .

Serve the different content on the same URL

The tricks involved are: 1. Detect the client (pretty simple, just include devicedetect.vcl and call it) 2. Figure out how to signal the backend what client class this is. This includes for example setting a header, changing a header or even changing the backend request URL. 3. Modify any response from the backend to add missing Vary headers, so Varnish' internal handling of this kicks in. 4. Modify output sent to the client so any caches outside our control don't serve the wrong content.

All this while still making sure that we only get 1 cached object per URL per device class.

Example 1: Send HTTP header to backend

The basic case is that Varnish adds the X-UA-Device HTTP header on the backend requests, and the backend mentions in the response Vary header that the content is dependant on this header.

Everything works out of the box from Varnish' perspective.

VCL:

sub vcl_recv {
    # call some detection engine that set req.http.X-UA-Device
}
# req.http.X-UA-Device is copied by Varnish into bereq.http.X-UA-Device

# so, this is a bit conterintuitive. The backend creates content based on
# the normalized User-Agent, but we use Vary on X-UA-Device so Varnish will
# use the same cached object for all U-As that map to the same X-UA-Device.
#
# If the backend does not mention in Vary that it has crafted special
# content based on the User-Agent (==X-UA-Device), add it.
# If your backend does set Vary: User-Agent, you may have to remove that here.
sub vcl_fetch {
    if (req.http.X-UA-Device) {
        if (!beresp.http.Vary) { # no Vary at all
            set beresp.http.Vary = "X-UA-Device";
        } elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
            set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
        }
    }
    # comment this out if you don't want the client to know your
    # classification
    set beresp.http.X-UA-Device = req.http.X-UA-Device;
}

# to keep any caches in the wild from serving wrong content to client #2
# behind them, we need to transform the Vary on the way out.
sub vcl_deliver {
    if ((req.http.X-UA-Device) && (resp.http.Vary)) {
        set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
    }
}

Example 2: Normalize the User-Agent string

Another way of signaling the device type is to override or normalize the User-Agent header sent to the backend.

For example

User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

becomes:

User-Agent: mobile-android

when seen by the backend.

This works if you don't need the original header for anything on the backend. A possible use for this is for CGI scripts where only a small set of predefined headers are (by default) available for the script.

VCL:

sub vcl_recv {
    # call some detection engine that set req.http.X-UA-Device
}

# override the header before it is sent to the backend
sub vcl_miss { if (req.http.X-UA-Device) { set bereq.http.User-Agent = req.http.X-UA-Device; } }
sub vcl_pass { if (req.http.X-UA-Device) { set bereq.http.User-Agent = req.http.X-UA-Device; } }

# standard Vary handling code from previous examples.
sub vcl_fetch {
    if (req.http.X-UA-Device) {
        if (!beresp.http.Vary) { # no Vary at all
            set beresp.http.Vary = "X-UA-Device";
        } elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
            set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
        }
    }
    set beresp.http.X-UA-Device = req.http.X-UA-Device;
}
sub vcl_deliver {
    if ((req.http.X-UA-Device) && (resp.http.Vary)) {
        set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
    }
}

Example 3: Add the device class as a GET query parameter

If everything else fails, you can add the device type as a GET argument.

The client itself does not see this classification, only the backend request is changed.

VCL:

sub vcl_recv {
    # call some detection engine that set req.http.X-UA-Device
}

sub append_ua {
    if ((req.http.X-UA-Device) && (req.request == "GET")) {
        # if there are existing GET arguments;
        if (req.url ~ "\?") {
            set req.http.X-get-devicetype = "&devicetype=" + req.http.X-UA-Device;
        } else {
            set req.http.X-get-devicetype = "?devicetype=" + req.http.X-UA-Device;
        }
        set req.url = req.url + req.http.X-get-devicetype;
        unset req.http.X-get-devicetype;
    }
}

# do this after vcl_hash, so all Vary-ants can be purged in one go. (avoid ban()ing)
sub vcl_miss { call append_ua; }
sub vcl_pass { call append_ua; }

# Handle redirects, otherwise standard Vary handling code from previous
# examples.
sub vcl_fetch {
    if (req.http.X-UA-Device) {
        if (!beresp.http.Vary) { # no Vary at all
            set beresp.http.Vary = "X-UA-Device";
        } elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
            set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
        }

        # if the backend returns a redirect (think missing trailing slash),
        # we will potentially show the extra address to the client. we
        # don't want that.  if the backend reorders the get parameters, you
        # may need to be smarter here. (? and & ordering)

        if (beresp.status == 301 || beresp.status == 302 || beresp.status == 303) {
            set beresp.http.location = regsub(beresp.http.location, "[?&]devicetype=.*$", "");
        }
    }
    set beresp.http.X-UA-Device = req.http.X-UA-Device;
}
sub vcl_deliver {
    if ((req.http.X-UA-Device) && (resp.http.Vary)) {
        set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
    }
}

Different backend for mobile clients

If you have a different backend that serves pages for mobile clients, or any special needs in VCL, you can use the X-UA-Device header like this:

backend mobile {
    .host = "10.0.0.1";
    .port = "80";
}

sub vcl_recv {
    # call some detection engine

    if (req.http.X-UA-Device ~ "^mobile" || req.http.X-UA-device ~ "^tablet") {
        set req.backend = mobile;
    }
}
sub vcl_hash {
    if (req.http.X-UA-Device) {
        hash_data(req.http.X-UA-Device);
    }
}

Redirecting mobile clients

If you want to redirect mobile clients you can use the following snippet.

VCL:

sub vcl_recv {
    # call some detection engine

    if (req.http.X-UA-Device ~ "^mobile" || req.http.X-UA-device ~ "^tablet") {
        error 750 "Moved Temporarily";
    }
}

sub vcl_error {
    if (obj.status == 750) {
        set obj.http.Location = "http://m.example.com" + req.url;
        set obj.status = 302;
        return(deliver);
    }
}
分享到:
评论

相关推荐

    EcomDev_Varnish, Magento的高级 varnish 实现.zip

    EcomDev_Varnish, Magento的高级 varnish 实现 varnish-集成Magento varnish Vache模块的实现系统要求PHP 5.3或者更高版本CE1.6. x-1.9.x/ee1.11.x-1.14.x varnish-安装可以使用 shell 脚本

    linux-varnish配置

    通过学习VCL(Varnish Configuration Language),你可以实现更复杂的逻辑,以适应不断变化的业务需求。 总结: Linux环境下的Varnish配置涉及到安装、配置文件的修改、启动和管理、监控以及性能优化等多个环节。...

    varnish实现原理

    ### Varnish 实现原理详解 #### 一、概述 Varnish Cache 是一款高性能的 HTTP 加速器,主要用于Web应用的加速与负载均衡。它通过缓存网页内容来减轻服务器的压力,提升网站的响应速度。Varnish 的设计目标是在不...

    varnish+lighttpd配置

    Varnish和Lighttpd是两个非常重要的开源Web服务器软件,它们在Web性能优化和负载均衡方面发挥着关键作用。Varnish作为一个高性能的HTTP缓存代理,常用于减轻后端服务器的压力,提高网站响应速度;而Lighttpd则是一款...

    Varnish权威指南(中文)

    《Varnish权威指南》是一本深度探讨Varnish缓存服务器技术的专业书籍,中文版的出版使得更多国内用户能够无障碍地学习和掌握这一高效的内容分发和加速工具。Varnish作为一个开源的HTTP加速器,它在Web性能优化领域...

    varnish-4.0.3.tar.gz

    在描述中提到的案例,挪威最大的在线报纸Verdens Gang将原有的12台Squid缓存服务器替换为3台Varnish服务器,不仅减少了硬件成本,还实现了更高的性能。这得益于Varnish的高效内存管理,它使用一种称为“存储桶”的...

    varnish安装包

    varnish 安装包 varnish 安装包 varnish 安装包 varnish 安装包

    Varnish 应用技术指南 V3.0 中文版

    4. Varnish的高可用性:通过集群部署和故障切换,Varnish可以实现高可用性和负载均衡。这使得即使在高流量情况下,服务也能保持稳定运行。 5. Varnish和CDN集成:Varnish可以与内容分发网络(CDN)结合使用,进一步...

    varnish-3.0.7.tgz 源码安装包

    Varnish是一个高性能的HTTP缓存...通过理解Varnish的工作原理和功能,你可以根据具体需求定制自己的缓存策略,实现高效的Web服务。在实际操作中,确保遵循最佳实践,如定期更新和维护,以确保Varnish的稳定性和安全性。

    Varnish网站加速缓存代理

    在反向代理,web加速方面,varnish已经有足够能力代替squid。挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。 2.作者:Poul-Henning Kamp是FreeBSD的内核开发者之一。

    varnish-magento

    Varnish-Magento是专门为Magento设计的一个模块,它允许Magento与Varnish无缝配合,实现更快的页面加载速度。 "supportdesk_nl-turpertine-formkey-workaround-574ff1851618" 这个文件名可能指的是一个针对特定问题...

    varnish.tar.bz2

    本资源包含Varnish的安装文件varnish-3.0.5-1.el6.x86_64.rpm 和varnish-libs-3.0.5-1.el6.x86_64.rpm,是搭建cdn的高性能HTTP加速器Varnish服务器必需的安装包,下载后解压即可,具体安装配置过程清移步我的博客

    varnish测试报告

    报告中提及了使用架构-mfs挂载测试设备,测试设备开启web服务供访问。mfs指的是全局分布式文件系统,通过挂载操作确保所有测试机器可以访问相同的数据集。 ### 测试工具Siege 在测试中,使用了Siege工具模拟随机...

    varnish-5.2.1.tar.gz

    Varnish是一个高性能的HTTP缓存和代理服务器,它的主要目标是加速网站的...通过下载并安装"varnish-5.2.1.tar.gz",你可以深入了解Varnish的运作机制,并将其部署到你的网站环境中,以实现更快速、更稳定的用户体验。

    squid、varnish、ngx_cache的性能测试对比报告

    本报告对比了Squid、Varnish和Ngx_cache三款缓存软件的性能。首先,从测试环境来看,本次测试所使用的Squid、Ngx_cache(也就是Varnish)、Nginx_cache均运行在具有单硬盘资源的服务器上,并为缓存分配了180G的存储...

Global site tag (gtag.js) - Google Analytics