Json   发布时间:2022-04-22  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用varnish 4代理处理jsonp接口大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

原文地址: http://blog.wangjunfeng.com/a...

背景

使用varnish是一个很不错的http加速方案,挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。然而varnish认情况下是以url进行hash,来标识缓存,所以对于jsonp这种带有callBACk参数的请求,每一次callBACk都不一样,很可能会生成大量重复数据,占用内存空间,浪费资源。最近就遇到了这个问题,好在这个还是有解决办法的。

实现原理

其实jsonp很简单,就是json数据加一个callBACk和一对括号就可以了,所以只要我们取到没有callBACk的json数据,并进行缓存,再把数据用标签包起来就可以了。是的,就是这么简单,但是如何实现呢?

其实实现起来也很简单,在varnish 4的VCL里面其实可以使用synthetic来组合数据,但是这个函数又只能在vcl_synth和vcl_BACkend_error内使用,其中vcl_synth是用来处理错误的,而vcl_BACkend_error是用来处理后端服务器错误,所以我们就必须先抛出错误,然后读取json数据,再进行拼接然后返回

这里拼接数据时还需要用到varnish的Edge Side Includes(ESI)。

代码示例

#
# This is an example VCL file for Varnish.
#
# It does not do anything by default,delegaTing control to the
# builTin VCl. The builTin VCL is called when there is no explicit
# return statement.
#
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/
# and https://www.varnish-cache.org/trac/wiki/VCLExamples for more examples.

# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;

# Default BACkend deFinition. Set this to point to your content server.

# 后端服务器
BACkend default {
    .host = "127.0.0.1";
    .port = "8000";
    .connect_timeout = 8s;
    .firsT_Byte_timeout = 8s;
    .between_bytes_timeout = 5s;
}

# varnish服务器
BACkend jsonp_template_BACkend {
  .host = "127.0.0.1";
  .port = "80";
}

sub vcl_recv {
    # 当地址是/JSONP-ESI-TEMPLATE时,则抛出760错误
    if (req.url == "/JSONP-ESI-TEMPLATE") {
        return (synth(760,"Json"));
    }
}

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    #
    # Typically you clean up the request here,removing cookies you don't need,# rewriTing the request,etc.
    if (req.method != "GET") {
        return (pass);
    }
    if (req.url ~ "callBACk=") {
        # 保存callBACk参数,后续拼装数据时会使用到
        set req.http.X-CallBACk = regsub(
            req.url,".*[\?&]callBACk=([\.A-Za-z0-9_]+).*","\1"
        );
        # 去除callBACk和_参数
        set req.http.X-ESI-Url = regsub(req.url,"&?callBACk=[\.A-Za-z0-9_]+","");
        set req.http.X-ESI-Url = regsub(req.http.X-ESI-Url,"&?_=[\.A-Za-z0-9_]+","\?$","\?&","?");
        # 设置后端请求地址
        set req.url = "/JSONP-ESI-TEMPLATE";
        # 设置请求后端服务器
        set req.BACkend_hint = jsonp_template_BACkend;
        return (pass);
    }
    return (hash);
}

sub vcl_BACkend_response {
    # 如果后端请求包含有X-ESI则启用X-ESI
    if (beresp.http.X-ESI) {
        unset beresp.http.X-ESI;
        set beresp.do_esi = true;
    }
}

sub vcl_BACkend_response {
    # X-JSONP-Server means we need to clean up the response a bit
    if (beresp.http.X-JSONP-Server) {
        unset beresp.http.X-JSONP-Server;
        set beresp.http.Server = "JSONP-Server";
    }
}

sub vcl_synth {
    # 处理760错误,这里设置相关参数,后续请求后端要用到
    if (resp.status == 760) {
        set resp.http.X-ESI = "1";
        set resp.http.X-JSONP-Server = "1";
        
        # 设置状态码为200
        set resp.status = 200;
        
        # 数据拼接,拼接后直接返回
        synthetic({"<esi:include />"} + {"/**/"} + req.http.X-CallBACk + {"(<esi:include src="} +  req.http.X-ESI-Url + {" />)"});
        return(deliver);
    }
}

sub vcl_BACkend_response {
    # Happens after we have read the response headers from the BACkend.
    #
    # Here you clean the response headers,removing silly Set-Cookie headers
    # and other mistakes your BACkend does.
    unset beresp.http.set-cookie;
    if (beresp.ttl <= 0s) {
        set beresp.ttl = 120s;
    }
    set beresp.do_gzip = true;
    return (deliver);
}

sub vcl_deliver {
    # Happens when we have all the pieces we need,and are about to send the
    # response to the client.
    #
    # you can do accounTing or modifying the final object here.
}

注意

原文地址: http://blog.wangjunfeng.com/a...

大佬总结

以上是大佬教程为你收集整理的使用varnish 4代理处理jsonp接口全部内容,希望文章能够帮你解决使用varnish 4代理处理jsonp接口所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。