代理(proxy),即中间人,它代替客户端发送请求给服务器,收到响应后再转给客户端。一般意义上的代理是从用户的角度讲的,用户经过某个代理能够访问多个网站,这个代理是靠近用户的,好比某些公司可能须要限制员工所访问的网站,就会在网络出口处放置一个代理来作过滤。nginx
反向代理(reverse proxy),本质上跟代理是一回事,只不过是从服务器的角度讲的,是靠近服务器的。好比某个网站有多个服务器,提供一样的功能,通常会在网络入口处放一个代理,接收客户端的请求,再基于某种策略(好比轮转)转发给后端服务器,这样能够提升整个系统的服务能力。nginx 就是一种常见的 HTTP 协议反向代理。git
nginx 中常见的反向代理指令有两个:proxy_pass
和 fastcgi_pass
,前者使用标准的 HTTP 协议转发,后者使用 FastCGI 协议转发,用于 PHP 等架构的环境。在我要说的这个域名问题上,它们行为是同样的,因此下面仅以 proxy_pass
为例。github
一个最简单的反向代理配置以下:后端
server { location / { proxy_pass https://github.com; } }
其做用是将全部请求转发到 github.com。注意此处写的是域名,而非 IP。咱们知道在真正发起请求前,是须要将域名解析成 IP 的,对于 github.com 来讲,在个人环境上它会被解析成两个 IP:192.30.253.112 和 192.30.253.113,TTL 都是 50s,以下图:缓存
那么使用上面这个配置,nginx 是何时作这件事情的呢?答案是启动的时候,只作一次,解析结果会被缓存下来,也就是彻底无视 TTL,后续全部的请求转发,都是直接使用缓存下来的 IP,不会再作任何域名解析。对于 github.com 这种返回多个 IP 的状况,nginx 在转发时会自动对 IP 列表进行轮转。服务器
可使用 sudo tcpdump -n -i any port 53
抓包来验证这个行为。注:53 是 DNS 服务的默认端口。网络
那么问题来了,IP 变了怎么办?有什么办法让 nginx 自动从新解析域名吗?架构
resolver 8.8.8.8; server { location / { set $servers github.com; proxy_pass http://$servers; } }
如上,经过使用变量($servers
)的方式能够强制 nginx 遵照域名解析结果的 TTL,过时后自动从新解析。不过这种写法有个反作用,如此配置后 nginx 不会自动使用系统 /etc/resolve.conf
的配置,此时必须使用 resolver
指令手动给它指定一个 DNS 服务器。tcp
其中 8.8.8.8是谷歌的开源免费DNS,国内的有114.114.114.114.若是是内网域名,须要制定内网的DNS服务器。网站
参看地址:
https://github.com/inetfuture/blog/issues/4
https://www.nginx.com/blog/dns-service-discovery-nginx-plus/