【问题标题】:Using varnish to cache heroku app使用 varnish 缓存 heroku 应用
【发布时间】:2013-12-16 23:02:53
【问题描述】:

我很久以前就设置了 varnish,我的一个后端设置为 host.herokuapp.com,效果很好。有一段时间,我可以使用基本的service varnish reload 命令更改设置并重新加载清漆配置。

现在当我尝试重新加载它时,我得到:

 * Reloading HTTP accelerator varnishd                                                                                    Command failed with error code 106
Message from VCC-compiler:
Backend host "myapp.herokuapp.com": resolves to multiple IPv4 addresses.
Only one address is allowed.
Please specify which exact address you want to use, we found these:
    154.129.225.36
    13.21.108.188
    50.10.185.176
    50.13.98.193
    54.125.177.29
    54.213.81.135
    107.25.192.112
    174.139.35.141
('/etc/varnish/backends.vcl' Line 39 Pos 27)
backend mobile  { .host = "myapp.herokuapp.com"; .port = "80"; }
--------------------------#####################-----------------
In backend specification starting at:
('/etc/varnish/backends.vcl' Line 39 Pos 1)
backend mobile  { .host = "myapp.herokuapp.com"; .port = "80"; }
#######---------------------------------------------------------------
Running VCC-compiler failed, exit 1
VCL compilation failed
Error: vcl.load 7ba71b44-c6b9-40e9-b0be-18f02bb5e9be /etc/varnish/default.vcl failed

由于 heroku 为其 dynos 使用动态 IP,IP 列表不断变化,因此将 IP 设置为后端是没有意义的。有什么办法可以解决这个问题吗?

【问题讨论】:

标签: caching heroku cloud cdn varnish


【解决方案1】:

我在 acquia 托管的服务器上遇到了几乎相同的问题。

解决它的一种方法是: - 通过 acquia 在单独的 vcl 中设置来自主机服务器的后端 IP - 构建一个 croned 脚本,如果后端发生变化,它会定期更新该 vcl - 重新启动清漆以将新后端投入生产

#!/usr/bin/python2.7

import socket
import subprocess
import re


#
# Do a nslookup and return the list of the IPs
#
def _nslookup(host):
    ips = ""
    ips = socket.getaddrinfo(host ,0,0,0,0)
    ip_list = []
    for result in ips:
        ip_list.append(result[-1][0])
    ip_list = list(set(ip_list))
    return ip_list

#
# Compare current backends with the list returned by nslookup
#
def _compare_backends_vcl(host_name, group_name):
    current_ips = []
    current_ips = _nslookup(host_name)

    # Get current backends
    current_backends = []
    list = subprocess.Popen("/usr/bin/varnishadm backend.list | grep " + group_name + " | awk '{print $1}'", shell=True, stdout=subprocess.PIPE)
    backend = ""
    for backend in list.stdout:
        current_backends.append(re.sub(r'^.*\((.*),.*,.*$\n', r'\1', backend))


# Due to varnish bug that is not removing backends (old ones are still declared in backend.list
# we are forced to add backends
# So the nslookup should be part of the current set of backends
# if set(current_ips).symmetric_difference(current_backends):
if set(current_ips).difference(current_backends):
    # List is present so difference exist
    print "_compare: We have to update " + group_name
    return True
else:
    return False

#
# Write the corresponding file
#
def _write_backends_vcl(host_name, group_name):
    TEMPLATE_NODE = '''backend %s {
\t.host = "%s";
\t.port = "80";
\t.probe = %s;
}'''


vcl_file = open("/etc/varnish/" + group_name + "_backends.vcl", 'w')
host_num = 1
hosts = _nslookup(host_name)
for host in hosts:
    vcl_file.write(TEMPLATE_NODE % (group_name + "_" + str(host_num), host, group_name + "_probe"))
    vcl_file.write("\n\n")
    host_num +=1
vcl_file.write("director " + group_name + "_default round-robin {\n")
for i in range(len(hosts)):
    node = group_name + "_" + str(i+1)
    vcl_file.write("\t{ .backend = %s; }\n" % node)
vcl_file.write("}\n")
vcl_file.close()

# Main
do_reload = ""
if _compare_backends_vcl("myhost.prod.acquia-sites.com", "MYHOST_CONFIG"):
    do_reload = True
    _write_backends_vcl("myhost.prod.acquia-sites.com", "MYHOST_CONFIG")

if do_reload:
    print "Reloading varnish"
    subprocess.Popen(['sudo', '/etc/init.d/varnish', 'reload'])
    exit(1)
else:
    # print "Everything is ok"
exit(0)

那么,对应的vcl看起来像:

backend MYHOST_CONFIG_1 {
    .host = "XX.XX.XX.XX";
    .port = "80";
    .probe = MYHOST_CONFIG_probe;
}

backend MYHOST_CONFIG_2 {
    .host = "XX.XX.XX.XX";
    .port = "80";
    .probe = MYHOST_CONFIG_probe;
}

director MYHOST_CONFIG_default round-robin {
    { .backend = MYHOST_CONFIG_1; }
    { .backend = MYHOST_CONFIG_2; }
}

您必须设置 MYHOST_CONFIG_probe 探针并将 MYHOST_CONFIG_default 设置为配置的导向器。 注意 varnish 存储了所有的后端,所以你必须定期重启它以清除有缺陷的服务器

【讨论】:

  • PajE,感谢您的回复。 heroku dynos 没有真正的 IP,它们位于 AWS 的 Elastic Load Balancer 之后,它每秒都会更改 IP。除非我看不出你的意思,否则这个解决方案是不可行的,因为我必须每秒运行一次脚本并经常重新加载/重新启动清漆。
【解决方案2】:

我今天也遇到了同样的问题。

所以,我在 3000 端口上安装了 nginx 服务器,并为 myapp.herokuapp.com 设置了一个 proxy_pass 服务器。

然后,将host="myapp.herokuapp.com" 和port="80" 修改为host="127.0.0.1" 和port="3000"。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    相关资源
    最近更新 更多