前两天发现一个问题,当使用proxy_pass的时候,发现域名对应IP是缓存的,这样一旦VIP变化之后,就会报错,下面就来详细分析一下这个问题。

一、问题说明
 location = /test {
     internal;
     no_error_pages;
     proxy_pass_request_headers off;
     proxy_pass 'http://www.taobao.com/test/router/rest';
 }

    大家应该知道,这是向http://www.taobao.com/test/router/rest发送请求,其实是向202.108.250.251发送请求

ping www.taobao.com
PING scorpio.danuoyi.tbcache.com (202.108.250.251): 56 data bytes
64 bytes from 202.108.250.251: icmp_seq=0 ttl=54 time=4.324 ms
64 bytes from 202.108.250.251: icmp_seq=1 ttl=54 time=8.320 ms

    如果在服务的过程中突然www.taobao.com对应的IP变化了(这是非常常见的,因为taobao.com对应多个域名),那么NGINX仍然会访问以前的IP202.108.250.251,这是为什么呐?下面咱们就来分析一下。

二、HTTP模块

    打开NGINX的源代码,搜索proxy_pass,发现在文件:src/http/modules/ngx_http_proxy_module.c实现了这个方法

static char *
ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
......
}

    那么,继续往下看

    1、url = &value[1]; //获取url

    2、ngx_memzero(&u, sizeof(ngx_url_t));

    3、plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);

    用gdb分析,发现ngx_http_upstream_add()函数在文件src/http/ngx_http_upstream.c里面。代码如下:

  4682 ngx_http_upstream_srv_conf_t *
  4683 ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
............................................................
- 4692 if (ngx_parse_url(cf->pool, u) != NGX_OK) { 3 4693 if (u->err) { 3 4694 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"%s in upstream \"%V\"", u->err, &u->url); 3 4696 } 3 4698 return NULL; 3 4699 }
.............................................................

 

    4、ngx_parse_url,它实在文件core/ngx_inet.c里面,下面是调用的顺序

  • ngx_parse_url()调用ngx_parse_inet_url()
  • ngx_parse_inet_url()调用ngx_inet_resolve_host()
  • ngx_inet_resolve_host()调用gethostbyname()
  • gethostbyname()函数就是通过域名获取IP的函数
三、问题解决

    未完,待续。。。