nginx转发实现过程中的问题总结

问题一:nginx针对后端地址变化的情况,如何保持长连接?

背景

1、转发单台设备的请求量在十几万QPS,如果不保持长连接,性能会非常差

2、转发的后端地址并不是固定的,需要根据请求信息上报给不同的域名

解决方法

使用balancer_by_lua_file的方式,用balancer.set_current_peer动态设置后端地址

解决过程

步骤一:直接采用proxy_pass进行转发,设置proxy相关的长连接参数(不可行)

location = /upload {
    # 长链接配置
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    
    proxy_pass "$scheme://$addr";
}

如上述代码,就是nginx的的一个配置,addr可以在rewrite过程中从请求信息中读取即可。

但实际测试过程中发现,该方式不可行,长连接并没有保持成功。

步骤二:为保持长连接,尝试采用upstream模块,但又发现无法动态配置后端地址

多方咨询,终于了解到,为了与后端保持长连接,需要加入upstream模块并配置keepalive

upstream log_forward_backend {
    server 127.0.0.1:80;
    keepalive 100;
}

但问题又来了,upstream模块中server配置的地址不能用变量,只能为ip,那不同域名的地址如何写到server配置中?想到了以下办法:

1、upstream中的server先放一个默认的,在安装脚本中根据实际地址去替换。

-- 不适用,后端地址固定的。而转发的场景后端地址太多,并且新增地址还需要还需要添加配置后重新reload,不灵活

2、放弃使用upstream,直接用lua库的resty.http去发起请求,用一个client也是可以保持长连接的。

-- resty.http性能会较差,且部分信息无法记录在访问日志中,不便于定位

3、采用balancer的方式,根据请求信息动态设置后端地址

-- 可行。

步骤三:采用balancer_by_lua_file的方式

经过上一步的方案讨论后,最终采用balancer_by_lua_file的方式,就只剩下以下问题需要解决:

  • balancer中只能设置IP,不支持直接设置域名,需要解决DNS解析的问题(下个问题展开阐述)
  • upstream中的一些配置不再生效,比如说一些重试的逻辑需要自己实现。

最终实现的关键代码如下:

1、location模块,proxy_pass到对应的upstream中:

location = /upload {
    # 长链接配置
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    
    proxy_pass "$scheme://forward_backend$path";
}

2、实现log_forward_backend的upstream,用了balancer之后,这里server实际就失效了,可以先写一个假的server:

upstream forward_backend {
    server 127.0.0.1:80;
    balancer_by_lua_file lua/balancer.lua;
    keepalive 100;
}

3、实现balancer.lua,主要是有以下两个配置:

balancer.set_more_tries(1)
balancer.set_current_peer(cur_ip, port)
  • balancer.set_more_tries用于设置重试次数,这里需要用ngx.ctx.tries记录进入balancer.lua的次数,超过设置的重试次数直接给错误响应码
  • balancer.set_current_peer用于设置后端的地址与端口,地址注意一定要是IP。这里是在rewrite阶段,从请求信息中读取出了关键信息, 做了一次DNS解析再设置进去的。

到此,nginx到后端厂商的长连接问题终于解决。

问题二:nginx如何支持DNS解析,解析出多个IP地址如何轮询?

背景

1、采用balancer之后,必须要自己实现DNS解析

2、DNS解析后,可能会有多个IP地址,如果只使用一个IP地址,可靠性会较差

解决过程

步骤一:直接用nginx中http模块中的resolver配置(采用balancer后不可行)

http {
    # DNS域名解析
    resolver    119.29.29.29 223.5.5.5 114.114.114.114 valid=300s;
    resolver_timeout    3s;
}

该方式对proxy_pass中的域名可正常解析,但由于需要保持长连接,用balancer就无法采用该配置。

步骤二:rewrite阶段进行DNS解析查询,并缓存DNS结果到共享内存中。

  • rewrite阶段进行DNS解析查询,并且保存IP列表,权重一样的IP列表每次查询还需打乱,避免一直都置连接列表中的第一个IP地址,对客户服务器造成压力
  • 将查询到的结果设置到ngx.ctx中
  • 请求走到balancer阶段,如果访问当前IP地址失败,重试时则切换到下一个IP地址
  • 此外,DNS解析结果做了一个缓存,放入共享内存多个worker工作中(这里其实放单worker,单进程共享也可以)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值