原文地址: http://www.oschina.net/translate/nginx-with-dynamic-upstreams

我最近在工作中做一个设置,我有一个面向用户的 Nginx 服务,它将访问转发到运行在AWS Elastic Load Balancer(如你所知. ELB)上的一个服务。这本身似乎不是一个困难的任务,你只需要找到 ELB 的主机名,将 ngin x指向它,这样不就搞定了,对吧?

location / {
    proxy_pass http://service-1234567890.us-east-1.elb.amazonaws.com;
}

测试没有问题,再正确设置一下防火墙/安全组配置,它就应该可以很好的工作了。几个小时之后,你可能会发现,服务不再工作了,尽管没有做任何改变。直接访问 ELB 端点是可以工作的,但访问 Nginx 却总是超时提醒。

ELB端启蒙

为了弄清楚为什么服务突然中止,需要先了解一下 ELB 是如何工作的:

当你创建一个弹性负载均衡(Elastic Load Balancer),你将会得到 DNS 的返回记录,AWS 会告诉你所有在使用的访问服务。DNS 记录是一个轮询 DNS(round robin DNS)记录,它指向两个或更多的 IP 地址——这取决于你有多少可用的区域。DNS 记录被设置成 60 秒的存活时间(time to live),这意味几乎不会有记录缓存。

短 TTL 可以让 AWS 快速改变机器的运行负载,在不中断服务的情况下,不会有任何复杂的虚拟 IP 问题。这也是他们特别告诉你不要查找主机名和发送流量到其中某个 IP 地址的原因,那样的话,你的服务可能会在未来某个未定义的时间,IP 地址可能会停止为负载均衡工作。

回到 Nginx

问题在于,对于 Nginx 来说,当它读取到一个配置时,它就会立刻向 DNS 请求主机名,然后使用其结果,直到下次重新加载配置。在这段时间到来之前,ELB 可能改变 IP 地址,让你的 Nginx 把请求转发到一些不为你服务的地址。

Nginx Plus

解决这个问题的方式是为Nginx Plus 付费,它添加 resolve 标记对在 upstream 分组上的服务器进行指示。那就是让 Nginx 骄傲的 DNS 对 TTL 的记录,偶尔按顺序重新处理记录,并取得服务器使用的更新列表。

为这个功能花费每年每服务器 $1.500,看起来花费很多。当然这是你希望得到 Nginx Plus 带来的其他功能,如果你不需要它们,这将会是一个昂贵的升级。

免费的选择

一个更加实惠的选择是写这样一个配置:

1
2
3
4
5
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 指令文档结尾找到,它声明了:

服务器名,端口以及传递的URI也可以使用变量被指定:

1
proxy_pass http://$host$uri;

甚至像这样:

1
proxy_pass $request;

在这个案例中,服务器名会在所描述的server groups 中被查找,如果没找到,会使用 resolver 来决定.

当我们给 proxy_pass 提供一个变量的时候,我们基本上是利用其改变行为,但这样确实需要我们在配置中指定一个 DNS resolver。例子里边用到的 DNS resolver应该能够在 AWS 上面跑在默认 VPC或者 EC2 中的所有服务器工作(适用)。你也可以随时查看 /etc/resolv.conf 找出哪些 AWS 为你的服务器提供并使用了哪些 DNS 服务器。

关于转发 URI 的 Caveat(警告)

如果你在 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 的参数的时候,上面带有尾部斜杠的行为会改变。例如我们有这样的配置。

1
2
3
4
5
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 去掉尾部斜杠,然后像这样手动重写:

1
2
3
4
5
6
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 做 upstream 服务器,它适用于配置所有在 nginx 做 upstream 服务器的修改 DNS 配置的情况。

希望这对你有用,如果你有任何建议或者只是想单纯联系我,用 twitter 联系吧 Tenzer

