当使用Nginx 转发请求到AWS ELB(即把ELB的域名作为proxy_pass的upstream)时,由于ELB域名的IP经常变化,会出现Nginx转发请求失败(连接upstream超时)的情况。Nginx 配置样例如下:
location / { proxy_pass http://service-1234567890.us-east-1.elb.amazonaws.com; }
原因在于Nginx解析域名的时机:
Nginx仅在启动的时候,对配置文件中的upstream域名进行解析,并将得到A记录IP地址全部作为upstream,直到下一次加载配置文件时,才会更新域名解析结果。而AWS ELB域名的IP是经常变化的,所以很容易出现转发错误的情况。
其中一个解决方案是付费购买Nginx Plus版本,然后在配置文件 upstream 组配置中,在 server 指令后添加 resolve 标记。
Example:
upstream backend { server service-1234567890.us-east-1.elb.amazonaws.com resolve; }
这样Nginx 就会遵循域名的TTL过期机制,当TTL过期时重新进行域名解析,获得server (AWS ELB)域名更新后IP地址。
另一个免费的方案是按照如下方法进行配置:
resolver 172.16.0.23; set $upstream_endpoint http://service-1234567890.us-east-1.elb.amazonaws.com; location / { proxy_pass $upstream_endpoint; }
即为Nginx 配置一个域名解析器 resolver ,并将 upstream server 配置为一个变量。
这样Nginx 也会遵循域名的TTL过期机制,并在收到请求一个过期的upstream server域名时重新进行域名解析。
这个方法奏效的原因可以在Nginx 官方文档中对 proxy_pass 指令的描述末尾中可以找到:
A server name, its port and the passed URI can also be specified using variables:
proxy_pass http://$host$uri;
or even like this:
proxy_pass $request;
In this case, the server name is searched among the described server groups, and, if not found, is determined using a resolver.
如果 location 不是 / ,proxy_pass 后的URI不同的写法会有不同的结果。
1)假设我们有如下配置:
location /foo/ { proxy_pass http://127.0.0.1:8080; }
当我们请求 /foo/bar/baz 时,Nginx 会转发请求到 http://127.0.0.1:8080/foo/bar/baz 。
2)但如果我们这样配置:
location /foo/ { # Note the trailing slash ↓ proxy_pass http://127.0.0.1:8080/; }
Nginx 会去除在 loation 中指定的路径,再将URI余下的部分转发。则请求 /foo/bar/baz 时,会被转发到 http://127.0.0.1:8080/bar/baz 。
1)假设我们按刚才的解决方案如下进行配置
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 时,Nginx 会转发请求到 / ,而不是 /bar/baz 。
如果想实现通常情况下Nginx 的转发行为,可以在上述配置中去掉upstream末尾的 / ,手工写rewrite 实现:
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 的请求。
没有验证码,会不会出现很多垃圾??
可能吧。。验证码还没搞定,哈哈