nginx upstream 动态域名解析 长链接

1,811 views
Skip to first unread message

杨白冰

unread,
Oct 13, 2015, 11:22:13 PM10/13/15
to openresty
代理服务器nginx A 通过域名代理到后端的服务器B,A是通过http1.1 长链接代理到B中,但是B的域名指向的ip会动态变化。

目前的配置如下:
http{
   resolver xxx.xxx.xxx.xxx valid=30s;
   server{
   location = /xxxx/xxxx
      {
    proxy_http_version 1.1;
    proxy_set_header Connection "keep-alive";
    proxy_connect_timeout 2;
    proxy_send_timeout 2;
    proxy_read_timeout 2;
    }
  }
}

以上配置的问题是,域名指向的动态ip 能够顺利切换,但是 并没有用上长链接。

请问有其他人又类似问题吗?

Yichun Zhang (agentzh)

unread,
Oct 13, 2015, 11:58:05 PM10/13/15
to openresty
Hello!

2015-10-14 11:22 GMT+08:00 杨白冰:
> 代理服务器nginx A 通过域名代理到后端的服务器B,A是通过http1.1 长链接代理到B中,但是B的域名指向的ip会动态变化。
>
> 目前的配置如下:
> http{
> resolver xxx.xxx.xxx.xxx valid=30s;
> server{
> location = /xxxx/xxxx
> {
> proxy_pass http://aaa.aaa.com/xxxx/xxxxxx;
>
[...]
> 以上配置的问题是,域名指向的动态ip 能够顺利切换,但是 并没有用上长链接。
>

在 proxy_pass 中静态指定的域名是在 nginx 启动时使用系统的 resolver
来解析的,而且解析结果一直不会变化。你可以使用 nginx 变量来强制 ngx_proxy 模块总是使用 nginx
自己的(非阻塞的)DNS resolver 来解析这里的域名,比如

set $host "aaa.aaa.com";
proxy_pass http://$host/xxx/xxxxx;

此时,nginx 自己的 resolver 会用来解析这里的域名,解析的结果会缓存在共享内存中,缓存的时间也会遵照你的 DNS
nameserver 返回的 TTL(以及你指定的有效期)。从而实现动态变化。

Regards,
-agentzh

YuanSheng Wang

unread,
Oct 14, 2015, 12:07:22 AM10/14/15
to open...@googlegroups.com
以上配置的问题是,域名指向的动态ip 能够顺利切换,但是 并没有用上长链接。

开启长连接,需要在 upstream 中 配置 keepalive 才可以。下面给个示例配置:

upstream back_center {
        server 127.0.0.1:8866;
        keepalive 50;
}

server {
        root "";
        listen 8877;

        location / { 
            proxy_set_header Host $host;  
            proxy_set_header X-Real-IP $remote_addr;  
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
            proxy_pass http://back_center;  
        }
}





--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html



--

杨白冰

unread,
Oct 14, 2015, 2:49:22 AM10/14/15
to openresty
谢谢!春哥 指导 

在 2015年10月14日星期三 UTC+8上午11:58:05,agentzh写道:

杨白冰

unread,
Oct 14, 2015, 2:50:12 AM10/14/15
to openresty, yuan...@iresty.org
问题是用了upstream 模块,无法动态解析 域名。故在找寻其他办法!

在 2015年10月14日星期三 UTC+8下午12:07:22,YuanSheng Wang写道:

杨白冰

unread,
Oct 14, 2015, 3:05:32 AM10/14/15
to openresty
春哥,可以实现 域名的动态解析(域名指向的ip 发生变化,nginx可以成功代理到新的机器上)
希望请教下 有没有一种方法,可以既能实现ip的动态变化,也能保证 nginx与后端的机器是保持的长链接 (A同B 保持长链接,当域名的指向发生变法,由B变成C后,A同C保持长链接)

请问有没有这种方法!


在 2015年10月14日星期三 UTC+8上午11:58:05,agentzh写道:
Hello!

Yichun Zhang (agentzh)

unread,
Oct 14, 2015, 3:12:11 AM10/14/15
to openresty
Hello!

2015-10-14 15:05 GMT+08:00 杨白冰:
> 春哥,可以实现 域名的动态解析(域名指向的ip 发生变化,nginx可以成功代理到新的机器上)
> 希望请教下 有没有一种方法,可以既能实现ip的动态变化,也能保证 nginx与后端的机器是保持的长链接 (A同B
> 保持长链接,当域名的指向发生变法,由B变成C后,A同C保持长链接)
>
> 请问有没有这种方法!
>

当然有办法。可以通过正确地配置 keepalive_requests 和 keepalive_timeout 指令来实现连接的有限次数和有限时间的复用。

http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests

值得一提的是,在 cosocket 的上下文中,也可以通过 getreusedtimes() 来显式地决定当前连接在使用完以后是通过
setkeepalive() 放回连接池继续复用呢,还是通过 close() 直接关闭。

Regards,
-agentzh
Message has been deleted

Yichun Zhang (agentzh)

unread,
Oct 14, 2015, 8:45:43 AM10/14/15
to openresty
Hello!

2015-10-14 15:39 GMT+08:00 杨白冰:
> 代理到后端的机器,后端的机器中http请求打印出来的日志 $connection 每次都不一样 $connection_requests 都是1
>

也许你的后端机器本身不支持 HTTP keepalive. 可以在 TCP 层面使用抓包工具进行确认。临时启用 nginx 调试日志,对于诊断问题也会很有用。

> 请春哥 给出详细的配置 谢谢!
>

这句话带有命令式的嫌疑,看了很不爽。记得下回在你我谈好价钱之后,你再用这种句式。

Regards,
-agentzh

lhmwzy

unread,
Oct 14, 2015, 10:15:00 PM10/14/15
to open...@googlegroups.com
末尾最好不要加!这个标点,要不,确实让人很不舒服

在 2015年10月14日 下午3:39,杨白冰 <shbaib...@gmail.com>写道:
我验证了下 好像并不能使用长链接!
配置如下:
location = /xxxxx/xxxxxxx
{
keepalive_requests 1000;
keepalive_timeout 15s;
    proxy_http_version 1.1;
    proxy_set_header Connection "keep-alive";
    proxy_connect_timeout 10;
    proxy_send_timeout 10;
    proxy_read_timeout 10;
}

代理到后端的机器,后端的机器中http请求打印出来的日志 $connection 每次都不一样 $connection_requests 都是1

请春哥 给出详细的配置 谢谢!

在 2015年10月14日星期三 UTC+8下午3:12:11,agentzh写道:

--

杨白冰

unread,
Nov 12, 2015, 6:46:46 AM11/12/15
to openresty
关于这个问题,后来找到解决办法了:需要集成 ngx_http_dynamic_upstream_module


谢谢春哥,之前的语气不好,还请春哥见谅。

在 2015年10月14日星期三 UTC+8下午8:45:43,agentzh写道:

Huang ChuanTong

unread,
Nov 12, 2015, 7:39:21 PM11/12/15
to openresty

另一种简单的动态upstream思路,



原理是 upstream保存为变量,并保存在ngx.shared中,再开个内部的url进行动态更新。

此方法在实际生产环境下验证使用过。



在 2015年11月12日星期四 UTC+8下午7:46:46,杨白冰写道:

杨白冰

unread,
Nov 15, 2015, 10:12:25 PM11/15/15
to openresty
谢谢 提供的建议!

在 2015年11月13日星期五 UTC+8上午8:39:21,Huang ChuanTong写道:

Paul Von

unread,
Jan 21, 2016, 10:06:16 AM1/21/16
to openresty

春哥:

     你好,我有点疑问,见原文中的红字

On Wednesday, October 14, 2015 at 11:58:05 AM UTC+8, agentzh wrote:
Hello!

2015-10-14 11:22 GMT+08:00 杨白冰:
> 代理服务器nginx A 通过域名代理到后端的服务器B,A是通过http1.1 长链接代理到B中,但是B的域名指向的ip会动态变化。
>
> 目前的配置如下:
> http{
>    resolver xxx.xxx.xxx.xxx valid=30s;
>    server{
>    location = /xxxx/xxxx
>       {
>     proxy_pass http://aaa.aaa.com/xxxx/xxxxxx;
>
[...]
> 以上配置的问题是,域名指向的动态ip 能够顺利切换,但是 并没有用上长链接。
>

在 proxy_pass 中静态指定的域名是在 nginx 启动时使用系统的 resolver     
 #你这里系统的resolver是操作系统的resolver还是说nginx配置文件里的resolver?

来解析的,而且解析结果一直不会变化。你可以使用 nginx 变量来强制 ngx_proxy 模块总是使用 nginx
自己的(非阻塞的)DNS resolver 来解析这里的域名,比如 
#除了你说的这种场景,利用变量替换url外,nginx的resolver 还有什么用呢?我的理解是nginx在启动或重载时都会用系统的DNS去 
#解析upstream server以及proxy_pass后面的url(这个是阻塞的)。只有当启动或重载时解析的ip访问失败时nginx才 
#使用resolver 后面的dns服务器?其实我问这么多,我对resolver指令理解的不是很深,谢谢春哥解答下 

Yichun Zhang (agentzh)

unread,
Jan 21, 2016, 8:11:31 PM1/21/16
to openresty
Hello!

2016-01-21 7:06 GMT-08:00 Paul Von:
>
> 春哥:
>
> 你好,我有点疑问,见原文中的红字

请尽量不要使用红字,看着伤眼,你只需要确保你的内容没有 > 前缀,我就可以很方便地看到。另外,建议尽量使用纯文本格式。

> 你这里系统的resolver是操作系统的resolver还是说nginx配置文件里的resolver?

我这里说的是操作系统的 resolver,这个总是阻塞的。

>> 来解析的,而且解析结果一直不会变化。你可以使用 nginx 变量来强制 ngx_proxy 模块总是使用 nginx
>> 自己的(非阻塞的)DNS resolver 来解析这里的域名,比如
>>
> 除了你说的这种场景,利用变量替换url外,nginx的resolver 还有什么用呢?我的理解是nginx在启动或重载时都会用系统的DNS去
> 解析upstream server以及proxy_pass后面的url(这个是阻塞的)。只有当启动或重载时解析的ip访问失败时nginx才
> 使用resolver 后面的dns服务器?其实我问这么多,我对resolver指令理解的不是很深,谢谢春哥解答下

NGINX 的 resolver 是非阻塞的,只有当实际处理请求时需要临时解析动态域名时才会调用。当系统 resolver
解析域名失败时,并不会调用 nginx 自身的 resolver.

Regards,
-agentzh

Paul Von

unread,
Jan 21, 2016, 10:40:02 PM1/21/16
to openresty


On Friday, January 22, 2016 at 9:11:31 AM UTC+8, agentzh wrote:
Hello!

2016-01-21 7:06 GMT-08:00 Paul Von:
>
> 春哥:
>
>      你好,我有点疑问,见原文中的红字

请尽量不要使用红字,看着伤眼,你只需要确保你的内容没有 > 前缀,我就可以很方便地看到。另外,建议尽量使用纯文本格式。  
 恩,好的,下次我会注意:)
> 你这里系统的resolver是操作系统的resolver还是说nginx配置文件里的resolver?

我这里说的是操作系统的 resolver,这个总是阻塞的。
这个阻塞nginx可以设置超时么,有时候等的时间有点长? 
>> 来解析的,而且解析结果一直不会变化。你可以使用 nginx 变量来强制 ngx_proxy 模块总是使用 nginx
>> 自己的(非阻塞的)DNS resolver 来解析这里的域名,比如
>>
> 除了你说的这种场景,利用变量替换url外,nginx的resolver 还有什么用呢?我的理解是nginx在启动或重载时都会用系统的DNS去
> 解析upstream server以及proxy_pass后面的url(这个是阻塞的)。只有当启动或重载时解析的ip访问失败时nginx才
> 使用resolver 后面的dns服务器?其实我问这么多,我对resolver指令理解的不是很深,谢谢春哥解答下

NGINX 的 resolver 是非阻塞的,只有当实际处理请求时需要临时解析动态域名时才会调用。当系统 resolver
解析域名失败时,并不会调用 nginx 自身的 resolver.
有点不是很明白『只有当实际处理请求时需要临时解析动态域名时才会调用』,这种时候一般是什么时候?是nginx启动时解析的域名不可用时?还是?
谢谢

paulvon

Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Jan 21, 2016, 11:43:24 PM1/21/16
to openresty
Hello!

2016-01-21 19:40 GMT-08:00 Paul Von:
>> 我这里说的是操作系统的 resolver,这个总是阻塞的。
>
> 这个阻塞nginx可以设置超时么,有时候等的时间有点长?

显然这一般是在操作系统级别上进行设置的,比如 Linux 上面:

http://man7.org/linux/man-pages/man5/resolv.conf.5.html

>
> 有点不是很明白『只有当实际处理请求时需要临时解析动态域名时才会调用』,这种时候一般是什么时候?

比我上面说的在 proxy_pass 里面的域名部分使用 nginx 变量的时候。而 nginx 变量是会每请求变化的。例如

location / {
proxy_pass http://$my_host:$my_port;
}

> 是nginx启动时解析的域名不可用时?还是?

唉,我前面都已经说了 nginx 启动时如果操作系统的域名解析失败了,nginx 也不会再用其自身的 resolver 去重试。

Regards,
-agentzh

Paul Von

unread,
Jan 22, 2016, 4:07:48 AM1/22/16
to openresty
嗯嗯 这下明白了 谢谢春哥这么有耐心解答哈。 有点笨望包涵:)

赵丰

unread,
Jun 21, 2020, 1:31:14 AM6/21/20
to openresty
这个模块可能会解决你的问题
https://github.com/zhaofeng0019/nginx-upstream-dynamic-resolve-servers

在 2015年10月14日星期三 UTC+8上午11:22:13,杨白冰写道:
Reply all
Reply to author
Forward
0 new messages