Nginx 的动态 upstreams的更多相关文章

  1. Consul+upsync+Nginx实现动态负载均衡 摘自https://blog.csdn.net/qq_29247945/article/details/80787014

    传统感念:每次修改完nginx配置文件,要重启nginx 动态感念:每次修改完nginx配置信息,不需要重启,nginx实时读取配置信息. Nginx: 反向代理和负载均衡 Consul:是用go编写 ...

  2. 基于Consul+Upsync+Nginx实现动态负载均衡

    基于Consul+Upsync+Nginx实现动态负载均衡 1.Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/l ...

  3. 《nginx 三》实现nginx的动态负载均衡——实战

    Http动态负载均衡 什么是动态负载均衡 传统的负载均衡,如果Upstream参数发生变化,每次都需要重新加载nginx.conf文件, 因此扩展性不是很高,所以我们可以采用动态负载均衡,实现Upst ...

  4. 【Nginx】基于Consul+Upsync+Nginx实现动态负载均衡

    一.Http动态负载均衡 什么是动态负载均衡 动态负载均衡实现方案 常用服务器注册与发现框架 二.Consul快速入门 Consul环境搭建 三.nginx-upsync-module nginx-u ...

  5. nginx实现动态/静态文件缓存(week4_day1_part2)-技术流ken

    nginx实现静态文件缓存实战 1.nginx静态文件缓存 如果要熟练使用nginx来实现文件的缓存,那下面的几个指令你必须要牢记于心 指令1:proxy_cache_path 作用:设置缓存数据的相 ...

  6. Upsync:微博开源基于Nginx容器动态流量管理方案

    Upsync:微博开源基于Nginx容器动态流量管理方案 https://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=404151075& ...

  7. nginx/iptables动态IP黑白名单实现方案

    nginx/iptables动态IP黑白名单实现方案 一.手动封IP步骤 1.Nginx手动封IP 1.获取各个IP访问次数 awk '{print $1}' nginx.access.log |so ...

  8. docker:nginx+confd动态生成配置

    docker:nginx+confd动态生成配置 当我们项目越来越多时手动去服务器修改nginx配置是一件很麻烦而且可能出错的事情.我们可以通过nginx+confd+配置中心实现一套方案避免出错并减 ...

  9. Nginx 实现动态负载均衡(Nginx-1.10.1 + Consul v0.6.4)

    一直也没有找到合适的类似Socat + Haproxy 的组合能用在Nginx,后来发现了Nginx的几个模块,但是也存在各种不足. 而且Nginx 在大流量的情况下nginx -s reload 是 ...

随机推荐

  1. ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) 的解决办法

    更换mysql数据目录后出现ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql ...

  2. 解决C/C++语言中全局变量重复定义的问题

    前言 今天,在整理自己的代码的时候,考虑到我写的代码从一至终都是在一个cpp文件里面.于是,想把自己的代码中的各个模块分离开来,以便更好地阅读和管理. 遇到的问题 我的做法是: 宏定义.结构体定义.函 ...

  3. Error updating database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String异常处理

    问题原因:Mybatis中对于时间参数进行比较时的一个BUG. 如果拿传入的时间类型参数与空字符串‘‘进行对比判断则会引发异常.,所以应该去掉该判断, 只保留非空判断就正常了 <if test= ...

  4. JS两种事件的触发方式

    一.入侵式触发方式 <input type="button" id="one" onclick="事件" /> 二.非入侵式触发 ...

  5. [转] Web移动端Fixed布局的解决方案

    移动端业务开发,iOS 下经常会有 fixed 元素和输入框(input 元素)同时存在的情况. 但是 fixed 元素在有软键盘唤起的情况下,会出现许多莫名其妙的问题. 这篇文章里就提供一个简单的有 ...

  6. [转] React 最佳实践——那些 React 没告诉你但很重要的事

    前言:对很多 react 新手来说,网上能找到的资源大都是些简单的 tutorial ,它们能教会你如何使用 react ,但并不会告诉你怎么在实际项目中优雅的组织和编写 react 代码.用谷歌搜中 ...

  7. awk 调用 shell 命令,并传递参数

    from:awk 调用 shell 命令的两种方法:system 与 print shell 向awk传递命令,这样使用即可: awk -v  ...  但反过来呢?awk调用外部命令,同时也传参呢? ...

  8. net mvc cms

    .NET作品集:linux下的.net mvc cms   cms程序架构 本程序是主要是用于企业网站开发的,也可以做博客程序,程序是从之前上一篇的.net 博客程序改进过来的,主要技术由webfor ...

  9. JAVA 图形界面开发基础详解

    与C的win32一样,JAVA也有自己的图形界面开发,将在此篇博客中对基础部分进行讲解. 1.Java提供的图形界面类有哪些? Java提供了两套图形界面 (1)AWT组建(基础) AWT组件是jdk ...

  10. Nmap扫描教程之基础扫描详解

    Nmap扫描教程之基础扫描详解 Nmap扫描基础扫描 当用户对Nmap工具了解后,即可使用该工具实施扫描.通过上一章的介绍,用户可知Nmap工具可以分别对主机.端口.版本.操作系统等实施扫描.但是,在 ...