我最近在工作中做一个设置,我有一个面向用户的 Nginx 服务,它将访问转发到运行在AWS Elastic Load Balancer (如你所知. ELB)上的一个服务。这本身似乎不是一个困难的任务,你只需要找到 ELB 的主机名,将 ngin x指向它,这样不就搞定了,对吧?
location / { proxy_pass http://service-1234567890.us-east-1.elb.amazonaws.com; }
测试没有问题,再正确设置一下防火墙/安全组配置,它就应该可以很好的工作了。几个小时之后,你可能会发现,服务不再工作了,尽管没有做任何改变。直接访问 ELB 端点是可以工作的,但访问 Nginx 却总是超时提醒。
为了弄清楚为什么服务突然中止,需要先了解一下 ELB 是如何工作的:
当你创建一个弹性负载均衡(Elastic Load Balancer),你将会得到 DNS 的返回记录,AWS 会告诉你所有在使用的访问服务。DNS 记录是一个轮询 DNS(round robin DNS)记录,它指向两个或更多的 IP 地址——这取决于你有多少可用的区域。DNS 记录被设置成 60 秒的存活时间(time to live),这意味几乎不会有记录缓存。
短 TTL 可以让 AWS 快速改变机器的运行负载,在不中断服务的情况下,不会有任何复杂的虚拟 IP 问题。这也是他们特别告诉你不要查找主机名和发送流量到其中某个 IP 地址的原因,那样的话,你的服务可能会在未来某个未定义的时间,IP 地址可能会停止为负载均衡工作。
问题在于,对于 Nginx 来说,当它读取到一个配置时,它就会立刻向 DNS 请求主机名,然后使用其结果,直到下次重新加载配置。在这段时间到来之前,ELB 可能改变 IP 地址,让你的 Nginx 把请求转发到一些不为你服务的地址。
解决这个问题的方式是为 Nginx Plus 付费,它添加 resolve 标记对在 upstream 分组上的服务器进行指示。那就是让 Nginx 骄傲的 DNS 对 TTL 的记录,偶尔按顺序重新处理记录,并取得服务器使用的更新列表。
为这个功能花费每年每服务器 $1.500,看起来花费很多。当然这是你希望得到 Nginx Plus 带来的其他功能,如果你不需要它们,这将会是一个昂贵的升级。
一个更加实惠的选择是写这样一个配置:
resolver 172.16.0.23; set $upstream_endpoint http://service-1234567890.us-east-1.elb.amazonaws.com; location / { proxy_pass $upstream_endpoint; }
它将会生效并且 Nginx 会遵循记录 DNS 记录的 TTL,万一一个请求进来,会重新解释它而且缓存的记录会过期。为什么会这样?
答案可以在 proxy_pass 指令文档结尾找到,它声明了:
<p>服务器名,端口以及传递的URI也可以使用变量被指定:</p> <pre class="code">proxy_pass http://$host$uri;
甚至像这样:
proxy_pass $request;
在这个案例中,服务器名会在所描述的 server groups 中被查找,如果没找到,会使用 resolver 来决定.
当我们给 proxy_pass 提供一个变量的时候,我们基本上是利用其改变行为,但这样确实需要我们在配置中指定一个 DNS resolver。例子里边用到的 DNS resolver应该能够在 AWS 上面跑在默认 VPC或者 EC2 中的所有服务器工作(适用)。你也可以随时查看 /etc/resolv.conf 找出哪些 AWS 为你的服务器提供并使用了哪些 DNS 服务器。
如果你在 Nginx 中设置的 Location 不只是 /,那么你需要注意到当给定一个变量作为参数时,proxy_pass 细微的改变行为。
先说重要的,快速概括 proxy_pass 如何在正常在操作中工作:
正常的表现行为
设想我们有一个 Nginx 配置包括这些:
location /foo/ { proxy_pass http://127.0.0.1:8080; }
当我们发送一个 /foo/bar/baz 的请求到这个站点,Nginx 会转发请求到 http://127.0.0.1:8000/foo/bar/baz。
location /foo/ { # Note the trailing slash ↓ proxy_pass http://127.0.0.1:8080/; }
Nginx 会在 Location 记录里边去掉部分指定的 URI,然后把剩下的部分传给 upstream 服务器。所以请求 /foo/bar/baz 会被转发到 http://127.0.0.1:8080/bar/baz。
改变行为
当我们使用一个变量作为 proxy_pass 的参数的时候,上面带有尾部斜杠的行为会改变。例如我们有这样的配置。
resolver 172.16.0.23; set $upstream_endpoint http://service-1234567890.us-east-1.elb.amazonaws.com/; location /foo/ { proxy_pass $upstream_endpoint; }
当我们向那个配置发送请求 /foo/bar/baz,转发请求将不会去到/并且不是预想中的 /bar/baz。
为此解决方案就是从 upstream 的 endpoint 去掉尾部斜杠,然后像这样手动重写:
resolver 172.16.0.23; set $upstream_endpoint http://service-1234567890.us-east-1.elb.amazonaws.com; location /foo/ { rewrite ^/foo/(.*) /$1 break; proxy_pass $upstream_endpoint; }
然后当你发送请求 /foo/bar/baz,upstream 会接受到我们想要的请求 /bar/baz。
これは、elb をアップストリーム サーバーとして設定する場合に適用されるだけでなく、アップストリーム サーバーとして nginx の DNS 構成を変更するすべての構成にも適用されることを知っておく必要があります。
これがあなたの役に立てば幸いです。何か提案がある場合、または単に私に連絡したい場合は、twitter Tenzer まで連絡してください。
プログラマーは残業しなければなりませんか?いいえ!
プログラマーが残業の犬や持ち帰りの顔という称号を取り除きたいと思っていることはわかっています。だから私たちはここにいます!
私たちはプログラマーが知識やスキルを共有できるアプリを作成しました。これはプログラマーの働き方を覆すことができると考えています
!
私たちは希望的観測だと言う人もいますが、私たちはそうは思いません。
私たちの希望的観測を非難する人々の顔を煽るために、私たちは今、
私たちの「脈動」を与えてくれるプログラマ業界の有力者を緊急に必要としています! 「診断料」が太っ腹!結局のところ、私たちはお金が足りないわけではない、ただ最善を尽くしたいだけです!
Quanquan Dictionaryによると、Niubiキャラクターとは、1,000人以上のグループメンバーを持つQQグループオーナー、
2,000人以上のフォロワーを持つTiebaオーナー、または10,000人以上のフォロワーを持つWeiboユーザーを指します。メンバー
として 2,000 件以上のトピック投稿をしたり、単一投稿の閲覧数が 2,000 件を超えるブロガーや、非常に幅広いつながりを持つサークル内の有名人などです。
基準を満たしていない将来の偉人たちに、私たちは涙ながらにこう言うことしかできません。いつかあなたが神になったら、私は生も死もあなたを頼りにします!
来ますか?まだ来ませんか?
サークル交流パスワード:1955246408(QQ)
http://www.bkjia.com/PHPjc/1048746.html